黄腾 aopstudio commited on
Commit
29fdf3e
·
1 Parent(s): 3f751c1

add supprot for OpenAI-API-Compatible llm (#1787)

Browse files

### What problem does this PR solve?

#1771 add supprot for OpenAI-API-Compatible

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Co-authored-by: Zhedong Cen <[email protected]>

api/apps/llm_app.py CHANGED
@@ -129,6 +129,9 @@ def add_llm():
129
  elif factory == "LocalAI":
130
  llm_name = req["llm_name"]+"___LocalAI"
131
  api_key = "xxxxxxxxxxxxxxx"
 
 
 
132
  else:
133
  llm_name = req["llm_name"]
134
  api_key = "xxxxxxxxxxxxxxx"
@@ -145,7 +148,7 @@ def add_llm():
145
  msg = ""
146
  if llm["model_type"] == LLMType.EMBEDDING.value:
147
  mdl = EmbeddingModel[factory](
148
- key=llm['api_key'] if factory in ["VolcEngine", "Bedrock"] else None,
149
  model_name=llm["llm_name"],
150
  base_url=llm["api_base"])
151
  try:
@@ -156,7 +159,7 @@ def add_llm():
156
  msg += f"\nFail to access embedding model({llm['llm_name']})." + str(e)
157
  elif llm["model_type"] == LLMType.CHAT.value:
158
  mdl = ChatModel[factory](
159
- key=llm['api_key'] if factory in ["VolcEngine", "Bedrock"] else None,
160
  model_name=llm["llm_name"],
161
  base_url=llm["api_base"]
162
  )
@@ -181,7 +184,7 @@ def add_llm():
181
  e)
182
  elif llm["model_type"] == LLMType.IMAGE2TEXT.value:
183
  mdl = CvModel[factory](
184
- key=None, model_name=llm["llm_name"], base_url=llm["api_base"]
185
  )
186
  try:
187
  img_url = (
 
129
  elif factory == "LocalAI":
130
  llm_name = req["llm_name"]+"___LocalAI"
131
  api_key = "xxxxxxxxxxxxxxx"
132
+ elif factory == "OpenAI-API-Compatible":
133
+ llm_name = req["llm_name"]+"___OpenAI-API"
134
+ api_key = req["api_key"]
135
  else:
136
  llm_name = req["llm_name"]
137
  api_key = "xxxxxxxxxxxxxxx"
 
148
  msg = ""
149
  if llm["model_type"] == LLMType.EMBEDDING.value:
150
  mdl = EmbeddingModel[factory](
151
+ key=llm['api_key'] if factory in ["VolcEngine", "Bedrock","OpenAI-API-Compatible"] else None,
152
  model_name=llm["llm_name"],
153
  base_url=llm["api_base"])
154
  try:
 
159
  msg += f"\nFail to access embedding model({llm['llm_name']})." + str(e)
160
  elif llm["model_type"] == LLMType.CHAT.value:
161
  mdl = ChatModel[factory](
162
+ key=llm['api_key'] if factory in ["VolcEngine", "Bedrock","OpenAI-API-Compatible"] else None,
163
  model_name=llm["llm_name"],
164
  base_url=llm["api_base"]
165
  )
 
184
  e)
185
  elif llm["model_type"] == LLMType.IMAGE2TEXT.value:
186
  mdl = CvModel[factory](
187
+ key=llm["api_key"] if factory in ["OpenAI-API-Compatible"] else None, model_name=llm["llm_name"], base_url=llm["api_base"]
188
  )
189
  try:
190
  img_url = (
conf/llm_factories.json CHANGED
@@ -158,6 +158,13 @@
158
  "status": "1",
159
  "llm": []
160
  },
 
 
 
 
 
 
 
161
  {
162
  "name": "Moonshot",
163
  "logo": "",
 
158
  "status": "1",
159
  "llm": []
160
  },
