@lobehub/chat 0.126.5 → 0.127.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/.env.example +8 -0
  2. package/CHANGELOG.md +25 -0
  3. package/Dockerfile +3 -0
  4. package/docs/Deployment/Environment-Variable.md +10 -0
  5. package/docs/Deployment/Environment-Variable.zh-CN.md +10 -0
  6. package/locales/ar/common.json +1 -0
  7. package/locales/ar/error.json +2 -0
  8. package/locales/ar/setting.json +16 -0
  9. package/locales/de-DE/common.json +1 -0
  10. package/locales/de-DE/error.json +2 -0
  11. package/locales/de-DE/setting.json +16 -0
  12. package/locales/en-US/common.json +1 -0
  13. package/locales/en-US/error.json +2 -0
  14. package/locales/en-US/setting.json +16 -0
  15. package/locales/es-ES/common.json +1 -0
  16. package/locales/es-ES/error.json +2 -0
  17. package/locales/es-ES/setting.json +16 -0
  18. package/locales/fr-FR/common.json +1 -0
  19. package/locales/fr-FR/error.json +2 -0
  20. package/locales/fr-FR/setting.json +16 -0
  21. package/locales/it-IT/common.json +1 -0
  22. package/locales/it-IT/error.json +2 -0
  23. package/locales/it-IT/setting.json +16 -0
  24. package/locales/ja-JP/common.json +1 -0
  25. package/locales/ja-JP/error.json +2 -0
  26. package/locales/ja-JP/setting.json +16 -0
  27. package/locales/ko-KR/common.json +1 -0
  28. package/locales/ko-KR/error.json +2 -0
  29. package/locales/ko-KR/setting.json +16 -0
  30. package/locales/nl-NL/common.json +1 -0
  31. package/locales/nl-NL/error.json +2 -0
  32. package/locales/nl-NL/setting.json +16 -0
  33. package/locales/pl-PL/common.json +1 -0
  34. package/locales/pl-PL/error.json +2 -0
  35. package/locales/pl-PL/setting.json +16 -0
  36. package/locales/pt-BR/common.json +1 -0
  37. package/locales/pt-BR/error.json +2 -0
  38. package/locales/pt-BR/setting.json +16 -0
  39. package/locales/ru-RU/common.json +1 -0
  40. package/locales/ru-RU/error.json +2 -0
  41. package/locales/ru-RU/setting.json +16 -0
  42. package/locales/tr-TR/common.json +1 -0
  43. package/locales/tr-TR/error.json +2 -0
  44. package/locales/tr-TR/setting.json +16 -0
  45. package/locales/vi-VN/common.json +1 -0
  46. package/locales/vi-VN/error.json +2 -0
  47. package/locales/vi-VN/setting.json +16 -0
  48. package/locales/zh-CN/common.json +1 -0
  49. package/locales/zh-CN/error.json +2 -0
  50. package/locales/zh-CN/setting.json +16 -0
  51. package/locales/zh-TW/common.json +1 -0
  52. package/locales/zh-TW/error.json +2 -0
  53. package/locales/zh-TW/setting.json +16 -0
  54. package/package.json +1 -1
  55. package/src/app/api/chat/[provider]/agentRuntime.ts +14 -0
  56. package/src/app/api/config/route.ts +2 -0
  57. package/src/app/api/errorResponse.ts +3 -0
  58. package/src/app/settings/llm/Ollama/index.tsx +81 -0
  59. package/src/app/settings/llm/page.tsx +7 -0
  60. package/src/components/ModelProviderIcon/index.tsx +5 -1
  61. package/src/config/modelProviders/index.ts +3 -0
  62. package/src/config/modelProviders/ollama.ts +117 -0
  63. package/src/config/server/provider.ts +6 -0
  64. package/src/const/settings.ts +4 -0
  65. package/src/libs/agent-runtime/error.ts +3 -0
  66. package/src/libs/agent-runtime/index.ts +1 -0
  67. package/src/libs/agent-runtime/ollama/index.ts +80 -0
  68. package/src/libs/agent-runtime/types/type.ts +1 -0
  69. package/src/locales/default/common.ts +1 -0
  70. package/src/locales/default/error.ts +3 -0
  71. package/src/locales/default/setting.ts +16 -0
  72. package/src/services/_auth.ts +8 -0
  73. package/src/store/global/slices/settings/selectors/modelProvider.ts +24 -2
  74. package/src/types/settings/modelProvider.ts +7 -0
