首頁 > web前端 > js教程 > 如何使用 OpenAI、Vercel AI SDK 和 Ollama 以及 Next.js 建立 AI 助手

如何使用 OpenAI、Vercel AI SDK 和 Ollama 以及 Next.js 建立 AI 助手

DDD
發布: 2024-11-07 03:30:03
原創
815 人瀏覽過

在今天的部落格文章中,我們將使用三種不同的 AI 模型來建構 AI 助理:OpenAI 的 Whisper 和 TTS 以及 Meta 的 Llama 3.1。

在探索人工智慧時,我想嘗試不同的事情並創建一個透過語音工作的人工智慧助理。這種好奇心促使我將 OpenAI 的 Whisper 和 TTS 模型與 Meta 的 Llama 3.1 結合起來,建構了一個語音活化助理。

以下是這些模型如何協同工作:

  • 首先,我們將音訊傳送到 Whisper 模型,該模型會將其從語音轉換為文字。
  • 接下來,我們將該文字傳遞給 Llama 3.1 模型。 Llama 將理解文字並產生回應。
  • 最後,我們將 Llama 的回覆傳送到 TTS 模型,將文字重新轉換為語音。然後我們會將音訊串流回客戶端。

讓我們深入研究並開始建立這個優秀的人工智慧助理!

開始使用

我們將使用不同的工具來建立我們的助手。為了建立我們的客戶端,我們將使用 Next.js。不過,您可以選擇您喜歡的框架。

要使用我們的 OpenAI 模型,我們將使用他們的 TypeScript / JavaScript SDK。要使用此 API,我們需要以下環境變數:OPENAI_API_KEY—

要取得此金鑰,我們需要登入 OpenAI 儀表板並找到 API 金鑰部分。在這裡,我們可以產生一個新的密鑰。

Open AI dashboard inside the API keys section

太棒了。現在,要使用我們的 Llama 3.1 模型,我們將使用 Ollama 和 Vercel AI SDK,並利用名為 ollama-ai-provider 的提供者。

Ollama 將允許我們下載我們喜歡的模型(我們甚至可以使用不同的模型,例如 Phi)並在本地運行它。 Vercel SDK 將促進其在我們的 Next.js 專案中的使用。

要使用Ollama,我們只需下載它並選擇我們喜歡的型號。對於本博文,我們將選擇 Llama 3.1。安裝 Ollama 後,我們可以透過開啟終端機並編寫以下命令來驗證它是否正常運作:

Terminal, with the command ‘ollama run llama3.1’

請注意,我寫了“llama3.1”,因為這是我選擇的模型,但您應該使用您下載的模型。

開始事情

是時候開始設定我們的 Next.js 應用程式了。讓我們從這個指令開始:

npx create-next-app@latest
登入後複製
登入後複製
登入後複製
登入後複製

運行命令後,您將看到一些設定應用程式詳細資訊的提示。讓我們一步一步來:

  • 為您的應用程式命名
  • 啟用應用程式路由器

其他步驟是可選的,完全取決於您。就我而言,我還選擇使用 TypeScript 和 Tailwind CSS。

現在已經完成了,讓我們進入我們的專案並安裝運行模型所需的依賴項:

npx create-next-app@latest
登入後複製
登入後複製
登入後複製
登入後複製

建立我們的客戶端邏輯

現在,我們的目標是錄製我們的聲音,將其發送到後端,然後接收來自後端的語音回應。

為了錄製音頻,我們需要使用客戶端功能,這意味著我們需要使用客戶端元件。在我們的例子中,我們不想將整個頁面轉換為使用客戶端功能並將整個樹放在客戶端包中;相反,我們更願意使用伺服器元件並匯入客戶端元件來逐步增強我們的應用程式。

所以,讓我們建立一個單獨的元件來處理客戶端邏輯。

在我們的應用程式資料夾中,讓我們建立一個元件資料夾,在這裡,我們將建立我們的元件:

npm i ai ollama-ai-provider openai
登入後複製
登入後複製
登入後複製