161
+ {
162
+ "name": "OpenAI-API-Compatible",
163
+ "logo": "",
164
+ "tags": "LLM,TEXT EMBEDDING,SPEECH2TEXT,MODERATION",
165
+ "status": "1",
166
+ "llm": []
167
+ },
168
  {
169
  "name": "Moonshot",
170
  "logo": "",
rag/llm/__init__.py CHANGED
@@ -36,7 +36,8 @@ EmbeddingModel = {
36
  "Bedrock": BedrockEmbed,
37
  "Gemini": GeminiEmbed,
38
  "NVIDIA": NvidiaEmbed,
39
- "LM-Studio": LmStudioEmbed
 
40
  }
41
 
42
 
@@ -53,7 +54,8 @@ CvModel = {
53
  "LocalAI": LocalAICV,
54
  "NVIDIA": NvidiaCV,
55
  "LM-Studio": LmStudioCV,
56
- "StepFun":StepFunCV
 
57
  }
58
 
59
 
@@ -78,7 +80,8 @@ ChatModel = {
78
  "OpenRouter": OpenRouterChat,
79
  "StepFun": StepFunChat,
80
  "NVIDIA": NvidiaChat,
81
- "LM-Studio": LmStudioChat
 
82
  }
83
 
84
 
@@ -88,7 +91,8 @@ RerankModel = {
88
  "Youdao": YoudaoRerank,
89
  "Xinference": XInferenceRerank,
90
  "NVIDIA": NvidiaRerank,
91
- "LM-Studio": LmStudioRerank
 
92
  }
93
 
94
 
 
36
  "Bedrock": BedrockEmbed,
37
  "Gemini": GeminiEmbed,
38
  "NVIDIA": NvidiaEmbed,
39
+ "LM-Studio": LmStudioEmbed,
40
+ "OpenAI-API-Compatible": OpenAI_APIEmbed
41
  }
42
 
43
 
 
54
  "LocalAI": LocalAICV,
55
  "NVIDIA": NvidiaCV,
56
  "LM-Studio": LmStudioCV,
57
+ "StepFun":StepFunCV,
58
+ "OpenAI-API-Compatible": OpenAI_APICV
59
  }
60
 
61
 
 
80
  "OpenRouter": OpenRouterChat,
81
  "StepFun": StepFunChat,
82
  "NVIDIA": NvidiaChat,
83
+ "LM-Studio": LmStudioChat,
84
+ "OpenAI-API-Compatible": OpenAI_APIChat
85
  }
86
 
87
 
 
91
  "Youdao": YoudaoRerank,
92
  "Xinference": XInferenceRerank,
93
  "NVIDIA": NvidiaRerank,
94
+ "LM-Studio": LmStudioRerank,
95
+ "OpenAI-API-Compatible": OpenAI_APIRerank
96
  }
97
 
98
 
rag/llm/chat_model.py CHANGED
@@ -887,6 +887,16 @@ class LmStudioChat(Base):
887
  if not base_url:
888
  raise ValueError("Local llm url cannot be None")
889
  if base_url.split("/")[-1] != "v1":
890
- self.base_url = os.path.join(base_url, "v1")
891
- self.client = OpenAI(api_key="lm-studio", base_url=self.base_url)
892
  self.model_name = model_name
 
 
 
 
 
 
 
 
 
 
 
887
  if not base_url:
888
  raise ValueError("Local llm url cannot be None")
889
  if base_url.split("/")[-1] != "v1":
890
+ base_url = os.path.join(base_url, "v1")
891
+ self.client = OpenAI(api_key="lm-studio", base_url=base_url)
892
  self.model_name = model_name
893
+
894
+
895
+ class OpenAI_APIChat(Base):
896
+ def __init__(self, key, model_name, base_url):
897
+ if not base_url:
898
+ raise ValueError("url cannot be None")
899
+ if base_url.split("/")[-1] != "v1":
900
+ base_url = os.path.join(base_url, "v1")
901
+ model_name = model_name.split("___")[0]
902
+ super().__init__(key, model_name, base_url)
rag/llm/cv_model.py CHANGED
@@ -638,3 +638,14 @@ class LmStudioCV(GptV4):
638
  self.client = OpenAI(api_key="lm-studio", base_url=base_url)
639
  self.model_name = model_name
640
  self.lang = lang
 
 
 
 
 
 
 
 
 
 
 
 
638
  self.client = OpenAI(api_key="lm-studio", base_url=base_url)
639
  self.model_name = model_name
640
  self.lang = lang
641
+
642
+
643
+ class OpenAI_APICV(GptV4):
644
+ def __init__(self, key, model_name, base_url, lang="Chinese"):
645
+ if not base_url:
646
+ raise ValueError("url cannot be None")
647
+ if base_url.split("/")[-1] != "v1":
648
+ base_url = os.path.join(base_url, "v1")
649
+ self.client = OpenAI(api_key=key, base_url=base_url)
650
+ self.model_name = model_name.split("___")[0]
651
+ self.lang = lang
rag/llm/embedding_model.py CHANGED
@@ -513,3 +513,13 @@ class LmStudioEmbed(LocalAIEmbed):
513
  self.base_url = os.path.join(base_url, "v1")
