mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-02-04 17:45:07 +08:00
Compare commits
7 Commits
0d7e52338e
...
cc167ae619
| Author | SHA1 | Date | |
|---|---|---|---|
| cc167ae619 | |||
| f8847e7bcd | |||
| 3baebd709b | |||
| 3e6a4b2628 | |||
| 312635cb13 | |||
| 756d454122 | |||
| a4cab371fa |
@ -24,6 +24,7 @@ from api.db.services.llm_service import LLMBundle
|
|||||||
from api import settings
|
from api import settings
|
||||||
from api.utils.api_utils import validate_request, build_error_result, apikey_required
|
from api.utils.api_utils import validate_request, build_error_result, apikey_required
|
||||||
from rag.app.tag import label_question
|
from rag.app.tag import label_question
|
||||||
|
from api.db.services.dialog_service import meta_filter
|
||||||
|
|
||||||
|
|
||||||
@manager.route('/dify/retrieval', methods=['POST']) # noqa: F821
|
@manager.route('/dify/retrieval', methods=['POST']) # noqa: F821
|
||||||
@ -37,7 +38,10 @@ def retrieval(tenant_id):
|
|||||||
retrieval_setting = req.get("retrieval_setting", {})
|
retrieval_setting = req.get("retrieval_setting", {})
|
||||||
similarity_threshold = float(retrieval_setting.get("score_threshold", 0.0))
|
similarity_threshold = float(retrieval_setting.get("score_threshold", 0.0))
|
||||||
top = int(retrieval_setting.get("top_k", 1024))
|
top = int(retrieval_setting.get("top_k", 1024))
|
||||||
|
metadata_condition = req.get("metadata_condition",{})
|
||||||
|
metas = DocumentService.get_meta_by_kbs([kb_id])
|
||||||
|
|
||||||
|
doc_ids = []
|
||||||
try:
|
try:
|
||||||
|
|
||||||
e, kb = KnowledgebaseService.get_by_id(kb_id)
|
e, kb = KnowledgebaseService.get_by_id(kb_id)
|
||||||
@ -45,7 +49,12 @@ def retrieval(tenant_id):
|
|||||||
return build_error_result(message="Knowledgebase not found!", code=settings.RetCode.NOT_FOUND)
|
return build_error_result(message="Knowledgebase not found!", code=settings.RetCode.NOT_FOUND)
|
||||||
|
|
||||||
embd_mdl = LLMBundle(kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id)
|
embd_mdl = LLMBundle(kb.tenant_id, LLMType.EMBEDDING.value, llm_name=kb.embd_id)
|
||||||
|
print(metadata_condition)
|
||||||
|
print("after",convert_conditions(metadata_condition))
|
||||||
|
doc_ids.extend(meta_filter(metas, convert_conditions(metadata_condition)))
|
||||||
|
print("doc_ids",doc_ids)
|
||||||
|
if not doc_ids and metadata_condition is not None:
|
||||||
|
doc_ids = ['-999']
|
||||||
ranks = settings.retrievaler.retrieval(
|
ranks = settings.retrievaler.retrieval(
|
||||||
question,
|
question,
|
||||||
embd_mdl,
|
embd_mdl,
|
||||||
@ -56,6 +65,7 @@ def retrieval(tenant_id):
|
|||||||
similarity_threshold=similarity_threshold,
|
similarity_threshold=similarity_threshold,
|
||||||
vector_similarity_weight=0.3,
|
vector_similarity_weight=0.3,
|
||||||
top=top,
|
top=top,
|
||||||
|
doc_ids=doc_ids,
|
||||||
rank_feature=label_question(question, [kb])
|
rank_feature=label_question(question, [kb])
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,6 +74,7 @@ def retrieval(tenant_id):
|
|||||||
[tenant_id],
|
[tenant_id],
|
||||||
[kb_id],
|
[kb_id],
|
||||||
embd_mdl,
|
embd_mdl,
|
||||||
|
doc_ids,
|
||||||
LLMBundle(kb.tenant_id, LLMType.CHAT))
|
LLMBundle(kb.tenant_id, LLMType.CHAT))
|
||||||
if ck["content_with_weight"]:
|
if ck["content_with_weight"]:
|
||||||
ranks["chunks"].insert(0, ck)
|
ranks["chunks"].insert(0, ck)
|
||||||
@ -90,3 +101,20 @@ def retrieval(tenant_id):
|
|||||||
)
|
)
|
||||||
logging.exception(e)
|
logging.exception(e)
|
||||||
return build_error_result(message=str(e), code=settings.RetCode.SERVER_ERROR)
|
return build_error_result(message=str(e), code=settings.RetCode.SERVER_ERROR)
|
||||||
|
|
||||||
|
def convert_conditions(metadata_condition):
|
||||||
|
if metadata_condition is None:
|
||||||
|
metadata_condition = {}
|
||||||
|
op_mapping = {
|
||||||
|
"is": "=",
|
||||||
|
"not is": "≠"
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"op": op_mapping.get(cond["comparison_operator"], cond["comparison_operator"]),
|
||||||
|
"key": cond["name"],
|
||||||
|
"value": cond["value"]
|
||||||
|
}
|
||||||
|
for cond in metadata_condition.get("conditions", [])
|
||||||
|
]
|
||||||
|
|
||||||
|
|||||||
@ -450,37 +450,26 @@ def agents_completion_openai_compatibility(tenant_id, agent_id):
|
|||||||
def agent_completions(tenant_id, agent_id):
|
def agent_completions(tenant_id, agent_id):
|
||||||
req = request.json
|
req = request.json
|
||||||
|
|
||||||
ans = {}
|
|
||||||
if req.get("stream", True):
|
if req.get("stream", True):
|
||||||
|
resp = Response(agent_completion(tenant_id=tenant_id, agent_id=agent_id, **req), mimetype="text/event-stream")
|
||||||
def generate():
|
|
||||||
for answer in agent_completion(tenant_id=tenant_id, agent_id=agent_id, **req):
|
|
||||||
if isinstance(answer, str):
|
|
||||||
try:
|
|
||||||
ans = json.loads(answer[5:]) # remove "data:"
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if ans.get("event") != "message":
|
|
||||||
continue
|
|
||||||
|
|
||||||
yield answer
|
|
||||||
|
|
||||||
yield "data:[DONE]\n\n"
|
|
||||||
|
|
||||||
resp = Response(generate(), mimetype="text/event-stream")
|
|
||||||
resp.headers.add_header("Cache-control", "no-cache")
|
resp.headers.add_header("Cache-control", "no-cache")
|
||||||
resp.headers.add_header("Connection", "keep-alive")
|
resp.headers.add_header("Connection", "keep-alive")
|
||||||
resp.headers.add_header("X-Accel-Buffering", "no")
|
resp.headers.add_header("X-Accel-Buffering", "no")
|
||||||
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
|
resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8")
|
||||||
return resp
|
return resp
|
||||||
|
result = {}
|
||||||
for answer in agent_completion(tenant_id=tenant_id, agent_id=agent_id, **req):
|
for answer in agent_completion(tenant_id=tenant_id, agent_id=agent_id, **req):
|
||||||
try:
|
try:
|
||||||
ans = json.loads(answer[5:]) # remove "data:"
|
ans = json.loads(answer[5:]) # remove "data:"
|
||||||
|
if not result:
|
||||||
|
result = ans.copy()
|
||||||
|
else:
|
||||||
|
result["data"]["answer"] += ans["data"]["answer"]
|
||||||
|
result["data"]["reference"] = ans["data"].get("reference", [])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return get_result(data=f"**ERROR**: {str(e)}")
|
return get_error_data_result(str(e))
|
||||||
return get_result(data=ans)
|
return result
|
||||||
|
|
||||||
|
|
||||||
@manager.route("/chats/<chat_id>/sessions", methods=["GET"]) # noqa: F821
|
@manager.route("/chats/<chat_id>/sessions", methods=["GET"]) # noqa: F821
|
||||||
@ -909,7 +898,7 @@ def ask_about_embedded():
|
|||||||
def stream():
|
def stream():
|
||||||
nonlocal req, uid
|
nonlocal req, uid
|
||||||
try:
|
try:
|
||||||
for ans in ask(req["question"], req["kb_ids"], uid, search_config):
|
for ans in ask(req["question"], req["kb_ids"], uid, search_config=search_config):
|
||||||
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans}, ensure_ascii=False) + "\n\n"
|
yield "data:" + json.dumps({"code": 0, "message": "", "data": ans}, ensure_ascii=False) + "\n\n"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
yield "data:" + json.dumps({"code": 500, "message": str(e), "data": {"answer": "**ERROR**: " + str(e), "reference": []}}, ensure_ascii=False) + "\n\n"
|
yield "data:" + json.dumps({"code": 500, "message": str(e), "data": {"answer": "**ERROR**: " + str(e), "reference": []}}, ensure_ascii=False) + "\n\n"
|
||||||
|
|||||||
@ -134,6 +134,25 @@ class UserCanvasService(CommonService):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def structure_answer(conv, ans, message_id, session_id):
|
||||||
|
if not conv:
|
||||||
|
return ans
|
||||||
|
content = ""
|
||||||
|
if ans["event"] == "message":
|
||||||
|
if ans["data"].get("start_to_think") is True:
|
||||||
|
content = "<think>"
|
||||||
|
elif ans["data"].get("end_to_think") is True:
|
||||||
|
content = "</think>"
|
||||||
|
else:
|
||||||
|
content = ans["data"]["content"]
|
||||||
|
|
||||||
|
reference = ans["data"].get("reference")
|
||||||
|
result = {"id": message_id, "session_id": session_id, "answer": content}
|
||||||
|
if reference:
|
||||||
|
result["reference"] = [reference]
|
||||||
|
return result
|
||||||
|
|
||||||
def completion(tenant_id, agent_id, session_id=None, **kwargs):
|
def completion(tenant_id, agent_id, session_id=None, **kwargs):
|
||||||
query = kwargs.get("query", "") or kwargs.get("question", "")
|
query = kwargs.get("query", "") or kwargs.get("question", "")
|
||||||
files = kwargs.get("files", [])
|
files = kwargs.get("files", [])
|
||||||
@ -176,13 +195,14 @@ def completion(tenant_id, agent_id, session_id=None, **kwargs):
|
|||||||
})
|
})
|
||||||
txt = ""
|
txt = ""
|
||||||
for ans in canvas.run(query=query, files=files, user_id=user_id, inputs=inputs):
|
for ans in canvas.run(query=query, files=files, user_id=user_id, inputs=inputs):
|
||||||
ans["session_id"] = session_id
|
ans = structure_answer(conv, ans, message_id, session_id)
|
||||||
if ans["event"] == "message":
|
txt += ans["answer"]
|
||||||
txt += ans["data"]["content"]
|
if ans.get("answer") or ans.get("reference"):
|
||||||
yield "data:" + json.dumps(ans, ensure_ascii=False) + "\n\n"
|
yield "data:" + json.dumps({"code": 0, "data": ans},
|
||||||
|
ensure_ascii=False) + "\n\n"
|
||||||
|
|
||||||
conv.message.append({"role": "assistant", "content": txt, "created_at": time.time(), "id": message_id})
|
conv.message.append({"role": "assistant", "content": txt, "created_at": time.time(), "id": message_id})
|
||||||
conv.reference = canvas.get_reference()
|
conv.reference.append(canvas.get_reference())
|
||||||
conv.errors = canvas.error
|
conv.errors = canvas.error
|
||||||
conv.dsl = str(canvas)
|
conv.dsl = str(canvas)
|
||||||
conv = conv.to_dict()
|
conv = conv.to_dict()
|
||||||
@ -211,11 +231,9 @@ def completionOpenAI(tenant_id, agent_id, question, session_id=None, stream=True
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.exception(f"Agent OpenAI-Compatible completionOpenAI parse answer failed: {e}")
|
logging.exception(f"Agent OpenAI-Compatible completionOpenAI parse answer failed: {e}")
|
||||||
continue
|
continue
|
||||||
|
if not ans["data"]["answer"]:
|
||||||
if ans.get("event") != "message":
|
|
||||||
continue
|
continue
|
||||||
|
content_piece = ans["data"]["answer"]
|
||||||
content_piece = ans["data"]["content"]
|
|
||||||
completion_tokens += len(tiktokenenc.encode(content_piece))
|
completion_tokens += len(tiktokenenc.encode(content_piece))
|
||||||
|
|
||||||
yield "data: " + json.dumps(
|
yield "data: " + json.dumps(
|
||||||
@ -260,9 +278,9 @@ def completionOpenAI(tenant_id, agent_id, question, session_id=None, stream=True
|
|||||||
):
|
):
|
||||||
if isinstance(ans, str):
|
if isinstance(ans, str):
|
||||||
ans = json.loads(ans[5:])
|
ans = json.loads(ans[5:])
|
||||||
if ans.get("event") != "message":
|
if not ans["data"]["answer"]:
|
||||||
continue
|
continue
|
||||||
all_content += ans["data"]["content"]
|
all_content += ans["data"]["answer"]
|
||||||
|
|
||||||
completion_tokens = len(tiktokenenc.encode(all_content))
|
completion_tokens = len(tiktokenenc.encode(all_content))
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,10 @@ class RecursiveAbstractiveProcessing4TreeOrganizedRetrieval:
|
|||||||
|
|
||||||
@timeout(60*20)
|
@timeout(60*20)
|
||||||
async def _chat(self, system, history, gen_conf):
|
async def _chat(self, system, history, gen_conf):
|
||||||
response = get_llm_cache(self._llm_model.llm_name, system, history, gen_conf)
|
response = await trio.to_thread.run_sync(
|
||||||
|
lambda: get_llm_cache(self._llm_model.llm_name, system, history, gen_conf)
|
||||||
|
)
|
||||||
|
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
response = await trio.to_thread.run_sync(
|
response = await trio.to_thread.run_sync(
|
||||||
@ -53,19 +56,23 @@ class RecursiveAbstractiveProcessing4TreeOrganizedRetrieval:
|
|||||||
response = re.sub(r"^.*</think>", "", response, flags=re.DOTALL)
|
response = re.sub(r"^.*</think>", "", response, flags=re.DOTALL)
|
||||||
if response.find("**ERROR**") >= 0:
|
if response.find("**ERROR**") >= 0:
|
||||||
raise Exception(response)
|
raise Exception(response)
|
||||||
set_llm_cache(self._llm_model.llm_name, system, response, history, gen_conf)
|
await trio.to_thread.run_sync(
|
||||||
|
lambda: set_llm_cache(self._llm_model.llm_name, system, response, history, gen_conf)
|
||||||
|
)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@timeout(20)
|
@timeout(20)
|
||||||
async def _embedding_encode(self, txt):
|
async def _embedding_encode(self, txt):
|
||||||
response = get_embed_cache(self._embd_model.llm_name, txt)
|
response = await trio.to_thread.run_sync(
|
||||||
|
lambda: get_embed_cache(self._embd_model.llm_name, txt)
|
||||||
|
)
|
||||||
if response is not None:
|
if response is not None:
|
||||||
return response
|
return response
|
||||||
embds, _ = await trio.to_thread.run_sync(lambda: self._embd_model.encode([txt]))
|
embds, _ = await trio.to_thread.run_sync(lambda: self._embd_model.encode([txt]))
|
||||||
if len(embds) < 1 or len(embds[0]) < 1:
|
if len(embds) < 1 or len(embds[0]) < 1:
|
||||||
raise Exception("Embedding error: ")
|
raise Exception("Embedding error: ")
|
||||||
embds = embds[0]
|
embds = embds[0]
|
||||||
set_embed_cache(self._embd_model.llm_name, txt, embds)
|
await trio.to_thread.run_sync(lambda: set_embed_cache(self._embd_model.llm_name, txt, embds))
|
||||||
return embds
|
return embds
|
||||||
|
|
||||||
def _get_optimal_clusters(self, embeddings: np.ndarray, random_state: int):
|
def _get_optimal_clusters(self, embeddings: np.ndarray, random_state: int):
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { LlmModelType } from '@/constants/knowledge';
|
|||||||
import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks';
|
import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks';
|
||||||
import * as SelectPrimitive from '@radix-ui/react-select';
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
||||||
import { forwardRef, memo, useMemo, useState } from 'react';
|
import { forwardRef, memo, useMemo, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { LlmSettingFieldItems } from '../llm-setting-items/next';
|
import { LlmSettingFieldItems } from '../llm-setting-items/next';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
|
||||||
import { Select, SelectTrigger, SelectValue } from '../ui/select';
|
import { Select, SelectTrigger, SelectValue } from '../ui/select';
|
||||||
@ -20,6 +21,7 @@ const NextInnerLLMSelect = forwardRef<
|
|||||||
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
||||||
NextInnerLLMSelectProps
|
NextInnerLLMSelectProps
|
||||||
>(({ value, disabled, filter, showSpeech2TextModel = false }, ref) => {
|
>(({ value, disabled, filter, showSpeech2TextModel = false }, ref) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||||
|
|
||||||
const ttsModel = useMemo(() => {
|
const ttsModel = useMemo(() => {
|
||||||
@ -49,7 +51,7 @@ const NextInnerLLMSelect = forwardRef<
|
|||||||
}}
|
}}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
<SelectValue>
|
<SelectValue placeholder={t('common.pleaseSelect')}>
|
||||||
{
|
{
|
||||||
modelOptions
|
modelOptions
|
||||||
.flatMap((x) => x.options)
|
.flatMap((x) => x.options)
|
||||||
|
|||||||
@ -8,9 +8,13 @@ import {
|
|||||||
} from '@/interfaces/database/llm';
|
} from '@/interfaces/database/llm';
|
||||||
import { buildLlmUuid } from '@/utils/llm-util';
|
import { buildLlmUuid } from '@/utils/llm-util';
|
||||||
|
|
||||||
|
export const enum LLMApiAction {
|
||||||
|
LlmList = 'llmList',
|
||||||
|
}
|
||||||
|
|
||||||
export const useFetchLlmList = (modelType?: LlmModelType) => {
|
export const useFetchLlmList = (modelType?: LlmModelType) => {
|
||||||
const { data } = useQuery<IThirdAiModelCollection>({
|
const { data } = useQuery<IThirdAiModelCollection>({
|
||||||
queryKey: ['llmList'],
|
queryKey: [LLMApiAction.LlmList],
|
||||||
initialData: {},
|
initialData: {},
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await userService.llm_list({ model_type: modelType });
|
const { data } = await userService.llm_list({ model_type: modelType });
|
||||||
|
|||||||
464
web/src/hooks/use-user-setting-request.tsx
Normal file
464
web/src/hooks/use-user-setting-request.tsx
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
import message from '@/components/ui/message';
|
||||||
|
import { LanguageTranslationMap } from '@/constants/common';
|
||||||
|
import { ResponseGetType } from '@/interfaces/database/base';
|
||||||
|
import { IToken } from '@/interfaces/database/chat';
|
||||||
|
import { ITenantInfo } from '@/interfaces/database/knowledge';
|
||||||
|
import { ILangfuseConfig } from '@/interfaces/database/system';
|
||||||
|
import {
|
||||||
|
ISystemStatus,
|
||||||
|
ITenant,
|
||||||
|
ITenantUser,
|
||||||
|
IUserInfo,
|
||||||
|
} from '@/interfaces/database/user-setting';
|
||||||
|
import { ISetLangfuseConfigRequestBody } from '@/interfaces/request/system';
|
||||||
|
import userService, {
|
||||||
|
addTenantUser,
|
||||||
|
agreeTenant,
|
||||||
|
deleteTenantUser,
|
||||||
|
listTenant,
|
||||||
|
listTenantUser,
|
||||||
|
} from '@/services/user-service';
|
||||||
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { Modal } from 'antd';
|
||||||
|
import DOMPurify from 'dompurify';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { history } from 'umi';
|
||||||
|
|
||||||
|
export const enum UserSettingApiAction {
|
||||||
|
UserInfo = 'userInfo',
|
||||||
|
TenantInfo = 'tenantInfo',
|
||||||
|
SaveSetting = 'saveSetting',
|
||||||
|
FetchManualSystemTokenList = 'fetchManualSystemTokenList',
|
||||||
|
FetchSystemTokenList = 'fetchSystemTokenList',
|
||||||
|
RemoveSystemToken = 'removeSystemToken',
|
||||||
|
CreateSystemToken = 'createSystemToken',
|
||||||
|
ListTenantUser = 'listTenantUser',
|
||||||
|
AddTenantUser = 'addTenantUser',
|
||||||
|
DeleteTenantUser = 'deleteTenantUser',
|
||||||
|
ListTenant = 'listTenant',
|
||||||
|
AgreeTenant = 'agreeTenant',
|
||||||
|
SetLangfuseConfig = 'setLangfuseConfig',
|
||||||
|
DeleteLangfuseConfig = 'deleteLangfuseConfig',
|
||||||
|
FetchLangfuseConfig = 'fetchLangfuseConfig',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useFetchUserInfo = (): ResponseGetType<IUserInfo> => {
|
||||||
|
const { i18n } = useTranslation();
|
||||||
|
|
||||||
|
const { data, isFetching: loading } = useQuery({
|
||||||
|
queryKey: [UserSettingApiAction.UserInfo],
|
||||||
|
initialData: {},
|
||||||
|
gcTime: 0,
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await userService.user_info();
|
||||||
|
if (data.code === 0) {
|
||||||
|
i18n.changeLanguage(
|
||||||
|
LanguageTranslationMap[
|
||||||
|
data.data.language as keyof typeof LanguageTranslationMap
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return data?.data ?? {};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFetchTenantInfo = (
|
||||||
|
showEmptyModelWarn = false,
|
||||||
|
): ResponseGetType<ITenantInfo> => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { data, isFetching: loading } = useQuery({
|
||||||
|
queryKey: [UserSettingApiAction.TenantInfo],
|
||||||
|
initialData: {},
|
||||||
|
gcTime: 0,
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data: res } = await userService.get_tenant_info();
|
||||||
|
if (res.code === 0) {
|
||||||
|
// llm_id is chat_id
|
||||||
|
// asr_id is speech2txt
|
||||||
|
const { data } = res;
|
||||||
|
if (
|
||||||
|
showEmptyModelWarn &&
|
||||||
|
(isEmpty(data.embd_id) || isEmpty(data.llm_id))
|
||||||
|
) {
|
||||||
|
Modal.warning({
|
||||||
|
title: t('common.warn'),
|
||||||
|
content: (
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: DOMPurify.sanitize(t('setting.modelProvidersWarn')),
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
),
|
||||||
|
onOk() {
|
||||||
|
history.push('/user-setting/model');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
data.chat_id = data.llm_id;
|
||||||
|
data.speech2text_id = data.asr_id;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSelectParserList = (): Array<{
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
}> => {
|
||||||
|
const { data: tenantInfo } = useFetchTenantInfo(true);
|
||||||
|
|
||||||
|
const parserList = useMemo(() => {
|
||||||
|
const parserArray: Array<string> = tenantInfo?.parser_ids?.split(',') ?? [];
|
||||||
|
return parserArray.map((x) => {
|
||||||
|
const arr = x.split(':');
|
||||||
|
return { value: arr[0], label: arr[1] };
|
||||||
|
});
|
||||||
|
}, [tenantInfo]);
|
||||||
|
|
||||||
|
return parserList;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSaveSetting = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [UserSettingApiAction.SaveSetting],
|
||||||
|
mutationFn: async (
|
||||||
|
userInfo: { new_password: string } | Partial<IUserInfo>,
|
||||||
|
) => {
|
||||||
|
const { data } = await userService.setting(userInfo);
|
||||||
|
if (data.code === 0) {
|
||||||
|
message.success(t('message.modified'));
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['userInfo'] });
|
||||||
|
}
|
||||||
|
return data?.code;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, saveSetting: mutateAsync };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFetchSystemVersion = () => {
|
||||||
|
const [version, setVersion] = useState('');
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const fetchSystemVersion = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const { data } = await userService.getSystemVersion();
|
||||||
|
if (data.code === 0) {
|
||||||
|
setVersion(data.data);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return { fetchSystemVersion, version, loading };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFetchSystemStatus = () => {
|
||||||
|
const [systemStatus, setSystemStatus] = useState<ISystemStatus>(
|
||||||
|
{} as ISystemStatus,
|
||||||
|
);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const fetchSystemStatus = useCallback(async () => {
|
||||||
|
setLoading(true);
|
||||||
|
const { data } = await userService.getSystemStatus();
|
||||||
|
if (data.code === 0) {
|
||||||
|
setSystemStatus(data.data);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
systemStatus,
|
||||||
|
fetchSystemStatus,
|
||||||
|
loading,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFetchManualSystemTokenList = () => {
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [UserSettingApiAction.FetchManualSystemTokenList],
|
||||||
|
mutationFn: async () => {
|
||||||
|
const { data } = await userService.listToken();
|
||||||
|
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, fetchSystemTokenList: mutateAsync };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFetchSystemTokenList = () => {
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isFetching: loading,
|
||||||
|
refetch,
|
||||||
|
} = useQuery<IToken[]>({
|
||||||
|
queryKey: [UserSettingApiAction.FetchSystemTokenList],
|
||||||
|
initialData: [],
|
||||||
|
gcTime: 0,
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await userService.listToken();
|
||||||
|
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, refetch };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRemoveSystemToken = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [UserSettingApiAction.RemoveSystemToken],
|
||||||
|
mutationFn: async (token: string) => {
|
||||||
|
const { data } = await userService.removeToken({}, token);
|
||||||
|
if (data.code === 0) {
|
||||||
|
message.success(t('message.deleted'));
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: [UserSettingApiAction.FetchSystemTokenList],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, removeToken: mutateAsync };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCreateSystemToken = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [UserSettingApiAction.CreateSystemToken],
|
||||||
|
mutationFn: async (params: Record<string, any>) => {
|
||||||
|
const { data } = await userService.createToken(params);
|
||||||
|
if (data.code === 0) {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: [UserSettingApiAction.FetchSystemTokenList],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, createToken: mutateAsync };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useListTenantUser = () => {
|
||||||
|
const { data: tenantInfo } = useFetchTenantInfo();
|
||||||
|
const tenantId = tenantInfo.tenant_id;
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isFetching: loading,
|
||||||
|
refetch,
|
||||||
|
} = useQuery<ITenantUser[]>({
|
||||||
|
queryKey: [UserSettingApiAction.ListTenantUser, tenantId],
|
||||||
|
initialData: [],
|
||||||
|
gcTime: 0,
|
||||||
|
enabled: !!tenantId,
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await listTenantUser(tenantId);
|
||||||
|
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, refetch };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAddTenantUser = () => {
|
||||||
|
const { data: tenantInfo } = useFetchTenantInfo();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [UserSettingApiAction.AddTenantUser],
|
||||||
|
mutationFn: async (email: string) => {
|
||||||
|
const { data } = await addTenantUser(tenantInfo.tenant_id, email);
|
||||||
|
if (data.code === 0) {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: [UserSettingApiAction.ListTenantUser],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data?.code;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, addTenantUser: mutateAsync };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDeleteTenantUser = () => {
|
||||||
|
const { data: tenantInfo } = useFetchTenantInfo();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [UserSettingApiAction.DeleteTenantUser],
|
||||||
|
mutationFn: async ({
|
||||||
|
userId,
|
||||||
|
tenantId,
|
||||||
|
}: {
|
||||||
|
userId: string;
|
||||||
|
tenantId?: string;
|
||||||
|
}) => {
|
||||||
|
const { data } = await deleteTenantUser({
|
||||||
|
tenantId: tenantId ?? tenantInfo.tenant_id,
|
||||||
|
userId,
|
||||||
|
});
|
||||||
|
if (data.code === 0) {
|
||||||
|
message.success(t('message.deleted'));
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: [UserSettingApiAction.ListTenantUser],
|
||||||
|
});
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: [UserSettingApiAction.ListTenant],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, deleteTenantUser: mutateAsync };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useListTenant = () => {
|
||||||
|
const { data: tenantInfo } = useFetchTenantInfo();
|
||||||
|
const tenantId = tenantInfo.tenant_id;
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isFetching: loading,
|
||||||
|
refetch,
|
||||||
|
} = useQuery<ITenant[]>({
|
||||||
|
queryKey: [UserSettingApiAction.ListTenant, tenantId],
|
||||||
|
initialData: [],
|
||||||
|
gcTime: 0,
|
||||||
|
enabled: !!tenantId,
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await listTenant();
|
||||||
|
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, refetch };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAgreeTenant = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [UserSettingApiAction.AgreeTenant],
|
||||||
|
mutationFn: async (tenantId: string) => {
|
||||||
|
const { data } = await agreeTenant(tenantId);
|
||||||
|
if (data.code === 0) {
|
||||||
|
message.success(t('message.operated'));
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: [UserSettingApiAction.ListTenant],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, agreeTenant: mutateAsync };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSetLangfuseConfig = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [UserSettingApiAction.SetLangfuseConfig],
|
||||||
|
mutationFn: async (params: ISetLangfuseConfigRequestBody) => {
|
||||||
|
const { data } = await userService.setLangfuseConfig(params);
|
||||||
|
if (data.code === 0) {
|
||||||
|
message.success(t('message.operated'));
|
||||||
|
}
|
||||||
|
return data?.code;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, setLangfuseConfig: mutateAsync };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDeleteLangfuseConfig = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isPending: loading,
|
||||||
|
mutateAsync,
|
||||||
|
} = useMutation({
|
||||||
|
mutationKey: [UserSettingApiAction.DeleteLangfuseConfig],
|
||||||
|
mutationFn: async () => {
|
||||||
|
const { data } = await userService.deleteLangfuseConfig();
|
||||||
|
if (data.code === 0) {
|
||||||
|
message.success(t('message.deleted'));
|
||||||
|
}
|
||||||
|
return data?.code;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading, deleteLangfuseConfig: mutateAsync };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFetchLangfuseConfig = () => {
|
||||||
|
const { data, isFetching: loading } = useQuery<ILangfuseConfig>({
|
||||||
|
queryKey: [UserSettingApiAction.FetchLangfuseConfig],
|
||||||
|
gcTime: 0,
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await userService.getLangfuseConfig();
|
||||||
|
|
||||||
|
return data?.data;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading };
|
||||||
|
};
|
||||||
@ -12,10 +12,13 @@ import { LanguageList, LanguageMap, ThemeEnum } from '@/constants/common';
|
|||||||
import { useChangeLanguage } from '@/hooks/logic-hooks';
|
import { useChangeLanguage } from '@/hooks/logic-hooks';
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { useNavigateWithFromState } from '@/hooks/route-hook';
|
import { useNavigateWithFromState } from '@/hooks/route-hook';
|
||||||
|
import { useListTenant } from '@/hooks/use-user-setting-request';
|
||||||
import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
|
import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
|
||||||
|
import { TenantRole } from '@/pages/user-setting/constants';
|
||||||
import { Routes } from '@/routes';
|
import { Routes } from '@/routes';
|
||||||
import { camelCase } from 'lodash';
|
import { camelCase } from 'lodash';
|
||||||
import {
|
import {
|
||||||
|
BellRing,
|
||||||
ChevronDown,
|
ChevronDown,
|
||||||
CircleHelp,
|
CircleHelp,
|
||||||
Cpu,
|
Cpu,
|
||||||
@ -53,11 +56,11 @@ export function Header() {
|
|||||||
changeLanguage(key);
|
changeLanguage(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const { data } = useListTenant();
|
const { data } = useListTenant();
|
||||||
|
|
||||||
// const showBell = useMemo(() => {
|
const showBell = useMemo(() => {
|
||||||
// return data.some((x) => x.role === TenantRole.Invite);
|
return data.some((x) => x.role === TenantRole.Invite);
|
||||||
// }, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const items = LanguageList.map((x) => ({
|
const items = LanguageList.map((x) => ({
|
||||||
key: x,
|
key: x,
|
||||||
@ -68,9 +71,9 @@ export function Header() {
|
|||||||
setTheme(theme === ThemeEnum.Dark ? ThemeEnum.Light : ThemeEnum.Dark);
|
setTheme(theme === ThemeEnum.Dark ? ThemeEnum.Light : ThemeEnum.Dark);
|
||||||
}, [setTheme, theme]);
|
}, [setTheme, theme]);
|
||||||
|
|
||||||
// const handleBellClick = useCallback(() => {
|
const handleBellClick = useCallback(() => {
|
||||||
// navigate('/user-setting/team');
|
navigate('/user-setting/team');
|
||||||
// }, [navigate]);
|
}, [navigate]);
|
||||||
|
|
||||||
const tagsData = useMemo(
|
const tagsData = useMemo(
|
||||||
() => [
|
() => [
|
||||||
@ -160,6 +163,14 @@ export function Header() {
|
|||||||
<Button variant={'ghost'} onClick={onThemeClick}>
|
<Button variant={'ghost'} onClick={onThemeClick}>
|
||||||
{theme === 'light' ? <Sun /> : <Moon />}
|
{theme === 'light' ? <Sun /> : <Moon />}
|
||||||
</Button>
|
</Button>
|
||||||
|
{showBell && (
|
||||||
|
<Button variant={'ghost'} onClick={handleBellClick}>
|
||||||
|
<div className="relative">
|
||||||
|
<BellRing className="size-4 " />
|
||||||
|
<span className="absolute size-1 rounded -right-1 -top-1 bg-red-600"></span>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<RAGFlowAvatar
|
<RAGFlowAvatar
|
||||||
name={nickname}
|
name={nickname}
|
||||||
|
|||||||
@ -240,9 +240,8 @@ export default {
|
|||||||
promptTip:
|
promptTip:
|
||||||
'Décrivez la tâche attendue du LLM, ses réponses, ses exigences, etc. Utilisez `/` pour afficher les variables disponibles.',
|
'Décrivez la tâche attendue du LLM, ses réponses, ses exigences, etc. Utilisez `/` pour afficher les variables disponibles.',
|
||||||
promptMessage: 'Le prompt est requis',
|
promptMessage: 'Le prompt est requis',
|
||||||
promptText: `Veuillez résumer les paragraphes suivants. Attention aux chiffres, ne pas inventer. Paragraphes suivants : {cluster_content
|
promptText: `Veuillez résumer les paragraphes suivants. Attention aux chiffres, ne pas inventer. Paragraphes suivants : {cluster_content}
|
||||||
}
|
Le contenu à résumer est ci-dessus.`,
|
||||||
Le contenu à résumer est ci-dessus.`,
|
|
||||||
maxToken: 'Nombre maximal de tokens',
|
maxToken: 'Nombre maximal de tokens',
|
||||||
maxTokenTip: 'Nombre maximal de tokens générés par résumé.',
|
maxTokenTip: 'Nombre maximal de tokens générés par résumé.',
|
||||||
maxTokenMessage: 'Nombre maximal de tokens requis',
|
maxTokenMessage: 'Nombre maximal de tokens requis',
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
|||||||
import { IKnowledge } from '@/interfaces/database/knowledge';
|
import { IKnowledge } from '@/interfaces/database/knowledge';
|
||||||
import { ChevronRight } from 'lucide-react';
|
import { ChevronRight } from 'lucide-react';
|
||||||
import { DatasetDropdown } from './dataset-dropdown';
|
import { DatasetDropdown } from './dataset-dropdown';
|
||||||
import { useDisplayOwnerName } from './use-display-owner';
|
|
||||||
import { useRenameDataset } from './use-rename-dataset';
|
import { useRenameDataset } from './use-rename-dataset';
|
||||||
|
|
||||||
export type DatasetCardProps = {
|
export type DatasetCardProps = {
|
||||||
@ -18,9 +17,6 @@ export function DatasetCard({
|
|||||||
showDatasetRenameModal,
|
showDatasetRenameModal,
|
||||||
}: DatasetCardProps) {
|
}: DatasetCardProps) {
|
||||||
const { navigateToDataset } = useNavigatePage();
|
const { navigateToDataset } = useNavigatePage();
|
||||||
const displayOwnerName = useDisplayOwnerName();
|
|
||||||
|
|
||||||
const owner = displayOwnerName(dataset.tenant_id, dataset.nickname);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HomeCard
|
<HomeCard
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import { LargeModelFormFieldWithoutFilter } from '@/components/large-model-form-
|
|||||||
import { LlmSettingSchema } from '@/components/llm-setting-items/next';
|
import { LlmSettingSchema } from '@/components/llm-setting-items/next';
|
||||||
import { NextMessageInput } from '@/components/message-input/next';
|
import { NextMessageInput } from '@/components/message-input/next';
|
||||||
import MessageItem from '@/components/message-item';
|
import MessageItem from '@/components/message-item';
|
||||||
|
import PdfDrawer from '@/components/pdf-drawer';
|
||||||
|
import { useClickDrawer } from '@/components/pdf-drawer/hooks';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Form } from '@/components/ui/form';
|
import { Form } from '@/components/ui/form';
|
||||||
@ -54,7 +56,8 @@ type ChatCardProps = {
|
|||||||
} & Pick<
|
} & Pick<
|
||||||
MultipleChatBoxProps,
|
MultipleChatBoxProps,
|
||||||
'controller' | 'removeChatBox' | 'addChatBox' | 'chatBoxIds'
|
'controller' | 'removeChatBox' | 'addChatBox' | 'chatBoxIds'
|
||||||
>;
|
> &
|
||||||
|
Pick<ReturnType<typeof useClickDrawer>, 'clickDocumentButton'>;
|
||||||
|
|
||||||
const ChatCard = forwardRef(function ChatCard(
|
const ChatCard = forwardRef(function ChatCard(
|
||||||
{
|
{
|
||||||
@ -66,6 +69,7 @@ const ChatCard = forwardRef(function ChatCard(
|
|||||||
chatBoxIds,
|
chatBoxIds,
|
||||||
derivedMessages,
|
derivedMessages,
|
||||||
sendLoading,
|
sendLoading,
|
||||||
|
clickDocumentButton,
|
||||||
}: ChatCardProps,
|
}: ChatCardProps,
|
||||||
ref,
|
ref,
|
||||||
) {
|
) {
|
||||||
@ -178,6 +182,7 @@ const ChatCard = forwardRef(function ChatCard(
|
|||||||
removeMessageById={removeMessageById}
|
removeMessageById={removeMessageById}
|
||||||
regenerateMessage={regenerateMessage}
|
regenerateMessage={regenerateMessage}
|
||||||
sendLoading={sendLoading}
|
sendLoading={sendLoading}
|
||||||
|
clickDocumentButton={clickDocumentButton}
|
||||||
></MessageItem>
|
></MessageItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -211,6 +216,8 @@ export function MultipleChatBox({
|
|||||||
const { conversationId } = useGetChatSearchParams();
|
const { conversationId } = useGetChatSearchParams();
|
||||||
const disabled = useGetSendButtonDisabled();
|
const disabled = useGetSendButtonDisabled();
|
||||||
const sendDisabled = useSendButtonDisabled(value);
|
const sendDisabled = useSendButtonDisabled(value);
|
||||||
|
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
|
||||||
|
useClickDrawer();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="h-full flex flex-col px-5">
|
<section className="h-full flex flex-col px-5">
|
||||||
@ -227,6 +234,7 @@ export function MultipleChatBox({
|
|||||||
derivedMessages={messageRecord[id]}
|
derivedMessages={messageRecord[id]}
|
||||||
ref={setFormRef(id)}
|
ref={setFormRef(id)}
|
||||||
sendLoading={sendLoading}
|
sendLoading={sendLoading}
|
||||||
|
clickDocumentButton={clickDocumentButton}
|
||||||
></ChatCard>
|
></ChatCard>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -246,6 +254,14 @@ export function MultipleChatBox({
|
|||||||
onUpload={handleUploadFile}
|
onUpload={handleUploadFile}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{visible && (
|
||||||
|
<PdfDrawer
|
||||||
|
visible={visible}
|
||||||
|
hideModal={hideModal}
|
||||||
|
documentId={documentId}
|
||||||
|
chunk={selectedChunk}
|
||||||
|
></PdfDrawer>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { NextMessageInput } from '@/components/message-input/next';
|
import { NextMessageInput } from '@/components/message-input/next';
|
||||||
import MessageItem from '@/components/message-item';
|
import MessageItem from '@/components/message-item';
|
||||||
|
import PdfDrawer from '@/components/pdf-drawer';
|
||||||
|
import { useClickDrawer } from '@/components/pdf-drawer/hooks';
|
||||||
import { MessageType } from '@/constants/chat';
|
import { MessageType } from '@/constants/chat';
|
||||||
import {
|
import {
|
||||||
useFetchConversation,
|
useFetchConversation,
|
||||||
@ -43,6 +45,8 @@ export function SingleChatBox({ controller }: IProps) {
|
|||||||
const { data: conversation } = useFetchConversation();
|
const { data: conversation } = useFetchConversation();
|
||||||
const disabled = useGetSendButtonDisabled();
|
const disabled = useGetSendButtonDisabled();
|
||||||
const sendDisabled = useSendButtonDisabled(value);
|
const sendDisabled = useSendButtonDisabled(value);
|
||||||
|
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
|
||||||
|
useClickDrawer();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="flex flex-col p-5 h-full">
|
<section className="flex flex-col p-5 h-full">
|
||||||
@ -68,7 +72,7 @@ export function SingleChatBox({ controller }: IProps) {
|
|||||||
},
|
},
|
||||||
message,
|
message,
|
||||||
)}
|
)}
|
||||||
// clickDocumentButton={clickDocumentButton}
|
clickDocumentButton={clickDocumentButton}
|
||||||
index={i}
|
index={i}
|
||||||
removeMessageById={removeMessageById}
|
removeMessageById={removeMessageById}
|
||||||
regenerateMessage={regenerateMessage}
|
regenerateMessage={regenerateMessage}
|
||||||
@ -94,6 +98,14 @@ export function SingleChatBox({ controller }: IProps) {
|
|||||||
onUpload={handleUploadFile}
|
onUpload={handleUploadFile}
|
||||||
isUploading={isUploading}
|
isUploading={isUploading}
|
||||||
/>
|
/>
|
||||||
|
{visible && (
|
||||||
|
<PdfDrawer
|
||||||
|
visible={visible}
|
||||||
|
hideModal={hideModal}
|
||||||
|
documentId={documentId}
|
||||||
|
chunk={selectedChunk}
|
||||||
|
></PdfDrawer>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,13 +109,12 @@ export default function Chat() {
|
|||||||
|
|
||||||
<Card className="flex-1 min-w-0 bg-transparent border h-full">
|
<Card className="flex-1 min-w-0 bg-transparent border h-full">
|
||||||
<CardContent className="flex p-0 h-full">
|
<CardContent className="flex p-0 h-full">
|
||||||
<Card className="flex flex-col flex-1 bg-transparent">
|
<Card className="flex flex-col flex-1 bg-transparent min-w-0">
|
||||||
<CardHeader
|
<CardHeader
|
||||||
className={cn('p-5', { 'border-b': hasSingleChatBox })}
|
className={cn('p-5', { 'border-b': hasSingleChatBox })}
|
||||||
>
|
>
|
||||||
<CardTitle className="flex justify-between items-center text-base">
|
<CardTitle className="flex justify-between items-center text-base">
|
||||||
<div>{conversation.name}</div>
|
<div className="truncate">{conversation.name}</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant={'ghost'}
|
variant={'ghost'}
|
||||||
onClick={switchDebugMode}
|
onClick={switchDebugMode}
|
||||||
|
|||||||
@ -90,8 +90,8 @@ export function Sessions({
|
|||||||
'bg-bg-card': conversationId === x.id,
|
'bg-bg-card': conversationId === x.id,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<CardContent className="px-3 py-2 flex justify-between items-center group">
|
<CardContent className="px-3 py-2 flex justify-between items-center group gap-1">
|
||||||
{x.name}
|
<div className="truncate">{x.name}</div>
|
||||||
<ConversationDropdown conversation={x}>
|
<ConversationDropdown conversation={x}>
|
||||||
<MoreButton></MoreButton>
|
<MoreButton></MoreButton>
|
||||||
</ConversationDropdown>
|
</ConversationDropdown>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { useSetModalState } from '@/hooks/common-hooks';
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
import { useSetDialog } from '@/hooks/use-chat-request';
|
import { useSetDialog } from '@/hooks/use-chat-request';
|
||||||
|
import { useFetchTenantInfo } from '@/hooks/use-user-setting-request';
|
||||||
import { IDialog } from '@/interfaces/database/chat';
|
import { IDialog } from '@/interfaces/database/chat';
|
||||||
import { isEmpty, omit } from 'lodash';
|
import { isEmpty, omit } from 'lodash';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
@ -14,6 +15,7 @@ export const useRenameChat = () => {
|
|||||||
} = useSetModalState();
|
} = useSetModalState();
|
||||||
const { setDialog, loading } = useSetDialog();
|
const { setDialog, loading } = useSetDialog();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const tenantInfo = useFetchTenantInfo();
|
||||||
|
|
||||||
const InitialData = useMemo(
|
const InitialData = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
@ -32,13 +34,13 @@ export const useRenameChat = () => {
|
|||||||
reasoning: false,
|
reasoning: false,
|
||||||
parameters: [{ key: 'knowledge', optional: false }],
|
parameters: [{ key: 'knowledge', optional: false }],
|
||||||
},
|
},
|
||||||
llm_id: '',
|
llm_id: tenantInfo.data.llm_id,
|
||||||
llm_setting: {},
|
llm_setting: {},
|
||||||
similarity_threshold: 0.2,
|
similarity_threshold: 0.2,
|
||||||
vector_similarity_weight: 0.30000000000000004,
|
vector_similarity_weight: 0.30000000000000004,
|
||||||
top_n: 8,
|
top_n: 8,
|
||||||
}),
|
}),
|
||||||
[t],
|
[t, tenantInfo.data.llm_id],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onChatRenameOk = useCallback(
|
const onChatRenameOk = useCallback(
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import showMessage from '@/components/ui/message';
|
||||||
import { MessageType } from '@/constants/chat';
|
import { MessageType } from '@/constants/chat';
|
||||||
import {
|
import {
|
||||||
useHandleMessageInputChange,
|
useHandleMessageInputChange,
|
||||||
@ -159,7 +160,7 @@ export function useSendMultipleChatMessage(
|
|||||||
if (res && (res?.response.status !== 200 || res?.data?.code !== 0)) {
|
if (res && (res?.response.status !== 200 || res?.data?.code !== 0)) {
|
||||||
// cancel loading
|
// cancel loading
|
||||||
setValue(message.content);
|
setValue(message.content);
|
||||||
console.info('removeLatestMessage111');
|
showMessage.error(res.data.message);
|
||||||
removeLatestMessage(chatBoxId);
|
removeLatestMessage(chatBoxId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user