讓我們繼續初始化我們的元件。我繼續添加了一個帶有一些樣式的按鈕:

app
 ↳components
  ↳audio-recorder.tsx
登入後複製
登入後複製
登入後複製

然後將其匯入到我們的Page Server元件中:

// app/components/audio-recorder.tsx
'use client'
export default function AudioRecorder() {
    function handleClick(){
      console.log('click')
    }

    return (
        <section>
        <button onClick={handleClick}
                    className={`bg-blue-500 text-white px-4 py-2 rounded shadow-md hover:bg-blue-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:ring-offset-white transition duration-300 ease-in-out absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2`}>
                Record voice
            </button>
        </section>
    )
}
登入後複製
登入後複製
登入後複製

現在,如果我們運行我們的應用程序,我們應該看到以下內容:

First look of the app, showing a centered blue button

太棒了!現在,我們的按鈕不執行任何操作,但我們的目標是錄製音訊並將其發送到某個地方;為此,讓我們創建一個包含我們邏輯的鉤子:

// app/page.tsx
import AudioRecorder from '@/app/components/audio-recorder';

export default function Home() {
  return (
      <AudioRecorder />
  );
}
登入後複製
登入後複製
登入後複製

我們將使用兩個 API 來錄製我們的聲音:navigator 和 MediaRecorder。導航器 API 將為我們提供有關用戶媒體設備的信息,例如用戶媒體音頻,而 MediaRecorder 將幫助我們錄製其中的音頻。這就是他們一起玩的方式:

app
 ↳hooks
  ↳useRecordVoice.ts

import { useEffect, useRef, useState } from 'react';

export function useRecordVoice() {
  return {}
}
登入後複製
登入後複製
登入後複製

讓我們逐步解釋這段程式碼。首先,我們建立兩個新狀態。第一個用於追蹤我們何時錄製,第二個用於儲存 MediaRecorder 的實例。

// apps/hooks/useRecordVoice.ts
import { useEffect, useRef, useState } from 'react';

export function useRecordVoice() {
    const [isRecording, setIsRecording] = useState(false);
    const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);

     const startRecording = async () => {
        if(!navigator?.mediaDevices){
            console.error('Media devices not supported');
            return;
        }

        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        const mediaRecorder = new MediaRecorder(stream);
        setIsRecording(true)
        setMediaRecorder(mediaRecorder);
        mediaRecorder.start(0)
    }

    const stopRecording = () =>{
        if(mediaRecorder) {
            setIsRecording(false)
            mediaRecorder.stop();
        }
    }

  return {
    isRecording,
    startRecording,
    stopRecording,
  }
}
登入後複製
登入後複製
登入後複製

然後,我們將建立第一個方法,startRecording。在這裡,我們將擁有開始錄製音訊的邏輯。
我們首先檢查使用者是否有可用的媒體設備,這要歸功於導航器 API,它為我們提供了有關使用者瀏覽器環境的資訊:

如果我們沒有媒體設備來錄製音頻,我們就返回。如果他們這樣做,那麼讓我們使用他們的音訊媒體設備來創建一個串流。

 const [isRecording, setIsRecording] = useState(false);
    const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);
登入後複製
登入後複製

最後,我們繼續建立 MediaRecorder 的實例來錄製此音訊:

npx create-next-app@latest
登入後複製
登入後複製
登入後複製
登入後複製

然後我們需要一個方法來停止我們的錄音,這就是我們的 stopRecording。在這裡,如果存在媒體錄製器,我們將停止錄製。

npm i ai ollama-ai-provider openai
登入後複製
登入後複製
登入後複製

我們正在錄製音頻,但我們不會將其儲存在任何地方。讓我們新增一個新的 useEffect 和 ref 來完成此任務。
我們需要一個新的引用,這就是我們的音訊資料塊的儲存位置。

app
 ↳components
  ↳audio-recorder.tsx
登入後複製
登入後複製
登入後複製

在 useEffect 中,我們將做兩件主要的事情:將這些區塊儲存在我們的 ref 中,當它停止時,我們將創建一個音訊/mp3 類型的新 Blob:

