feat: Add custom headers support
This commit is contained in:
parent
86296c96b6
commit
52f9a2953a
@ -229,6 +229,18 @@
|
|||||||
"label": "Custom Origin URL",
|
"label": "Custom Origin URL",
|
||||||
"placeholder": "Enter Custom Origin URL"
|
"placeholder": "Enter Custom Origin URL"
|
||||||
},
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "Custom Headers",
|
||||||
|
"add": "Add Header",
|
||||||
|
"key": {
|
||||||
|
"label": "Header Key",
|
||||||
|
"placeholder": "Authorization"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "Header Value",
|
||||||
|
"placeholder": "Bearer token"
|
||||||
|
}
|
||||||
|
},
|
||||||
"help": "If you have connection issues with Ollama on Page Assist, you can configure a custom origin URL. To learn more about the configuration, <anchor>click here</anchor>."
|
"help": "If you have connection issues with Ollama on Page Assist, you can configure a custom origin URL. To learn more about the configuration, <anchor>click here</anchor>."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,6 +229,18 @@
|
|||||||
"label": "URL Personalizada",
|
"label": "URL Personalizada",
|
||||||
"placeholder": "Ingresar URL Personalizada"
|
"placeholder": "Ingresar URL Personalizada"
|
||||||
},
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "Encabezados Personalizados",
|
||||||
|
"add": "Agregar Encabezado",
|
||||||
|
"key": {
|
||||||
|
"label": "Clave del Encabezado",
|
||||||
|
"placeholder": "Autorización"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "Valor del Encabezado",
|
||||||
|
"placeholder": "Token Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
"help": "Si tenes problemas de conexión con Ollama en Page Assist, podes configurar una URL de personalizada. Para saber más sobre la configuración, <anchor>click aqui</anchor>."
|
"help": "Si tenes problemas de conexión con Ollama en Page Assist, podes configurar una URL de personalizada. Para saber más sobre la configuración, <anchor>click aqui</anchor>."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,6 +229,18 @@
|
|||||||
"label": "URL d'origine personnalisée",
|
"label": "URL d'origine personnalisée",
|
||||||
"placeholder": "Entrez l'URL d'origine personnalisée"
|
"placeholder": "Entrez l'URL d'origine personnalisée"
|
||||||
},
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "En-têtes Personnalisés",
|
||||||
|
"add": "Ajouter En-tête",
|
||||||
|
"key": {
|
||||||
|
"label": "Clé de l'En-tête",
|
||||||
|
"placeholder": "Autorisation"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "Valeur de l'En-tête",
|
||||||
|
"placeholder": "Jeton Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
"help": "Si vous avez des problèmes de connexion avec OLLAMA sur Page Assist, vous pouvez configurer une URL d'origine personnalisée. Pour en savoir plus sur la configuration, <anchor>cliquez ici</anchor>."
|
"help": "Si vous avez des problèmes de connexion avec OLLAMA sur Page Assist, vous pouvez configurer une URL d'origine personnalisée. Pour en savoir plus sur la configuration, <anchor>cliquez ici</anchor>."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,6 +229,18 @@
|
|||||||
"label": "URL di Origine Personalizzato",
|
"label": "URL di Origine Personalizzato",
|
||||||
"placeholder": "Inserisci URL di Origine Personalizzato"
|
"placeholder": "Inserisci URL di Origine Personalizzato"
|
||||||
},
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "Intestazioni Personalizzate",
|
||||||
|
"add": "Aggiungi Intestazione",
|
||||||
|
"key": {
|
||||||
|
"label": "Chiave dell'Intestazione",
|
||||||
|
"placeholder": "Autorizzazione"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "Valore dell'Intestazione",
|
||||||
|
"placeholder": "Token Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
"help": "Se hai problemi di connessione con Ollama su Page Assist, puoi configurare un URL di origine personalizzato. Per saperne di più sulla configurazione, <anchor>clicca qui</anchor>."
|
"help": "Se hai problemi di connessione con Ollama su Page Assist, puoi configurare un URL di origine personalizzato. Per saperne di più sulla configurazione, <anchor>clicca qui</anchor>."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,6 +232,18 @@
|
|||||||
"label": "カスタムOriginのURL",
|
"label": "カスタムOriginのURL",
|
||||||
"placeholder": "カスタムOriginのURLを入力"
|
"placeholder": "カスタムOriginのURLを入力"
|
||||||
},
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "カスタムヘッダー",
|
||||||
|
"add": "ヘッダーを追加",
|
||||||
|
"key": {
|
||||||
|
"label": "ヘッダーキー",
|
||||||
|
"placeholder": "認証"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "ヘッダー値",
|
||||||
|
"placeholder": "ベアラートークン"
|
||||||
|
}
|
||||||
|
},
|
||||||
"help": "PageAssistでOllamaに接続の問題がある場合は、カスタムOriginのURLを設定できます。設定の詳細については、<anchor>ここをクリック</anchor>してください。"
|
"help": "PageAssistでOllamaに接続の問題がある場合は、カスタムOriginのURLを設定できます。設定の詳細については、<anchor>ここをクリック</anchor>してください。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,6 +232,18 @@
|
|||||||
"label": "Custom Origin URL",
|
"label": "Custom Origin URL",
|
||||||
"placeholder": "Enter Custom Origin URL"
|
"placeholder": "Enter Custom Origin URL"
|
||||||
},
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "കസ്റ്റം തലക്കെട്ടുകൾ",
|
||||||
|
"add": "തലക്കെട്ട് ചേർക്കുക",
|
||||||
|
"key": {
|
||||||
|
"label": "തലക്കെട്ട് കീ",
|
||||||
|
"placeholder": "അധികൃതപെടുത്തൽ"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "തലക്കെട്ട് മൂല്യം",
|
||||||
|
"placeholder": "ബെയറർ ടോക്കൺ"
|
||||||
|
}
|
||||||
|
},
|
||||||
"help": "ഏജ് അസിസ്റ്റന്റിൽ Ollama-യുമായി ബന്ധപ്പെടുമ്പോൾ ബന്ധതടസ്സം ഉണ്ടെങ്കിൽ, നിങ്ങൾക്ക് ഒരു വ്യക്തിഗത അസ്ഥിരത്വം URL കോൺഫിഗർ ചെയ്യാം. കോൺഫിഗറേഷനെക്കുറിച്ച് കൂടുതലറിയാൻ, <anchor>ഇവിടെ ക്ലിക്കുചെയ്യുക</anchor>."
|
"help": "ഏജ് അസിസ്റ്റന്റിൽ Ollama-യുമായി ബന്ധപ്പെടുമ്പോൾ ബന്ധതടസ്സം ഉണ്ടെങ്കിൽ, നിങ്ങൾക്ക് ഒരു വ്യക്തിഗത അസ്ഥിരത്വം URL കോൺഫിഗർ ചെയ്യാം. കോൺഫിഗറേഷനെക്കുറിച്ച് കൂടുതലറിയാൻ, <anchor>ഇവിടെ ക്ലിക്കുചെയ്യുക</anchor>."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,6 +229,18 @@
|
|||||||
"label": "URL de Origem Personalizada",
|
"label": "URL de Origem Personalizada",
|
||||||
"placeholder": "Insira a URL de Origem Personalizada"
|
"placeholder": "Insira a URL de Origem Personalizada"
|
||||||
},
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "Cabeçalhos Personalizados",
|
||||||
|
"add": "Adicionar Cabeçalho",
|
||||||
|
"key": {
|
||||||
|
"label": "Chave do Cabeçalho",
|
||||||
|
"placeholder": "Autorização"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "Valor do Cabeçalho",
|
||||||
|
"placeholder": "Token Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
"help": "Se você tiver problemas de conexão com o Ollama no Page Assist, você pode configurar uma URL de origem personalizada. Para saber mais sobre a configuração, <anchor>clique aqui</anchor>."
|
"help": "Se você tiver problemas de conexão com o Ollama no Page Assist, você pode configurar uma URL de origem personalizada. Para saber mais sobre a configuração, <anchor>clique aqui</anchor>."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,6 +230,18 @@
|
|||||||
"label": "Пользовательский исходный URL",
|
"label": "Пользовательский исходный URL",
|
||||||
"placeholder": "Введите пользовательский исходный URL"
|
"placeholder": "Введите пользовательский исходный URL"
|
||||||
},
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "Пользовательские Заголовки",
|
||||||
|
"add": "Добавить Заголовок",
|
||||||
|
"key": {
|
||||||
|
"label": "Ключ Заголовка",
|
||||||
|
"placeholder": "Авторизация"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "Значение Заголовка",
|
||||||
|
"placeholder": "Токен Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
"help": "Если у вас возникают проблемы с подключением к Ollama на странице помощника, вы можете настроить пользовательский исходный URL. Чтобы узнать больше о конфигурации, <anchor>нажмите здесь</anchor>."
|
"help": "Если у вас возникают проблемы с подключением к Ollama на странице помощника, вы можете настроить пользовательский исходный URL. Чтобы узнать больше о конфигурации, <anchor>нажмите здесь</anchor>."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,6 +234,18 @@
|
|||||||
"label": "自定义来源 URL",
|
"label": "自定义来源 URL",
|
||||||
"placeholder": "输入自定义来源 URL"
|
"placeholder": "输入自定义来源 URL"
|
||||||
},
|
},
|
||||||
|
"headers": {
|
||||||
|
"label": "自定义头部",
|
||||||
|
"add": "添加头部",
|
||||||
|
"key": {
|
||||||
|
"label": "头部键",
|
||||||
|
"placeholder": "授权"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"label": "头部值",
|
||||||
|
"placeholder": "承载令牌"
|
||||||
|
}
|
||||||
|
},
|
||||||
"help": "如果您在 Page Assist 上与 Ollama 有连接问题,您可以配置自定义来源 URL。要了解更多关于配置的信息,<anchor>点击此处</anchor>。"
|
"help": "如果您在 Page Assist 上与 Ollama 有连接问题,您可以配置自定义来源 URL。要了解更多关于配置的信息,<anchor>点击此处</anchor>。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,132 @@
|
|||||||
import { useStorage } from "@plasmohq/storage/hook"
|
import { Divider, Input, Switch } from "antd"
|
||||||
import { Input, Switch } from "antd"
|
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { Form } from "antd"
|
||||||
|
import React from "react"
|
||||||
|
import {
|
||||||
|
customOllamaHeaders,
|
||||||
|
getRewriteUrl,
|
||||||
|
isUrlRewriteEnabled,
|
||||||
|
setCustomOllamaHeaders,
|
||||||
|
setRewriteUrl,
|
||||||
|
setUrlRewriteEnabled
|
||||||
|
} from "@/services/app"
|
||||||
|
import { Trash2Icon } from "lucide-react"
|
||||||
|
import { SaveButton } from "../SaveButton"
|
||||||
|
|
||||||
export const AdvanceOllamaSettings = () => {
|
export const AdvanceOllamaSettings = () => {
|
||||||
const [urlRewriteEnabled, setUrlRewriteEnabled] = useStorage(
|
const [form] = Form.useForm()
|
||||||
"urlRewriteEnabled",
|
const watchUrlRewriteEnabled = Form.useWatch("urlRewriteEnabled", form)
|
||||||
false
|
|
||||||
)
|
const fetchAdvancedData = async () => {
|
||||||
|
const [urlRewriteEnabled, rewriteUrl, headers] = await Promise.all([
|
||||||
|
isUrlRewriteEnabled(),
|
||||||
|
getRewriteUrl(),
|
||||||
|
customOllamaHeaders()
|
||||||
|
])
|
||||||
|
form.setFieldsValue({ urlRewriteEnabled, rewriteUrl, headers })
|
||||||
|
}
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
fetchAdvancedData()
|
||||||
|
}, [])
|
||||||
|
|
||||||
const [rewriteUrl, setRewriteUrl] = useStorage(
|
|
||||||
"rewriteUrl",
|
|
||||||
"http://127.0.0.1:11434"
|
|
||||||
)
|
|
||||||
const { t } = useTranslation("settings")
|
const { t } = useTranslation("settings")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<Form
|
||||||
<div className="flex sm:flex-row flex-col space-y-4 sm:space-y-0 sm:justify-between">
|
onFinish={(e) => {
|
||||||
<span className="text-gray-700 dark:text-neutral-50 ">
|
const headers = e?.headers?.filter(
|
||||||
{t("ollamaSettings.settings.advanced.urlRewriteEnabled.label")}
|
(header: { key: string; value: string }) => header.key && header.value
|
||||||
</span>
|
)
|
||||||
<div>
|
setUrlRewriteEnabled(e.urlRewriteEnabled)
|
||||||
<Switch
|
setRewriteUrl(e.rewriteUrl)
|
||||||
className="mt-4 sm:mt-0"
|
setCustomOllamaHeaders(headers)
|
||||||
checked={urlRewriteEnabled}
|
}}
|
||||||
onChange={(checked) => setUrlRewriteEnabled(checked)}
|
form={form}
|
||||||
/>
|
layout="vertical"
|
||||||
</div>
|
className="space-y-4">
|
||||||
</div>
|
<Form.Item
|
||||||
<div className="flex flex-col space-y-4 sm:space-y-0 sm:justify-between">
|
name="urlRewriteEnabled"
|
||||||
<span className="text-gray-700 dark:text-neutral-50 mb-3">
|
label={t("ollamaSettings.settings.advanced.urlRewriteEnabled.label")}>
|
||||||
{t("ollamaSettings.settings.advanced.rewriteUrl.label")}
|
<Switch />
|
||||||
</span>
|
</Form.Item>
|
||||||
<div>
|
<Form.Item
|
||||||
|
required={watchUrlRewriteEnabled}
|
||||||
|
name="rewriteUrl"
|
||||||
|
label={t("ollamaSettings.settings.advanced.rewriteUrl.label")}>
|
||||||
<Input
|
<Input
|
||||||
|
disabled={!watchUrlRewriteEnabled}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
value={rewriteUrl}
|
|
||||||
disabled={!urlRewriteEnabled}
|
|
||||||
placeholder={t(
|
placeholder={t(
|
||||||
"ollamaSettings.settings.advanced.rewriteUrl.placeholder"
|
"ollamaSettings.settings.advanced.rewriteUrl.placeholder"
|
||||||
)}
|
)}
|
||||||
onChange={(e) => setRewriteUrl(e.target.value)}
|
|
||||||
/>
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.List name="headers">
|
||||||
|
{(fields, { add, remove }) => (
|
||||||
|
<div className="flex flex-col ">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<h3 className="text-md font-semibold">
|
||||||
|
{t("ollamaSettings.settings.advanced.headers.label")}
|
||||||
|
</h3>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="dark:bg-white dark:text-black text-white bg-black p-1.5 text-xs rounded-md"
|
||||||
|
onClick={() => {
|
||||||
|
add()
|
||||||
|
}}>
|
||||||
|
{t("ollamaSettings.settings.advanced.headers.add")}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{fields.map((field, index) => (
|
||||||
|
<div key={field.key} className="flex items-center w-full">
|
||||||
|
<div className="flex-grow flex space-x-4">
|
||||||
|
<Form.Item
|
||||||
|
label={t(
|
||||||
|
"ollamaSettings.settings.advanced.headers.key.label"
|
||||||
|
)}
|
||||||
|
name={[field.name, "key"]}
|
||||||
|
className="flex-1 mb-0">
|
||||||
|
<Input
|
||||||
|
className="w-full"
|
||||||
|
placeholder={t(
|
||||||
|
"ollamaSettings.settings.advanced.headers.key.placeholder"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t(
|
||||||
|
"ollamaSettings.settings.advanced.headers.value.label"
|
||||||
|
)}
|
||||||
|
name={[field.name, "value"]}
|
||||||
|
className="flex-1 mb-0">
|
||||||
|
<Input
|
||||||
|
className="w-full"
|
||||||
|
placeholder={t(
|
||||||
|
"ollamaSettings.settings.advanced.headers.value.placeholder"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
remove(field.name)
|
||||||
|
}}
|
||||||
|
className="shrink-0 ml-2 text-red-500 dark:text-red-400">
|
||||||
|
<Trash2Icon className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Form.List>
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Form.Item className="flex justify-end">
|
||||||
|
<SaveButton btnType="submit" />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,14 @@ export const SettingsOllama = () => {
|
|||||||
className="w-full p-2 border border-gray-300 rounded-md dark:bg-[#262626] dark:text-gray-100"
|
className="w-full p-2 border border-gray-300 rounded-md dark:bg-[#262626] dark:text-gray-100"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex justify-end mb-3">
|
||||||
|
<SaveButton
|
||||||
|
onClick={() => {
|
||||||
|
saveOllamaURL(ollamaURL)
|
||||||
|
}}
|
||||||
|
className="mt-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<Collapse
|
<Collapse
|
||||||
size="small"
|
size="small"
|
||||||
items={[
|
items={[
|
||||||
@ -79,15 +87,6 @@ export const SettingsOllama = () => {
|
|||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
|
||||||
<SaveButton
|
|
||||||
onClick={() => {
|
|
||||||
saveOllamaURL(ollamaURL)
|
|
||||||
}}
|
|
||||||
className="mt-2"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ModelSettings />
|
<ModelSettings />
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Embeddings, EmbeddingsParams } from "@langchain/core/embeddings"
|
import { Embeddings, EmbeddingsParams } from "@langchain/core/embeddings"
|
||||||
import type { StringWithAutocomplete } from "@langchain/core/utils/types"
|
import type { StringWithAutocomplete } from "@langchain/core/utils/types"
|
||||||
import { parseKeepAlive } from "./utils/ollama"
|
import { parseKeepAlive } from "./utils/ollama"
|
||||||
|
import { getCustomOllamaHeaders } from "@/services/app"
|
||||||
|
|
||||||
export interface OllamaInput {
|
export interface OllamaInput {
|
||||||
embeddingOnly?: boolean
|
embeddingOnly?: boolean
|
||||||
@ -213,12 +214,14 @@ export class OllamaEmbeddingsPageAssist extends Embeddings {
|
|||||||
"http://127.0.0.1:"
|
"http://127.0.0.1:"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
const customHeaders = await getCustomOllamaHeaders()
|
||||||
|
|
||||||
const response = await fetch(`${formattedBaseUrl}/api/embeddings`, {
|
const response = await fetch(`${formattedBaseUrl}/api/embeddings`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
...this.headers
|
...this.headers,
|
||||||
|
...customHeaders
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
prompt,
|
prompt,
|
||||||
|
@ -1,184 +1,189 @@
|
|||||||
import { IterableReadableStream } from "@langchain/core/utils/stream";
|
import { IterableReadableStream } from "@langchain/core/utils/stream"
|
||||||
import type { StringWithAutocomplete } from "@langchain/core/utils/types";
|
import type { StringWithAutocomplete } from "@langchain/core/utils/types"
|
||||||
import { BaseLanguageModelCallOptions } from "@langchain/core/language_models/base";
|
import { BaseLanguageModelCallOptions } from "@langchain/core/language_models/base"
|
||||||
|
import { getCustomOllamaHeaders } from "@/services/app"
|
||||||
|
|
||||||
export interface OllamaInput {
|
export interface OllamaInput {
|
||||||
embeddingOnly?: boolean;
|
embeddingOnly?: boolean
|
||||||
f16KV?: boolean;
|
f16KV?: boolean
|
||||||
frequencyPenalty?: number;
|
frequencyPenalty?: number
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>
|
||||||
keepAlive?: any;
|
keepAlive?: any
|
||||||
logitsAll?: boolean;
|
logitsAll?: boolean
|
||||||
lowVram?: boolean;
|
lowVram?: boolean
|
||||||
mainGpu?: number;
|
mainGpu?: number
|
||||||
model?: string;
|
model?: string
|
||||||
baseUrl?: string;
|
baseUrl?: string
|
||||||
mirostat?: number;
|
mirostat?: number
|
||||||
mirostatEta?: number;
|
mirostatEta?: number
|
||||||
mirostatTau?: number;
|
mirostatTau?: number
|
||||||
numBatch?: number;
|
numBatch?: number
|
||||||
numCtx?: number;
|
numCtx?: number
|
||||||
numGpu?: number;
|
numGpu?: number
|
||||||
numGqa?: number;
|
numGqa?: number
|
||||||
numKeep?: number;
|
numKeep?: number
|
||||||
numPredict?: number;
|
numPredict?: number
|
||||||
numThread?: number;
|
numThread?: number
|
||||||
penalizeNewline?: boolean;
|
penalizeNewline?: boolean
|
||||||
presencePenalty?: number;
|
presencePenalty?: number
|
||||||
repeatLastN?: number;
|
repeatLastN?: number
|
||||||
repeatPenalty?: number;
|
repeatPenalty?: number
|
||||||
ropeFrequencyBase?: number;
|
ropeFrequencyBase?: number
|
||||||
ropeFrequencyScale?: number;
|
ropeFrequencyScale?: number
|
||||||
temperature?: number;
|
temperature?: number
|
||||||
stop?: string[];
|
stop?: string[]
|
||||||
tfsZ?: number;
|
tfsZ?: number
|
||||||
topK?: number;
|
topK?: number
|
||||||
topP?: number;
|
topP?: number
|
||||||
typicalP?: number;
|
typicalP?: number
|
||||||
useMLock?: boolean;
|
useMLock?: boolean
|
||||||
useMMap?: boolean;
|
useMMap?: boolean
|
||||||
vocabOnly?: boolean;
|
vocabOnly?: boolean
|
||||||
seed?: number;
|
seed?: number
|
||||||
format?: StringWithAutocomplete<"json">;
|
format?: StringWithAutocomplete<"json">
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OllamaRequestParams {
|
export interface OllamaRequestParams {
|
||||||
model: string;
|
model: string
|
||||||
format?: StringWithAutocomplete<"json">;
|
format?: StringWithAutocomplete<"json">
|
||||||
images?: string[];
|
images?: string[]
|
||||||
options: {
|
options: {
|
||||||
embedding_only?: boolean;
|
embedding_only?: boolean
|
||||||
f16_kv?: boolean;
|
f16_kv?: boolean
|
||||||
frequency_penalty?: number;
|
frequency_penalty?: number
|
||||||
logits_all?: boolean;
|
logits_all?: boolean
|
||||||
low_vram?: boolean;
|
low_vram?: boolean
|
||||||
main_gpu?: number;
|
main_gpu?: number
|
||||||
mirostat?: number;
|
mirostat?: number
|
||||||
mirostat_eta?: number;
|
mirostat_eta?: number
|
||||||
mirostat_tau?: number;
|
mirostat_tau?: number
|
||||||
num_batch?: number;
|
num_batch?: number
|
||||||
num_ctx?: number;
|
num_ctx?: number
|
||||||
num_gpu?: number;
|
num_gpu?: number
|
||||||
num_gqa?: number;
|
num_gqa?: number
|
||||||
num_keep?: number;
|
num_keep?: number
|
||||||
num_thread?: number;
|
num_thread?: number
|
||||||
num_predict?: number;
|
num_predict?: number
|
||||||
penalize_newline?: boolean;
|
penalize_newline?: boolean
|
||||||
presence_penalty?: number;
|
presence_penalty?: number
|
||||||
repeat_last_n?: number;
|
repeat_last_n?: number
|
||||||
repeat_penalty?: number;
|
repeat_penalty?: number
|
||||||
rope_frequency_base?: number;
|
rope_frequency_base?: number
|
||||||
rope_frequency_scale?: number;
|
rope_frequency_scale?: number
|
||||||
temperature?: number;
|
temperature?: number
|
||||||
stop?: string[];
|
stop?: string[]
|
||||||
tfs_z?: number;
|
tfs_z?: number
|
||||||
top_k?: number;
|
top_k?: number
|
||||||
top_p?: number;
|
top_p?: number
|
||||||
typical_p?: number;
|
typical_p?: number
|
||||||
use_mlock?: boolean;
|
use_mlock?: boolean
|
||||||
use_mmap?: boolean;
|
use_mmap?: boolean
|
||||||
vocab_only?: boolean;
|
vocab_only?: boolean
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OllamaMessage = {
|
export type OllamaMessage = {
|
||||||
role: StringWithAutocomplete<"user" | "assistant" | "system">;
|
role: StringWithAutocomplete<"user" | "assistant" | "system">
|
||||||
content: string;
|
content: string
|
||||||
images?: string[];
|
images?: string[]
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface OllamaGenerateRequestParams extends OllamaRequestParams {
|
export interface OllamaGenerateRequestParams extends OllamaRequestParams {
|
||||||
prompt: string;
|
prompt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OllamaChatRequestParams extends OllamaRequestParams {
|
export interface OllamaChatRequestParams extends OllamaRequestParams {
|
||||||
messages: OllamaMessage[];
|
messages: OllamaMessage[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BaseOllamaGenerationChunk = {
|
export type BaseOllamaGenerationChunk = {
|
||||||
model: string;
|
model: string
|
||||||
created_at: string;
|
created_at: string
|
||||||
done: boolean;
|
done: boolean
|
||||||
total_duration?: number;
|
total_duration?: number
|
||||||
load_duration?: number;
|
load_duration?: number
|
||||||
prompt_eval_count?: number;
|
prompt_eval_count?: number
|
||||||
prompt_eval_duration?: number;
|
prompt_eval_duration?: number
|
||||||
eval_count?: number;
|
eval_count?: number
|
||||||
eval_duration?: number;
|
eval_duration?: number
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OllamaGenerationChunk = BaseOllamaGenerationChunk & {
|
export type OllamaGenerationChunk = BaseOllamaGenerationChunk & {
|
||||||
response: string;
|
response: string
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OllamaChatGenerationChunk = BaseOllamaGenerationChunk & {
|
export type OllamaChatGenerationChunk = BaseOllamaGenerationChunk & {
|
||||||
message: OllamaMessage;
|
message: OllamaMessage
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OllamaCallOptions = BaseLanguageModelCallOptions & {
|
export type OllamaCallOptions = BaseLanguageModelCallOptions & {
|
||||||
headers?: Record<string, string>;
|
headers?: Record<string, string>
|
||||||
};
|
}
|
||||||
|
|
||||||
async function* createOllamaStream(
|
async function* createOllamaStream(
|
||||||
url: string,
|
url: string,
|
||||||
params: OllamaRequestParams,
|
params: OllamaRequestParams,
|
||||||
options: OllamaCallOptions
|
options: OllamaCallOptions
|
||||||
) {
|
) {
|
||||||
let formattedUrl = url;
|
let formattedUrl = url
|
||||||
if (formattedUrl.startsWith("http://localhost:")) {
|
if (formattedUrl.startsWith("http://localhost:")) {
|
||||||
// Node 18 has issues with resolving "localhost"
|
// Node 18 has issues with resolving "localhost"
|
||||||
// See https://github.com/node-fetch/node-fetch/issues/1624
|
// See https://github.com/node-fetch/node-fetch/issues/1624
|
||||||
formattedUrl = formattedUrl.replace(
|
formattedUrl = formattedUrl.replace(
|
||||||
"http://localhost:",
|
"http://localhost:",
|
||||||
"http://127.0.0.1:"
|
"http://127.0.0.1:"
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customHeaders = await getCustomOllamaHeaders()
|
||||||
|
|
||||||
const response = await fetch(formattedUrl, {
|
const response = await fetch(formattedUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify(params),
|
body: JSON.stringify(params),
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
...options.headers,
|
...options.headers,
|
||||||
|
...customHeaders
|
||||||
},
|
},
|
||||||
signal: options.signal,
|
signal: options.signal
|
||||||
});
|
})
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
let error;
|
let error
|
||||||
const responseText = await response.text();
|
const responseText = await response.text()
|
||||||
try {
|
try {
|
||||||
const json = JSON.parse(responseText);
|
const json = JSON.parse(responseText)
|
||||||
error = new Error(
|
error = new Error(
|
||||||
`Ollama call failed with status code ${response.status}: ${json.error}`
|
`Ollama call failed with status code ${response.status}: ${json.error}`
|
||||||
);
|
)
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
error = new Error(
|
error = new Error(
|
||||||
`Ollama call failed with status code ${response.status}: ${responseText}`
|
`Ollama call failed with status code ${response.status}: ${responseText}`
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
(error as any).response = response;
|
;(error as any).response = response
|
||||||
throw error;
|
throw error
|
||||||
}
|
}
|
||||||
if (!response.body) {
|
if (!response.body) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Could not begin Ollama stream. Please check the given URL and try again."
|
"Could not begin Ollama stream. Please check the given URL and try again."
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const stream = IterableReadableStream.fromReadableStream(response.body);
|
const stream = IterableReadableStream.fromReadableStream(response.body)
|
||||||
|
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder()
|
||||||
let extra = "";
|
let extra = ""
|
||||||
for await (const chunk of stream) {
|
for await (const chunk of stream) {
|
||||||
const decoded = extra + decoder.decode(chunk);
|
const decoded = extra + decoder.decode(chunk)
|
||||||
const lines = decoded.split("\n");
|
const lines = decoded.split("\n")
|
||||||
extra = lines.pop() || "";
|
extra = lines.pop() || ""
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
try {
|
try {
|
||||||
yield JSON.parse(line);
|
yield JSON.parse(line)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(`Received a non-JSON parseable chunk: ${line}`);
|
console.warn(`Received a non-JSON parseable chunk: ${line}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,7 +194,7 @@ export async function* createOllamaGenerateStream(
|
|||||||
params: OllamaGenerateRequestParams,
|
params: OllamaGenerateRequestParams,
|
||||||
options: OllamaCallOptions
|
options: OllamaCallOptions
|
||||||
): AsyncGenerator<OllamaGenerationChunk> {
|
): AsyncGenerator<OllamaGenerationChunk> {
|
||||||
yield* createOllamaStream(`${baseUrl}/api/generate`, params, options);
|
yield* createOllamaStream(`${baseUrl}/api/generate`, params, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function* createOllamaChatStream(
|
export async function* createOllamaChatStream(
|
||||||
@ -197,10 +202,9 @@ export async function* createOllamaChatStream(
|
|||||||
params: OllamaChatRequestParams,
|
params: OllamaChatRequestParams,
|
||||||
options: OllamaCallOptions
|
options: OllamaCallOptions
|
||||||
): AsyncGenerator<OllamaChatGenerationChunk> {
|
): AsyncGenerator<OllamaChatGenerationChunk> {
|
||||||
yield* createOllamaStream(`${baseUrl}/api/chat`, params, options);
|
yield* createOllamaStream(`${baseUrl}/api/chat`, params, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const parseKeepAlive = (keepAlive: any) => {
|
export const parseKeepAlive = (keepAlive: any) => {
|
||||||
if (keepAlive === "-1") {
|
if (keepAlive === "-1") {
|
||||||
return -1
|
return -1
|
||||||
|
@ -5,10 +5,10 @@ const DEFAULT_URL_REWRITE_URL = "http://127.0.0.1:11434"
|
|||||||
|
|
||||||
export const isUrlRewriteEnabled = async () => {
|
export const isUrlRewriteEnabled = async () => {
|
||||||
const enabled = await storage.get<boolean | undefined>("urlRewriteEnabled")
|
const enabled = await storage.get<boolean | undefined>("urlRewriteEnabled")
|
||||||
return enabled
|
return enabled ?? false
|
||||||
}
|
}
|
||||||
export const setUrlRewriteEnabled = async (enabled: boolean) => {
|
export const setUrlRewriteEnabled = async (enabled: boolean) => {
|
||||||
await storage.set("urlRewriteEnabled", enabled ? "true" : "false")
|
await storage.set("urlRewriteEnabled", enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getRewriteUrl = async () => {
|
export const getRewriteUrl = async () => {
|
||||||
@ -35,12 +35,10 @@ export const getAdvancedOllamaSettings = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const copilotResumeLastChat = async () => {
|
export const copilotResumeLastChat = async () => {
|
||||||
return await storage.get<boolean>("copilotResumeLastChat")
|
return await storage.get<boolean>("copilotResumeLastChat")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const defaultSidebarOpen = async () => {
|
export const defaultSidebarOpen = async () => {
|
||||||
const sidebarOpen = await storage.get("sidebarOpen")
|
const sidebarOpen = await storage.get("sidebarOpen")
|
||||||
if (!sidebarOpen || sidebarOpen === "") {
|
if (!sidebarOpen || sidebarOpen === "") {
|
||||||
@ -49,7 +47,36 @@ export const defaultSidebarOpen = async () => {
|
|||||||
return sidebarOpen
|
return sidebarOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const setSidebarOpen = async (sidebarOpen: string) => {
|
export const setSidebarOpen = async (sidebarOpen: string) => {
|
||||||
await storage.set("sidebarOpen", sidebarOpen)
|
await storage.set("sidebarOpen", sidebarOpen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const customOllamaHeaders = async (): Promise<
|
||||||
|
{ key: string; value: string }[]
|
||||||
|
> => {
|
||||||
|
const headers = await storage.get<
|
||||||
|
{ key: string; value: string }[] | undefined
|
||||||
|
>("customOllamaHeaders")
|
||||||
|
if (!headers) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
|
export const setCustomOllamaHeaders = async (headers: string[]) => {
|
||||||
|
await storage.set("customOllamaHeaders", headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getCustomOllamaHeaders = async (): Promise<
|
||||||
|
Record<string, string>
|
||||||
|
> => {
|
||||||
|
const headers = await customOllamaHeaders()
|
||||||
|
|
||||||
|
const headerMap: Record<string, string> = {}
|
||||||
|
|
||||||
|
for (const header of headers) {
|
||||||
|
headerMap[header.key] = header.value
|
||||||
|
}
|
||||||
|
|
||||||
|
return headerMap
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user