JobSmithManipulation
Kevin Hu
commited on
Commit
·
086a0cb
1
Parent(s):
a694851
add huggingface model (#2624)
Browse files### What problem does this PR solve?
#2469
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
---------
Co-authored-by: Kevin Hu <[email protected]>
- api/apps/llm_app.py +4 -0
- conf/llm_factories.json +8 -1
- rag/llm/__init__.py +3 -2
- rag/llm/chat_model.py +1 -0
- rag/llm/embedding_model.py +37 -0
- web/src/assets/svg/llm/huggingface.svg +37 -0
- web/src/pages/user-setting/constants.tsx +1 -0
- web/src/pages/user-setting/setting-model/constant.ts +1 -0
- web/src/pages/user-setting/setting-model/ollama-modal/index.tsx +28 -10
api/apps/llm_app.py
CHANGED
@@ -155,6 +155,10 @@ def add_llm():
|
|
155 |
elif factory == "LocalAI":
|
156 |
llm_name = req["llm_name"]+"___LocalAI"
|
157 |
api_key = "xxxxxxxxxxxxxxx"
|
|
|
|
|
|
|
|
|
158 |
|
159 |
elif factory == "OpenAI-API-Compatible":
|
160 |
llm_name = req["llm_name"]+"___OpenAI-API"
|
|
|
155 |
elif factory == "LocalAI":
|
156 |
llm_name = req["llm_name"]+"___LocalAI"
|
157 |
api_key = "xxxxxxxxxxxxxxx"
|
158 |
+
|
159 |
+
elif factory == "HuggingFace":
|
160 |
+
llm_name = req["llm_name"]+"___HuggingFace"
|
161 |
+
api_key = "xxxxxxxxxxxxxxx"
|
162 |
|
163 |
elif factory == "OpenAI-API-Compatible":
|
164 |
llm_name = req["llm_name"]+"___OpenAI-API"
|
conf/llm_factories.json
CHANGED
@@ -2344,6 +2344,13 @@
|
|
2344 |
"tags": "LLM",
|
2345 |
"status": "1",
|
2346 |
"llm": []
|
2347 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2348 |
]
|
2349 |
}
|
|
|
2344 |
"tags": "LLM",
|
2345 |
"status": "1",
|
2346 |
"llm": []
|
2347 |
+
},
|
2348 |
+
{
|
2349 |
+
"name": "HuggingFace",
|
2350 |
+
"logo": "",
|
2351 |
+
"tags": "TEXT EMBEDDING",
|
2352 |
+
"status": "1",
|
2353 |
+
"llm": []
|
2354 |
+
}
|
2355 |
]
|
2356 |
}
|
rag/llm/__init__.py
CHANGED
@@ -18,7 +18,7 @@ from .chat_model import *
|
|
18 |
from .cv_model import *
|
19 |
from .rerank_model import *
|
20 |
from .sequence2txt_model import *
|
21 |
-
from .tts_model import *
|
22 |
|
23 |
EmbeddingModel = {
|
24 |
"Ollama": OllamaEmbed,
|
@@ -46,7 +46,8 @@ EmbeddingModel = {
|
|
46 |
"SILICONFLOW": SILICONFLOWEmbed,
|
47 |
"Replicate": ReplicateEmbed,
|
48 |
"BaiduYiyan": BaiduYiyanEmbed,
|
49 |
-
"Voyage AI": VoyageEmbed
|
|
|
50 |
}
|
51 |
|
52 |
|
|
|
18 |
from .cv_model import *
|
19 |
from .rerank_model import *
|
20 |
from .sequence2txt_model import *
|
21 |
+
from .tts_model import *
|
22 |
|
23 |
EmbeddingModel = {
|
24 |
"Ollama": OllamaEmbed,
|
|
|
46 |
"SILICONFLOW": SILICONFLOWEmbed,
|
47 |
"Replicate": ReplicateEmbed,
|
48 |
"BaiduYiyan": BaiduYiyanEmbed,
|
49 |
+
"Voyage AI": VoyageEmbed,
|
50 |
+
"HuggingFace":HuggingFaceEmbed,
|
51 |
}
|
52 |
|
53 |
|
rag/llm/chat_model.py
CHANGED
@@ -1414,3 +1414,4 @@ class GoogleChat(Base):
|
|
1414 |
yield ans + "\n**ERROR**: " + str(e)
|
1415 |
|
1416 |
yield response._chunks[-1].usage_metadata.total_token_count
|
|
|
|
1414 |
yield ans + "\n**ERROR**: " + str(e)
|
1415 |
|
1416 |
yield response._chunks[-1].usage_metadata.total_token_count
|
1417 |
+
|
rag/llm/embedding_model.py
CHANGED
@@ -678,3 +678,40 @@ class VoyageEmbed(Base):
|
|
678 |
texts=text, model=self.model_name, input_type="query"
|
679 |
)
|
680 |
return np.array(res.embeddings), res.total_tokens
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
678 |
texts=text, model=self.model_name, input_type="query"
|
679 |
)
|
680 |
return np.array(res.embeddings), res.total_tokens
|
681 |
+
|
682 |
+
|
683 |
+
class HuggingFaceEmbed(Base):
|
684 |
+
def __init__(self, key, model_name, base_url=None):
|
685 |
+
if not model_name:
|
686 |
+
raise ValueError("Model name cannot be None")
|
687 |
+
self.key = key
|
688 |
+
self.model_name = model_name
|
689 |
+
self.base_url = base_url or "http://127.0.0.1:8080"
|
690 |
+
|
691 |
+
def encode(self, texts: list, batch_size=32):
|
692 |
+
embeddings = []
|
693 |
+
for text in texts:
|
694 |
+
response = requests.post(
|
695 |
+
f"{self.base_url}/embed",
|
696 |
+
json={"inputs": text},
|
697 |
+
headers={'Content-Type': 'application/json'}
|
698 |
+
)
|
699 |
+
if response.status_code == 200:
|
700 |
+
embedding = response.json()
|
701 |
+
embeddings.append(embedding[0])
|
702 |
+
else:
|
703 |
+
raise Exception(f"Error: {response.status_code} - {response.text}")
|
704 |
+
return np.array(embeddings), sum([num_tokens_from_string(text) for text in texts])
|
705 |
+
|
706 |
+
def encode_queries(self, text):
|
707 |
+
response = requests.post(
|
708 |
+
f"{self.base_url}/embed",
|
709 |
+
json={"inputs": text},
|
710 |
+
headers={'Content-Type': 'application/json'}
|
711 |
+
)
|
712 |
+
if response.status_code == 200:
|
713 |
+
embedding = response.json()
|
714 |
+
return np.array(embedding[0]), num_tokens_from_string(text)
|
715 |
+
else:
|
716 |
+
raise Exception(f"Error: {response.status_code} - {response.text}")
|
717 |
+
|
web/src/assets/svg/llm/huggingface.svg
ADDED
|
web/src/pages/user-setting/constants.tsx
CHANGED
@@ -26,4 +26,5 @@ export const LocalLlmFactories = [
|
|
26 |
'TogetherAI',
|
27 |
'Replicate',
|
28 |
'OpenRouter',
|
|
|
29 |
];
|
|
|
26 |
'TogetherAI',
|
27 |
'Replicate',
|
28 |
'OpenRouter',
|
29 |
+
'HuggingFace',
|
30 |
];
|
web/src/pages/user-setting/setting-model/constant.ts
CHANGED
@@ -40,6 +40,7 @@ export const IconMap = {
|
|
40 |
Anthropic: 'anthropic',
|
41 |
'Voyage AI': 'voyage',
|
42 |
'Google Cloud': 'google-cloud',
|
|
|
43 |
};
|
44 |
|
45 |
export const BedrockRegionList = [
|
|
|
40 |
Anthropic: 'anthropic',
|
41 |
'Voyage AI': 'voyage',
|
42 |
'Google Cloud': 'google-cloud',
|
43 |
+
HuggingFace: 'huggingface',
|
44 |
};
|
45 |
|
46 |
export const BedrockRegionList = [
|
web/src/pages/user-setting/setting-model/ollama-modal/index.tsx
CHANGED
@@ -8,6 +8,20 @@ type FieldType = IAddLlmRequestBody & { vision: boolean };
|
|
8 |
|
9 |
const { Option } = Select;
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
const OllamaModal = ({
|
12 |
visible,
|
13 |
hideModal,
|
@@ -35,7 +49,9 @@ const OllamaModal = ({
|
|
35 |
|
36 |
onOk?.(data);
|
37 |
};
|
38 |
-
|
|
|
|
|
39 |
return (
|
40 |
<Modal
|
41 |
title={t('addLlmTitle', { name: llmFactory })}
|
@@ -46,11 +62,7 @@ const OllamaModal = ({
|
|
46 |
footer={(originNode: React.ReactNode) => {
|
47 |
return (
|
48 |
<Flex justify={'space-between'}>
|
49 |
-
<a
|
50 |
-
href={`https://github.com/infiniflow/ragflow/blob/main/docs/guides/deploy_local_llm.mdx`}
|
51 |
-
target="_blank"
|
52 |
-
rel="noreferrer"
|
53 |
-
>
|
54 |
{t('ollamaLink', { name: llmFactory })}
|
55 |
</a>
|
56 |
<Space>{originNode}</Space>
|
@@ -72,10 +84,16 @@ const OllamaModal = ({
|
|
72 |
rules={[{ required: true, message: t('modelTypeMessage') }]}
|
73 |
>
|
74 |
<Select placeholder={t('modelTypeMessage')}>
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
</Select>
|
80 |
</Form.Item>
|
81 |
<Form.Item<FieldType>
|
|
|
8 |
|
9 |
const { Option } = Select;
|
10 |
|
11 |
+
const llmFactoryToUrlMap = {
|
12 |
+
Ollama: 'https://huggingface.co/docs/text-embeddings-inference/quick_tour',
|
13 |
+
Xinference: 'https://inference.readthedocs.io/en/latest/user_guide',
|
14 |
+
LocalAI: 'https://localai.io/docs/getting-started/models/',
|
15 |
+
'LM-Studio': 'https://lmstudio.ai/docs/basics',
|
16 |
+
'OpenAI-API-Compatible': 'https://platform.openai.com/docs/models/gpt-4',
|
17 |
+
TogetherAI: 'https://docs.together.ai/docs/deployment-options',
|
18 |
+
Replicate: 'https://replicate.com/docs/topics/deployments',
|
19 |
+
OpenRouter: 'https://openrouter.ai/docs',
|
20 |
+
HuggingFace:
|
21 |
+
'https://huggingface.co/docs/text-embeddings-inference/quick_tour',
|
22 |
+
};
|
23 |
+
type LlmFactory = keyof typeof llmFactoryToUrlMap;
|
24 |
+
|
25 |
const OllamaModal = ({
|
26 |
visible,
|
27 |
hideModal,
|
|
|
49 |
|
50 |
onOk?.(data);
|
51 |
};
|
52 |
+
const url =
|
53 |
+
llmFactoryToUrlMap[llmFactory as LlmFactory] ||
|
54 |
+
'https://huggingface.co/docs/text-embeddings-inference/quick_tour';
|
55 |
return (
|
56 |
<Modal
|
57 |
title={t('addLlmTitle', { name: llmFactory })}
|
|
|
62 |
footer={(originNode: React.ReactNode) => {
|
63 |
return (
|
64 |
<Flex justify={'space-between'}>
|
65 |
+
<a href={url} target="_blank" rel="noreferrer">
|
|
|
|
|
|
|
|
|
66 |
{t('ollamaLink', { name: llmFactory })}
|
67 |
</a>
|
68 |
<Space>{originNode}</Space>
|
|
|
84 |
rules={[{ required: true, message: t('modelTypeMessage') }]}
|
85 |
>
|
86 |
<Select placeholder={t('modelTypeMessage')}>
|
87 |
+
{llmFactory === 'HuggingFace' ? (
|
88 |
+
<Option value="embedding">embedding</Option>
|
89 |
+
) : (
|
90 |
+
<>
|
91 |
+
<Option value="chat">chat</Option>
|
92 |
+
<Option value="embedding">embedding</Option>
|
93 |
+
<Option value="rerank">rerank</Option>
|
94 |
+
<Option value="image2text">image2text</Option>
|
95 |
+
</>
|
96 |
+
)}
|
97 |
</Select>
|
98 |
</Form.Item>
|
99 |
<Form.Item<FieldType>
|