// app/components/audio-recorder.tsx
'use client'
export default function AudioRecorder() {
    function handleClick(){
      console.log('click')
    }

    return (
        <section>
        <button onClick={handleClick}
                    className={`bg-blue-500 text-white px-4 py-2 rounded shadow-md hover:bg-blue-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:ring-offset-white transition duration-300 ease-in-out absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2`}>
                Record voice
            </button>
        </section>
    )
}
登入後複製
登入後複製
登入後複製

是時候將此鉤子與我們的 AudioRecorder 元件連接起來了:

// app/page.tsx
import AudioRecorder from '@/app/components/audio-recorder';

export default function Home() {
  return (
      <AudioRecorder />
  );
}
登入後複製
登入後複製
登入後複製

讓我們看看硬幣的另一面,後端!

設定我們的伺服器端

我們希望在伺服器上使用我們的模型來確保安全並運行得更快。讓我們建立一個新路由並使用 Next.js 中的路由處理程序為其新增一個處理程序。在我們的 App 資料夾中,建立一個「Api」資料夾,其中包含以下路由:

我們希望在伺服器上使用我們的模型來確保安全並運行得更快。讓我們建立一個新路由並使用 Next.js 中的路由處理程序為其新增一個處理程序。在我們的 App 資料夾中,建立一個「Api」資料夾,其中包含以下路由:

app
 ↳hooks
  ↳useRecordVoice.ts

import { useEffect, useRef, useState } from 'react';

export function useRecordVoice() {
  return {}
}
登入後複製
登入後複製
登入後複製

我們的路線稱為「聊天」。在route.ts檔案中,我們將設定我們的處理程序。讓我們從設定 OpenAI SDK 開始。

// apps/hooks/useRecordVoice.ts
import { useEffect, useRef, useState } from 'react';

export function useRecordVoice() {
    const [isRecording, setIsRecording] = useState(false);
    const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);

     const startRecording = async () => {
        if(!navigator?.mediaDevices){
            console.error('Media devices not supported');
            return;
        }

        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        const mediaRecorder = new MediaRecorder(stream);
        setIsRecording(true)
        setMediaRecorder(mediaRecorder);
        mediaRecorder.start(0)
    }

    const stopRecording = () =>{
        if(mediaRecorder) {
            setIsRecording(false)
            mediaRecorder.stop();
        }
    }

  return {
    isRecording,
    startRecording,
    stopRecording,
  }
}
登入後複製
登入後複製
登入後複製

在此路線中,我們將從前端作為 Base64 字串發送音訊。然後,我們將接收它並將其轉換為 Buffer 物件。

 const [isRecording, setIsRecording] = useState(false);
    const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);
登入後複製
登入後複製

是時候使用我們的第一個模型了。我們希望將此音訊轉換為文本,並使用 OpenAI 的 Whisper Speech-To-Text 模型。 Whisper 需要音訊檔案來建立文字。由於我們有一個 Buffer 而不是文件,因此我們將使用他們的“toFile”方法將音頻 Buffer 轉換為音頻文件,如下所示:

// check if they have media devices
if(!navigator?.mediaDevices){
 console.error('Media devices not supported');
 return;
}
// create stream using the audio media device
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
登入後複製

請注意,我們指定了「mp3」。這是 Whisper 模型可以使用的眾多擴充之一。您可以在此處查看支援的擴充功能的完整清單:https://platform.openai.com/docs/api-reference/audio/createTranscription#audio-createtranscription-file

現在我們的文件已準備就緒,讓我們將其傳遞給 Whisper!使用我們的 OpenAI 實例,我們將這樣呼叫我們的模型:

// create an instance passing in the stream as parameter
const mediaRecorder = new MediaRecorder(stream);
// Set this state to true to 
setIsRecording(true)
// Store the instance in the state
setMediaRecorder(mediaRecorder);
// Start recording inmediately
mediaRecorder.start(0)
登入後複製