@@ -0,0 +1,80 @@
1
+ import { OpenAIStream, StreamingTextResponse } from 'ai';
2
+ import OpenAI from 'openai';
3
+
4
+ import { LobeRuntimeAI } from '../BaseAI';
5
+ import { AgentRuntimeErrorType } from '../error';
6
+ import { ChatStreamPayload, ModelProvider } from '../types';
7
+ import { AgentRuntimeError } from '../utils/createError';
8
+ import { debugStream } from '../utils/debugStream';
9
+ import { desensitizeUrl } from '../utils/desensitizeUrl';
10
+ import { DEBUG_CHAT_COMPLETION } from '../utils/env';
11
+ import { handleOpenAIError } from '../utils/handleOpenAIError';
12
+
13
+ const DEFAULT_BASE_URL = 'http://127.0.0.1:11434/v1';
14
+
15
+ export class LobeOllamaAI implements LobeRuntimeAI {
16
+ private _llm: OpenAI;
17
+
18
+ baseURL: string;
19
+
20
+ constructor(baseURL: string = DEFAULT_BASE_URL) {
21
+ if (!baseURL) throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidOllamaArgs);
22
+
23
+ this._llm = new OpenAI({ apiKey: 'ollama', baseURL });
24
+ this.baseURL = baseURL;
25
+ }
26
+
27
+ async chat(payload: ChatStreamPayload) {
28
+ try {
29
+ const response = await this._llm.chat.completions.create(
30
+ payload as unknown as OpenAI.ChatCompletionCreateParamsStreaming,
31
+ );
32
+
33
+ const stream = OpenAIStream(response);
34
+
35
+ const [debug, returnStream] = stream.tee();
36
+
37
+ if (DEBUG_CHAT_COMPLETION) {
38
+ debugStream(debug).catch(console.error);
39
+ }
40
+
41
+ return new StreamingTextResponse(returnStream);
42
+ } catch (error) {
43
+ let desensitizedEndpoint = this.baseURL;
44
+
45
+ if (this.baseURL !== DEFAULT_BASE_URL) {
46
+ desensitizedEndpoint = desensitizeUrl(this.baseURL);
47
+ }
48
+
49
+ if ('status' in (error as any)) {
50
+ switch ((error as Response).status) {
51
+ case 401: {
52
+ throw AgentRuntimeError.chat({
53
+ endpoint: desensitizedEndpoint,
54
+ error: error as any,
55
+ errorType: AgentRuntimeErrorType.InvalidOllamaArgs,
56
+ provider: ModelProvider.Ollama,
57
+ });
58
+ }
59
+
60
+ default: {
61
+ break;
62
+ }
63
+ }
64
+ }
65
+
66
+ const { errorResult, RuntimeError } = handleOpenAIError(error);
67
+
68
+ const errorType = RuntimeError || AgentRuntimeErrorType.OllamaBizError;
69
+
70
+ throw AgentRuntimeError.chat({
71
+ endpoint: desensitizedEndpoint,
72
+ error: errorResult,
73
+ errorType,
74
+ provider: ModelProvider.Ollama,
75
+ });
76
+ }
77
+ }
78
+ }
79
+
80
+ export default LobeOllamaAI;
@@ -29,6 +29,7 @@ export enum ModelProvider {
29
29
  Google = 'google',
30
30
  Mistral = 'mistral',
31
31
  Moonshot = 'moonshot',
32
+ Ollama = 'ollama',
32
33
  OpenAI = 'openai',
33
34
  Tongyi = 'tongyi',
34
35
  ZhiPu = 'zhipu',
@@ -103,6 +103,7 @@ export default {
103
103
  bedrock: 'AWS Bedrock',
104
104
  google: 'Google',
105
105
  moonshot: 'Moonshot AI',
106
+ ollama: 'Ollama',
106
107
  oneapi: 'One API',
107
108
  openai: 'OpenAI',
108
109
  zhipu: '智谱AI',
@@ -73,6 +73,9 @@ export default {
73
73
  InvalidAzureAPIKey: 'Azure API Key 不正确或为空,请检查 Azure API Key 后重试',
74
74
  AzureBizError: '请求 Azure AI 服务出错,请根据以下信息排查或重试',
75
75
 
76
+ InvalidOllamaArgs: 'Ollama 配置不正确,请检查 Ollama 配置后重试',
77
+ OllamaBizError: '请求 Ollama 服务出错,请根据以下信息排查或重试',
78
+
76
79
  AgentRuntimeError: 'Lobe 语言模型运行时执行出错,请根据以下信息排查或重试',
77
80
  /* eslint-enable */
78
81
  },
@@ -85,6 +85,22 @@ export default {
85
85
  title: 'API Key',
86
86
  },
87
87
  },
88
+ Ollama: {
89
+ checker: {
90
+ desc: '测试代理地址是否正确填写',
91
+ },
92
+ customModelName: {
93
+ desc: '增加自定义模型,多个模型使用逗号(,)隔开',
94
+ placeholder: 'vicuna,llava,codellama,llama2:13b-text',
95
+ title: '自定义模型名称',
96
+ },
97
+ endpoint: {
98
+ desc: '填入 Ollama 接口代理地址,本地未额外指定可留空',
99
+ placeholder: 'http://127.0.0.1:11434/v1',
100
+ title: '接口代理地址',
101
+ },
102
+ title: 'Ollama',
103
+ },
88
104
  OpenAI: {
89
105
  azureApiVersion: {
90
106
  desc: 'Azure 的 API 版本,遵循 YYYY-MM-DD 格式,查阅[最新版本](https://learn.microsoft.com/zh-cn/azure/ai-services/openai/reference#chat-completions)',
@@ -40,6 +40,14 @@ const getProviderAuthPayload = (provider: string) => {
40
40
  };
41
41
  }
42
42
 
43
+ case ModelProvider.Ollama: {
44
+ const endpoint = modelProviderSelectors.ollamaProxyUrl(useGlobalStore.getState());
45
+
46
+ return {
47
+ endpoint,
48
+ };
49
+ }
50
+
43
51
  default:
44
52
  case ModelProvider.OpenAI: {
45
53
  const openai = modelProviderSelectors.openAIConfig(useGlobalStore.getState());
@@ -5,6 +5,7 @@ import {
5
5
  GoogleProvider,
6
6
  LOBE_DEFAULT_MODEL_LIST,
7
7
  MoonshotProvider,
8
+ OllamaProvider,
8
9
  OpenAIProvider,
9
10
  ZhiPuProvider,
10
11
  } from '@/config/modelProviders';
@@ -37,6 +38,12 @@ const azureConfig = (s: GlobalStore) => modelProvider(s).azure;
37
38
  const enableMoonshot = (s: GlobalStore) => modelProvider(s).moonshot.enabled;
38
39
  const moonshotAPIKey = (s: GlobalStore) => modelProvider(s).moonshot.apiKey;
39
40
 
41
+ const enableOllamaConfigInSettings = (s: GlobalStore) =>
42
+ s.serverConfig.languageModel?.ollama?.enabled || false;
43
+
44
+ const enableOllama = (s: GlobalStore) => modelProvider(s).ollama.enabled;
45
+ const ollamaProxyUrl = (s: GlobalStore) => modelProvider(s).ollama.endpoint;
46
+
40
47
  // const azureModelList = (s: GlobalStore): ModelProviderCard => {
41
48
  // const azure = azureConfig(s);
42
49
  // return {
@@ -46,8 +53,11 @@ const moonshotAPIKey = (s: GlobalStore) => modelProvider(s).moonshot.apiKey;
46
53
  // };
47
54
 
48
55
  // 提取处理 chatModels 的专门方法
49
- const processChatModels = (modelConfig: ReturnType<typeof parseModelString>): ChatModelCard[] => {
50
- let chatModels = modelConfig.removeAll ? [] : OpenAIProvider.chatModels;
56
+ const processChatModels = (
57
+ modelConfig: ReturnType<typeof parseModelString>,
58
+ defaultChartModels = OpenAIProvider.chatModels,
59
+ ): ChatModelCard[] => {
60
+ let chatModels = modelConfig.removeAll ? [] : defaultChartModels;
51
61
 
52
62
  // 处理移除逻辑
53
63
  if (!modelConfig.removeAll) {
@@ -102,6 +112,12 @@ const modelSelectList = (s: GlobalStore): ModelProviderCard[] => {
102
112
 
103
113
  const chatModels = processChatModels(modelConfig);
104
114
 
115
+ const ollamaModelConfig = parseModelString(
116
+ currentSettings(s).languageModel.ollama.customModelName,
117
+ );
118
+
119
+ const ollamaChatModels = processChatModels(ollamaModelConfig, OllamaProvider.chatModels);
120
+
105
121
  return [
106
122
  {
107
123
  ...OpenAIProvider,
@@ -112,6 +128,7 @@ const modelSelectList = (s: GlobalStore): ModelProviderCard[] => {
112
128
  { ...MoonshotProvider, enabled: enableMoonshot(s) },
113
129
  { ...GoogleProvider, enabled: enableGoogle(s) },
114
130
  { ...BedrockProvider, enabled: enableBedrock(s) },
131
+ { ...OllamaProvider, chatModels: ollamaChatModels, enabled: enableOllama(s) },
115
132
  ];
116
133
  };
117
134
 
@@ -174,4 +191,9 @@ export const modelProviderSelectors = {
174
191
  // Moonshot
175
192
  enableMoonshot,
176
193
  moonshotAPIKey,
194
+
195
+ // Ollama
196
+ enableOllamaConfigInSettings,
197
+ enableOllama,
198
+ ollamaProxyUrl,
177
199
  };
@@ -47,11 +47,18 @@ export interface AWSBedrockConfig {
47
47
  secretAccessKey?: string;
48
48
  }
49
49
 
50
+ export interface OllamaConfig {
51
+ customModelName?: string;
52
+ enabled?: boolean;
53
+ endpoint?: string;
54
+ }
55
+
50
56
  export interface GlobalLLMConfig {
51
57
  azure: AzureOpenAIConfig;
52
58
  bedrock: AWSBedrockConfig;
53
59
  google: GoogleConfig;
54
60
  moonshot: MoonshotConfig;
61
+ ollama: OllamaConfig;
55
62
  openAI: OpenAIConfig;
56
63
  zhipu: ZhiPuConfig;
57
64
  }