514
  self.client = OpenAI(api_key="lm-studio", base_url=self.base_url)
515
  self.model_name = model_name
 
 
 
 
 
 
 
 
 
 
 
513
  self.base_url = os.path.join(base_url, "v1")
514
  self.client = OpenAI(api_key="lm-studio", base_url=self.base_url)
515
  self.model_name = model_name
516
+
517
+
518
+ class OpenAI_APIEmbed(OpenAIEmbed):
519
+ def __init__(self, key, model_name, base_url):
520
+ if not base_url:
521
+ raise ValueError("url cannot be None")
522
+ if base_url.split("/")[-1] != "v1":
523
+ self.base_url = os.path.join(base_url, "v1")
524
+ self.client = OpenAI(api_key=key, base_url=base_url)
525
+ self.model_name = model_name.split("___")[0]
rag/llm/rerank_model.py CHANGED
@@ -212,3 +212,11 @@ class LmStudioRerank(Base):
212
 
213
  def similarity(self, query: str, texts: list):
214
  raise NotImplementedError("The LmStudioRerank has not been implement")
 
 
 
 
 
 
 
 
 
212
 
213
  def similarity(self, query: str, texts: list):
214
  raise NotImplementedError("The LmStudioRerank has not been implement")
215
+
216
+
217
+ class OpenAI_APIRerank(Base):
218
+ def __init__(self, key, model_name, base_url):
219
+ pass
220
+
221
+ def similarity(self, query: str, texts: list):
222
+ raise NotImplementedError("The api has not been implement")
web/src/assets/svg/llm/openai-api.svg ADDED
web/src/interfaces/request/llm.ts CHANGED
@@ -3,6 +3,7 @@ export interface IAddLlmRequestBody {
3
  llm_name: string;
4
  model_type: string;
5
  api_base?: string; // chat|embedding|speech2text|image2text
 
6
  }
7
 
8
  export interface IDeleteLlmRequestBody {
 
3
  llm_name: string;
4
  model_type: string;
5
  api_base?: string; // chat|embedding|speech2text|image2text
6
+ api_key: string;
7
  }
8
 
9
  export interface IDeleteLlmRequestBody {
web/src/pages/user-setting/constants.tsx CHANGED
@@ -17,4 +17,4 @@ export const UserSettingIconMap = {
17
 
18
  export * from '@/constants/setting';
19
 
20
- export const LocalLlmFactories = ['Ollama', 'Xinference','LocalAI','LM-Studio'];
 
17
 
18
  export * from '@/constants/setting';
19
 
20
+ export const LocalLlmFactories = ['Ollama', 'Xinference','LocalAI','LM-Studio',"OpenAI-API-Compatible"];
web/src/pages/user-setting/setting-model/constant.ts CHANGED
@@ -21,7 +21,8 @@ export const IconMap = {
21
  LocalAI: 'local-ai',
22
  StepFun: 'stepfun',
23
  NVIDIA:'nvidia',
24
- 'LM-Studio':'lm-studio'
 
25
  };
26
 
27
  export const BedrockRegionList = [
 
21
  LocalAI: 'local-ai',
22
  StepFun: 'stepfun',
23
  NVIDIA:'nvidia',
24
+ 'LM-Studio':'lm-studio',
25
+ 'OpenAI-API-Compatible':'openai-api'
26
  };
27
 
28
  export const BedrockRegionList = [
web/src/pages/user-setting/setting-model/ollama-modal/index.tsx CHANGED
@@ -92,6 +92,13 @@ const OllamaModal = ({
92
  >
93
  <Input placeholder={t('baseUrlNameMessage')} />
94
  </Form.Item>
 
 
 
 
 
 
 
95
  <Form.Item noStyle dependencies={['model_type']}>
96
  {({ getFieldValue }) =>
97
  getFieldValue('model_type') === 'chat' && (
 
92
  >
93
  <Input placeholder={t('baseUrlNameMessage')} />
94
  </Form.Item>
95
+ <Form.Item<FieldType>
96
+ label={t('apiKey')}
97
+ name="api_key"
98
+ rules={[{ required: false, message: t('apiKeyMessage') }]}
99
+ >
100
+ <Input placeholder={t('apiKeyMessage')} />
101
+ </Form.Item>
102
  <Form.Item noStyle dependencies={['model_type']}>
103
  {({ getFieldValue }) =>
104
  getFieldValue('model_type') === 'chat' && (