就是這樣!現在,我們可以繼續下一步:使用 Llama 3.1 來解釋這段文本並給我們一個答案。我們將使用兩種方法。首先,我們將使用“ollama-ai-provider”套件中的“ollama”,它允許我們將此模型與本地運行的 Ollama 一起使用。然後,我們將使用 Vercel AI SDK 中的「generateText」來產生文字。
附註:為了讓我們的 Ollama 在本地運行,我們需要在終端機中編寫以下命令:

npx create-next-app@latest
登入後複製
登入後複製
登入後複製
登入後複製
npm i ai ollama-ai-provider openai
登入後複製
登入後複製
登入後複製

最後,我們有了最後一個模型:來自 OpenAI 的 TTS。我們想用音訊回覆用戶,所以這個模型會非常有幫助。它將把我們的文字變成語音:

app
 ↳components
  ↳audio-recorder.tsx
登入後複製
登入後複製
登入後複製

TTS 模型會將我們的回應轉換為音訊檔案。我們希望將此音訊串流回用戶,如下所示:

// app/components/audio-recorder.tsx
'use client'
export default function AudioRecorder() {
    function handleClick(){
      console.log('click')
    }

    return (
        <section>
        <button onClick={handleClick}
                    className={`bg-blue-500 text-white px-4 py-2 rounded shadow-md hover:bg-blue-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:ring-offset-white transition duration-300 ease-in-out absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2`}>
                Record voice
            </button>
        </section>
    )
}
登入後複製
登入後複製
登入後複製

這就是整個後端程式碼!現在,回到前端完成所有連接。

把它們放在一起

在我們的 useRecordVoice.tsx 掛鉤中,我們建立一個新方法來呼叫我們的 API 端點。此方法還將取回回應並向用戶播放我們從後端串流的音訊。

// app/page.tsx
import AudioRecorder from '@/app/components/audio-recorder';

export default function Home() {
  return (
      <AudioRecorder />
  );
}
登入後複製
登入後複製
登入後複製

太棒了!現在我們已經收到了串流響應,我們需要處理它並向用戶播放音訊。為此,我們將使用 AudioContext API。該 API 允許我們儲存音訊、對其進行解碼並在準備好後向用戶播放:

app
 ↳hooks
  ↳useRecordVoice.ts

import { useEffect, useRef, useState } from 'react';

export function useRecordVoice() {
  return {}
}
登入後複製
登入後複製
登入後複製

就是這樣!現在,用戶應該在其設備上聽到音訊響應。最後,讓我們透過添加一個小的載入指示器來讓我們的應用程式變得更好一點:

// apps/hooks/useRecordVoice.ts
import { useEffect, useRef, useState } from 'react';

export function useRecordVoice() {
    const [isRecording, setIsRecording] = useState(false);
    const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);

     const startRecording = async () => {
        if(!navigator?.mediaDevices){
            console.error('Media devices not supported');
            return;
        }

        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        const mediaRecorder = new MediaRecorder(stream);
        setIsRecording(true)
        setMediaRecorder(mediaRecorder);
        mediaRecorder.start(0)
    }

    const stopRecording = () =>{
        if(mediaRecorder) {
            setIsRecording(false)
            mediaRecorder.stop();
        }
    }

  return {
    isRecording,
    startRecording,
    stopRecording,
  }
}
登入後複製
登入後複製
登入後複製

結論

在這篇文章中,我們了解了組合多個人工智慧模型如何幫助我們實現目標。我們學會了在本地運行 Llama 3.1 等 AI 模型,並在我們的 Next.js 應用程式中使用它們。我們還發現瞭如何將音訊發送到這些模型並流迴響應,將音訊播放回用戶。

這只是使用人工智慧的眾多方式之一——可能性是無限的。人工智慧模型是令人驚嘆的工具,它讓我們能夠創造出曾經難以以如此高的品質實現的東西。感謝您的閱讀;現在,輪到你用 AI 建造一些令人驚嘆的東西了!

您可以在 GitHub 上找到完整的示範:AI Assistant with Whisper TTS and Ollama using Next.js

以上是如何使用 OpenAI、Vercel AI SDK 和 Ollama 以及 Next.js 建立 AI 助手的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板