Skip to content

Commit

Permalink
feat: added Azure OpenAI support
Browse files Browse the repository at this point in the history
  • Loading branch information
Markus Kiss committed Dec 12, 2024
1 parent 92671b7 commit 6ac1c20
Show file tree
Hide file tree
Showing 17 changed files with 254 additions and 6 deletions.
3 changes: 3 additions & 0 deletions public/locales/ar/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
"api-endpoint": "نقطة نهاية API",
"must-start-with-http-s-or-use-api-openai-as-default": "يجب أن يبدأ بـ ://http(s) أو استخدام /api/openai كإعداد افتراضي",
"user-custom-openai-api-key": "مفتاح واجهة برمجة التطبيقات المخصص للمستخدم من OpenAI",
"user-custom-azureopenai-api-instance": "اسم مثيل Azure OpenAI",
"user-custom-azureopenai-api-deployment": "اسم نشر Azure OpenAI",
"user-custom-azureopenai-api-version": "نسخة API",
"ai-model": "نموذج الذكاء الاصطناعي",
"logout": "تسجيل الخروج",
"user-or-password-error": "خطأ في اسم المستخدم أو كلمة المرور",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@
"upload-file": "Datei hochladen",
"use-ai": "Ai verwenden",
"user-custom-openai-api-key": "Benutzerdefinierter OpenAI Api-Schlüssel",
"user-custom-azureopenai-api-instance": "Azure OpenAI Instanzname",
"user-custom-azureopenai-api-deployment": "Azure OpenAI Bereitstellungsname",
"user-custom-azureopenai-api-version": "API version",
"user-or-password-error": "Benutzer- oder Passwortfehler",
"username": "Nutzername",
"your-changes-have-been-saved": "Ihre Änderungen wurden gespeichert!",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
"api-endpoint": "API Endpoint",
"must-start-with-http-s-or-use-api-openai-as-default": "Must start with http(s):// or use /api/openai as default",
"user-custom-openai-api-key": "User custom OpenAI Api Key",
"user-custom-azureopenai-api-instance": "Azure OpenAI instance name",
"user-custom-azureopenai-api-deployment": "Azure OpenAI deployment name",
"user-custom-azureopenai-api-version": "API version",
"ai-model": "AI Model",
"logout": "Logout",
"user-or-password-error": "User or password error",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@
"upload-file": "Cargar archivo",
"use-ai": "Utilizar ai",
"user-custom-openai-api-key": "Clave Api OpenAI personalizada por el usuario",
"user-custom-azureopenai-api-instance": "Nombre de la instancia de Azure OpenAI",
"user-custom-azureopenai-api-deployment": "Nombre de implementación de Azure OpenAI",
"user-custom-azureopenai-api-version": "Versión API",
"username": "nombre de usuario",
"your-changes-have-been-saved": "Tus cambios se han guardado.",
"all-notes-have-been-loaded": "Todas las notas {{items}} han sido cargadas",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@
"upload-file": "Télécharger le fichier",
"use-ai": "Utiliser l'ai",
"user-custom-openai-api-key": "Clé Api OpenAI personnalisée par l'utilisateur",
"user-custom-azureopenai-api-instance": "Nom de l'instance Azure OpenAI",
"user-custom-azureopenai-api-deployment": "Nom du déploiement Azure OpenAI",
"user-custom-azureopenai-api-version": "Version API",
"user-or-password-error": "Erreur d'utilisateur ou de mot de passe",
"username": "Nom d'utilisateur",
"backup-file": "FICHIER DE SAUVEGARDE",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/ja/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
"upload-file": "ファイルのアップロード",
"use-ai": "aiを使う",
"user-custom-openai-api-key": "ユーザー独自のOpenAI APIキー",
"user-custom-azureopenai-api-instance": "Azure OpenAI インスタンス名",
"user-custom-azureopenai-api-deployment": "Azure OpenAI デプロイ名",
"user-custom-azureopenai-api-version": "APIバージョン",
"edit": "編集",
"enter-your-password": "パスワードを入力してください",
"import-from-bko": ".bkoからのインポート",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/ko/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
"update-successfully": "업데이트 성공",
"use-ai": "AI 사용",
"user-custom-openai-api-key": "사용자 지정 OpenAI API 키",
"user-custom-azureopenai-api-instance": "Azure OpenAI 인스턴스 이름",
"user-custom-azureopenai-api-deployment": "Azure OpenAI 배포 이름",
"user-custom-azureopenai-api-version": "API 버전",
"user-or-password-error": "사용자 또는 비밀번호 오류",
"username": "사용자 이름",
"api-endpoint": "API 엔드포인트",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/pt/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
"upload-file": "Carregar ficheiro",
"use-ai": "Utilizar ai",
"user-custom-openai-api-key": "Chave de Api OpenAI personalizada pelo utilizador",
"user-custom-azureopenai-api-instance": "Nome da instância do Azure OpenAI",
"user-custom-azureopenai-api-deployment": "Nome da implantação do Azure OpenAI",
"user-custom-azureopenai-api-version": "Versão da API",
"user-or-password-error": "Erro de utilizador ou de palavra-passe",
"username": "nome de utilizador",
"your-changes-have-been-saved": "As suas alterações foram guardadas!",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/ru/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@
"upload-file": "Загрузить файл",
"use-ai": "Включить AI",
"user-custom-openai-api-key": "Пользовательский ключ OpenAI Api Key",
"user-custom-azureopenai-api-instance": "Имя экземпляра Azure OpenAI",
"user-custom-azureopenai-api-deployment": "Имя развертывания Azure OpenAI",
"user-custom-azureopenai-api-version": "Версия API",
"user-or-password-error": "Ошибка пользователя или пароля",
"username": "имя пользователя",
"your-changes-have-been-saved": "Ваши данные сохранены!",
Expand Down
10 changes: 6 additions & 4 deletions public/locales/tr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@
"keep-sign-in": "Oturum açmaya devam et",
"language": "Dil",
"last-run": "SON KOŞU",
"logout": "Oturumu Kapat"
}
"delete-success": "Başarıyla silindi",
"logout": "Oturumu Kapat",
"delete-success": "Başarıyla silindi",
"enter-your-username": "Kullanıcı adınızı girin",
"every-day": "Her gün"
"every-day": "Her gün",
"user-custom-azureopenai-api-instance": "Azure OpenAI örnek adı",
"user-custom-azureopenai-api-deployment": "Azure OpenAI dağıtım adı",
"user-custom-azureopenai-api-version": "API sürümü"
}
3 changes: 3 additions & 0 deletions public/locales/zh-TW/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
"api-endpoint": "接口地址",
"must-start-with-http-s-or-use-api-openai-as-default": "必須以 http(s):// 開頭,或默認使用 /api/openai",
"user-custom-openai-api-key": "用戶自定義 OpenAI Api 密鑰",
"user-custom-azureopenai-api-instance": "Azure OpenAI 虛擬實例名稱",
"user-custom-azureopenai-api-deployment": "Azure OpenAI 部署名稱",
"user-custom-azureopenai-api-version": "API 版本",
"ai-model": "人工智能模型",
"logout": "註銷",
"user-or-password-error": "用戶或密碼錯誤",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/zh/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
"api-endpoint": "接口地址",
"must-start-with-http-s-or-use-api-openai-as-default": "必须以 http(s):// 开头,或默认使用 /api/openai",
"user-custom-openai-api-key": "用户自定义 OpenAI Api 密钥",
"user-custom-azureopenai-api-instance": "Azure OpenAI 虛擬實例名稱",
"user-custom-azureopenai-api-deployment": "Azure OpenAI 部署名稱",
"user-custom-azureopenai-api-version": "API 版本",
"ai-model": "人工智能模型",
"logout": "注销",
"user-or-password-error": "用户或密码错误",
Expand Down
114 changes: 112 additions & 2 deletions src/components/BlinkoSettings/AiSetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ export const AiSetting = observer(() => {
const store = RootStore.Local(() => ({
isVisible: false,
apiKey: '',
apiVersion: '',
apiEndPoint: '',
aiModel: '',
aiModel: '',
embeddingModel: '',
embeddingTopK: 2,
embeddingScore: 1.5,
Expand All @@ -33,6 +34,7 @@ export const AiSetting = observer(() => {
}))
useEffect(() => {
store.apiEndPoint = blinko.config.value?.aiApiEndpoint!
store.apiVersion = blinko.config.value?.aiApiVersion!
store.apiKey = blinko.config.value?.aiApiKey!
store.aiModel = blinko.config.value?.aiModel!
store.embeddingModel = blinko.config.value?.embeddingModel!
Expand Down Expand Up @@ -286,6 +288,58 @@ export const AiSetting = observer(() => {
)
}

{
blinko.config.value?.aiModelProvider == 'AzureOpenAI' &&
<Item
type={isPc ? 'row' : 'col'}
leftContent={<div className="flex flex-col ga-1">
<>{t('user-custom-azureopenai-api-instance')}</>
</div>}
rightContent={
<Input
size='sm'
variant="bordered"
className="w-full md:w-[300px]"
placeholder="Enter instance name"
value={store.apiEndPoint}
onChange={e => { store.apiEndPoint = e.target.value }}
onBlur={e => {
PromiseCall(api.config.update.mutate({
key: 'aiApiEndpoint',
value: store.apiEndPoint
}))
}}
type="text"
/>
} />
}

{
blinko.config.value?.aiModelProvider == 'AzureOpenAI' &&
<Item
type={isPc ? 'row' : 'col'}
leftContent={<div className="flex flex-col ga-1">
<>{t('user-custom-azureopenai-api-deployment')}</>
</div>}
rightContent={
<Input
size='sm'
variant="bordered"
className="w-full md:w-[300px]"
placeholder="Enter deployment name"
value={store.aiModel}
onChange={e => { store.aiModel = e.target.value }}
onBlur={e => {
PromiseCall(api.config.update.mutate({
key: 'aiModel',
value: store.aiModel
}))
}}
type="text"
/>
} />
}

{
blinko.config.value?.aiModelProvider != 'Ollama' &&
<Item
Expand Down Expand Up @@ -323,7 +377,62 @@ export const AiSetting = observer(() => {
} />
}

< Item
{
blinko.config.value?.aiModelProvider == 'AzureOpenAI' &&
<Item
type={isPc ? 'row' : 'col'}
leftContent={<div className="flex flex-col ga-1">
<>{t('user-custom-azureopenai-api-version')}</>
</div>}
rightContent={
<Input
size='sm'
variant="bordered"
className="w-full md:w-[300px]"
placeholder="Enter API version"
value={store.apiVersion}
onChange={e => { store.apiVersion = e.target.value }}
onBlur={e => {
PromiseCall(api.config.update.mutate({
key: 'aiApiVersion',
value: store.apiVersion
}))
}}
type="text"
/>
} />
}

{
blinko.config.value?.aiModelProvider == 'AzureOpenAI' &&
<Item
type={isPc ? 'row' : 'col'}
leftContent={<div className="flex flex-col ga-1">
<>{t('embedding-model')}</>
<div className="text-desc text-xs">{t('embedding-model-description')}</div>
</div>}
rightContent={
<Input
size='sm'
variant="bordered"
className="w-full md:w-[300px]"
placeholder="Enter deployment name"
value={store.embeddingModel}
onChange={e => { store.embeddingModel = e.target.value }}
onBlur={e => {
PromiseCall(api.config.update.mutate({
key: 'embeddingModel',
value: store.embeddingModel
}))
}}
type="text"
/>
} />
}

{
blinko.config.value?.aiModelProvider != 'AzureOpenAI' &&
<Item
type={isPc ? 'row' : 'col'}
leftContent={< div className="flex flex-col gap-1" >
<>{t('api-endpoint')}</>
Expand All @@ -344,6 +453,7 @@ export const AiSetting = observer(() => {
}))
}}
/>} />
}

<Item
type={isPc ? 'row' : 'col'}
Expand Down
12 changes: 12 additions & 0 deletions src/server/plugins/ai/aiModelFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { MarkdownTextSplitter, TokenTextSplitter } from "@langchain/textsplitter
import { FaissStore } from "@langchain/community/vectorstores/faiss"
import { BaseChatModel } from "@langchain/core/language_models/chat_models"
import { Embeddings } from "@langchain/core/embeddings"
import { AzureOpenAIModelProvider } from "./azureOpenAIModelProvider"
import { OpenAIModelProvider } from "./openAIModelProvider"
import { getGlobalConfig } from "@/server/routers/config"
import { OllamaModelProvider } from "./ollamaModelProvider"
Expand Down Expand Up @@ -35,6 +36,17 @@ export class AiModelFactory {
}
}

if (globalConfig.aiModelProvider == 'AzureOpenAI') {
const provider = new AzureOpenAIModelProvider({ globalConfig });
return {
LLM: provider.LLM(),
VectorStore: await provider.VectorStore(),
Embeddings: provider.Embeddings(),
MarkdownSplitter: provider.MarkdownSplitter(),
TokenTextSplitter: provider.TokenTextSplitter(),
};
}

if (globalConfig.aiModelProvider == 'Ollama') {
const provider = new OllamaModelProvider({ globalConfig })
return {
Expand Down
84 changes: 84 additions & 0 deletions src/server/plugins/ai/azureOpenAIModelProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { AzureChatOpenAI, AzureOpenAIEmbeddings } from '@langchain/openai'
import { MarkdownTextSplitter, TokenTextSplitter } from '@langchain/textsplitters'
import { FaissStore } from '@langchain/community/vectorstores/faiss'
import path from 'path'
import { FAISS_PATH } from '@/lib/constant'
import { BaseChatModel } from '@langchain/core/language_models/chat_models'
import { Embeddings } from '@langchain/core/embeddings'
import { GlobalConfig } from '@/server/types'
import { BufferLoader } from 'langchain/document_loaders/fs/buffer'

export abstract class AiBaseModelPrivider {
globalConfig: GlobalConfig

constructor({ globalConfig }) {
this.globalConfig = globalConfig
}

abstract LLM(): BaseChatModel
abstract Embeddings(): Embeddings

public MarkdownSplitter(): MarkdownTextSplitter {
return new MarkdownTextSplitter({
chunkSize: 2000,
chunkOverlap: 200,
})
}

public TokenTextSplitter(): TokenTextSplitter {
return new TokenTextSplitter({
chunkSize: 2000,
chunkOverlap: 200,
})
}

public async VectorStore(): Promise<FaissStore> {
const FaissStorePath = path.join(process.cwd(), FAISS_PATH)
try {
return await FaissStore.load(FaissStorePath, this.Embeddings())
} catch (error) {
try {
console.log(this.globalConfig)
const VectorStore = new FaissStore(this.Embeddings(), {})
const documents = [
{
pageContent: 'init faiss store',
metadata: { id: '0' },
},
]
console.log('init faiss store', documents)
await VectorStore.addDocuments(documents, { ids: ['0'] })
await VectorStore.save(FaissStorePath)
return VectorStore
} catch (error) {
console.log('VectorStore error', error)
throw error
}
}
}

public AudioLoader(audioPath): BufferLoader {
return null as unknown as BufferLoader
}
}

export class AzureOpenAIModelProvider extends AiBaseModelPrivider {
LLM() {
return new AzureChatOpenAI({
azureOpenAIApiInstanceName: this.globalConfig.aiApiEndpoint,
deploymentName: this.globalConfig.aiModel,
openAIApiKey: this.globalConfig.aiApiKey,
openAIApiVersion: this.globalConfig.aiApiVersion,
temperature: 0
})
}

Embeddings() {
return new AzureOpenAIEmbeddings({
azureOpenAIApiInstanceName: this.globalConfig.aiApiEndpoint,
apiKey: this.globalConfig.aiApiKey,
deploymentName: this.globalConfig.embeddingModel,
openAIApiVersion: this.globalConfig.aiApiVersion
})
}
}
Loading

0 comments on commit 6ac1c20

Please sign in to comment.