From 69a1b56e8950f9fccc98c79626f1ca16848f8079 Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:38:41 +0800 Subject: [PATCH 01/11] Update wikipedia.py --- graph/component/wikipedia.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/graph/component/wikipedia.py b/graph/component/wikipedia.py index 9e67875961e..48abefaf6e7 100644 --- a/graph/component/wikipedia.py +++ b/graph/component/wikipedia.py @@ -30,9 +30,16 @@ class WikipediaParam(ComponentParamBase): def __init__(self): super().__init__() self.top_n = 10 + self.lang = 'en' def check(self): self.check_positive_integer(self.top_n, "Top N") + self.check_valid_value(self.lang, "Wikipedia languages", + ['af', 'pl', 'ar', 'ast', 'az', 'bg', 'nan', 'bn', 'be', 'ca', 'cs', 'cy', 'da', 'de', + 'et', 'el', 'en', 'es', 'eo', 'eu', 'fa', 'fr', 'gl', 'ko', 'hy', 'hi', 'hr', 'id', + 'it', 'he', 'ka', 'lld', 'la', 'lv', 'lt', 'hu', 'mk', 'arz', 'ms', 'min', 'my', 'nl', + 'ja', 'nb', 'nn', 'ce', 'uz', 'pt', 'kk', 'ro', 'ru', 'ceb', 'sk', 'sl', 'sr', 'sh', + 'fi', 'sv', 'ta', 'tt', 'th', 'tg', 'azb', 'tr', 'uk', 'ur', 'vi', 'war', 'zh', 'yue']) class Wikipedia(ComponentBase, ABC): @@ -45,9 +52,11 @@ def _run(self, history, **kwargs): return Wikipedia.be_output(self._param.no) wiki_res = [] - for wiki_key in wikipedia.search(ans, results=self._param.top_n): + wikipedia.set_lang(self._param.lang) + wiki_engine = wikipedia + for wiki_key in wiki_engine.search(ans, results=self._param.top_n): try: - page = wikipedia.page(title=wiki_key, auto_suggest=False) + page = wiki_engine.page(title=wiki_key, auto_suggest=False) wiki_res.append({"content": '' + page.title + ' ' + page.summary}) except Exception as e: print(e) From 268c0c7eb7fb7df47600341af51ca37a3241411e Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:37:28 +0800 Subject: [PATCH 02/11] Update requirements.txt --- requirements.txt | 176 ++++++++++++++--------------------------------- 1 file changed, 51 insertions(+), 125 deletions(-) diff --git a/requirements.txt b/requirements.txt index 43eddf5b18f..9d02e96486e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,153 +1,79 @@ -accelerate==0.27.2 -aiohttp==3.9.5 -aiosignal==1.3.1 -annotated-types==0.6.0 -anyio==4.3.0 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 Aspose.Slides==24.2.0 -attrs==23.2.0 -blinker==1.7.0 -cachelib==0.12.0 +BCEmbedding==0.1.3 +boto3==1.34.140 +botocore==1.34.140 cachetools==5.3.3 -certifi==2024.2.2 -cffi==1.16.0 -charset-normalizer==3.3.2 -click==8.1.7 -coloredlogs==15.0.1 -cryptography==42.0.5 +chardet==5.2.0 +cn2an==0.5.22 dashscope==1.14.1 -datasets==2.17.1 datrie==0.8.2 demjson3==3.0.6 -dill==0.3.8 -distro==1.9.0 -elastic-transport==8.12.0 +discord.py==2.3.2 +duckduckgo_search==6.1.9 +elastic_transport==8.12.0 elasticsearch==8.12.1 -elasticsearch-dsl==8.12.0 -et-xmlfile==1.1.0 -filelock==3.13.1 +elasticsearch_dsl==8.12.0 fastembed==0.2.6 -FlagEmbedding==1.2.5 -Flask==3.0.2 -Flask-Cors==4.0.0 -Flask-Login==0.6.3 -Flask-Session==0.6.0 -flatbuffers==23.5.26 -frozenlist==1.4.1 -fsspec==2023.10.0 -h11==0.14.0 +fasttext==0.9.3 +filelock==3.15.4 +FlagEmbedding==1.2.10 +Flask==3.0.3 +Flask_Cors==4.0.0 +Flask_Login==0.6.3 +flask_session==0.8.0 +groq==0.9.0 hanziconv==0.3.2 -httpcore==1.0.4 +html_text==0.6.2 httpx==0.27.0 -huggingface-hub==0.20.3 -humanfriendly==10.0 -idna==3.6 -install==1.3.5 +huggingface_hub==0.20.3 +infinity_emb==0.0.51 itsdangerous==2.1.2 -Jinja2==3.1.3 -joblib==1.3.2 -lxml==5.1.0 -MarkupSafe==2.1.5 +Markdown==3.6 minio==7.2.4 -mpmath==1.3.0 -multidict==6.0.5 -multiprocess==0.70.16 -networkx==3.2.1 +mistralai==0.4.2 nltk==3.8.1 numpy==1.26.4 -nvidia-cublas-cu12==12.1.3.1 -nvidia-cuda-cupti-cu12==12.1.105 -nvidia-cuda-nvrtc-cu12==12.1.105 -nvidia-cuda-runtime-cu12==12.1.105 -nvidia-cudnn-cu12==8.9.2.26 -nvidia-cufft-cu12==11.0.2.54 -nvidia-curand-cu12==10.3.2.106 -nvidia-cusolver-cu12==11.4.5.107 -nvidia-cusparse-cu12==12.1.0.106 -nvidia-nccl-cu12==2.19.3 -nvidia-nvjitlink-cu12==12.3.101 -nvidia-nvtx-cu12==12.1.105 -ollama==0.1.9 -onnxruntime-gpu==1.17.1 -openai==1.12.0 -opencv-python==4.9.0.80 +ollama==0.2.1 +onnxruntime==1.17.3 +onnxruntime_gpu==1.17.1 +openai==1.35.14 +opencv_python==4.9.0.80 +opencv_python_headless==4.9.0.80 openpyxl==3.1.2 -packaging==23.2 -pandas==2.2.1 -pdfminer.six==20221105 +pandas==2.2.2 pdfplumber==0.10.4 peewee==3.17.1 -pillow==10.3.0 -protobuf==4.25.3 -psutil==5.9.8 -pyarrow==15.0.0 -pyarrow-hotfix==0.6 +Pillow==10.4.0 +pipreqs==0.5.0 +protobuf==5.27.2 pyclipper==1.3.0.post5 -pycparser==2.21 -pycryptodome -pycryptodome-test-vectors -pycryptodomex -pydantic==2.6.2 -pydantic_core==2.16.3 -PyJWT==2.8.0 -PyMySQL==1.1.1 +pycryptodomex==3.20.0 PyPDF2==3.0.1 -pypdfium2==4.27.0 -python-dateutil==2.8.2 -python-docx==1.1.0 +pytest==8.2.2 python-dotenv==1.0.1 -python-pptx==0.6.23 -PyYAML==6.0.1 +python_dateutil==2.8.2 +python_pptx==0.6.23 +readability_lxml==0.8.1 redis==5.0.3 -regex==2023.12.25 -requests==2.31.0 -ruamel.yaml==0.18.6 -ruamel.yaml.clib==0.2.8 -safetensors==0.4.2 -scikit-learn==1.4.1.post1 -scipy==1.12.0 -sentence-transformers==2.4.0 -shapely==2.0.3 +Requests==2.32.3 +roman_numbers==1.0.2 +ruamel.base==1.0.0 +scikit_learn==1.4.1.post1 +selenium==4.22.0 +setuptools==69.5.1 +Shapely==2.0.5 six==1.16.0 -sniffio==1.3.1 StrEnum==0.4.15 -sympy==1.12 -threadpoolctl==3.3.0 tika==2.6.0 tiktoken==0.6.0 -tokenizers==0.15.2 -torch==2.2.1 -tqdm==4.66.2 +torch==2.3.0 transformers==4.38.1 -triton==2.2.0 -typing_extensions==4.10.0 -tzdata==2024.1 -urllib3==2.2.1 +umap==0.1.1 +volcengine==1.0.146 +webdriver_manager==4.0.1 Werkzeug==3.0.3 -xgboost==2.0.3 -XlsxWriter==3.2.0 +wikipedia==1.4.0 +word2number==1.1 +xgboost==2.1.0 xpinyin==0.7.6 -xxhash==3.4.1 -yarl==1.9.4 zhipuai==2.0.1 -BCEmbedding -loguru==0.7.2 -umap-learn -fasttext==0.9.2 -pybind11==2.13.1 -volcengine==1.0.141 -readability-lxml==0.8.1 -html_text==0.6.2 -selenium==4.21.0 -webdriver-manager==4.0.1 -cn2an==0.5.22 -roman-numbers==1.0.2 -word2number==1.1 -markdown==3.6 -mistralai==0.4.2 -boto3==1.34.140 -duckduckgo_search==6.1.9 -google-generativeai==0.7.2 -groq==0.9.0 -wikipedia==1.4.0 From 92cf45134adabff305b38d2f7fea9d768a030995 Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Fri, 19 Jul 2024 18:23:24 +0800 Subject: [PATCH 03/11] Update llm_service.py --- api/db/services/llm_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/db/services/llm_service.py b/api/db/services/llm_service.py index 5906927b7bc..a994d6103eb 100644 --- a/api/db/services/llm_service.py +++ b/api/db/services/llm_service.py @@ -70,7 +70,7 @@ def model_instance(cls, tenant_id, llm_type, elif llm_type == LLMType.SPEECH2TEXT.value: mdlnm = tenant.asr_id elif llm_type == LLMType.IMAGE2TEXT.value: - mdlnm = tenant.img2txt_id + mdlnm = tenant.img2txt_id if not llm_name else llm_name elif llm_type == LLMType.CHAT.value: mdlnm = tenant.llm_id if not llm_name else llm_name elif llm_type == LLMType.RERANK: From ad5a5b8bed32a47c073f0484feb235bcff6e94cd Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Fri, 19 Jul 2024 18:24:37 +0800 Subject: [PATCH 04/11] Update index.tsx --- web/src/components/llm-setting-items/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/components/llm-setting-items/index.tsx b/web/src/components/llm-setting-items/index.tsx index a8365d616e8..c31d7aabeea 100644 --- a/web/src/components/llm-setting-items/index.tsx +++ b/web/src/components/llm-setting-items/index.tsx @@ -46,7 +46,7 @@ const LlmSettingItems = ({ prefix, formItemLayout = {} }: IProps) => { {...formItemLayout} rules={[{ required: true, message: t('modelMessage') }]} > - Date: Mon, 22 Jul 2024 18:27:56 +0800 Subject: [PATCH 05/11] Update init_data.py --- api/db/init_data.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/db/init_data.py b/api/db/init_data.py index 0acfe7b12a5..61fd0e6de01 100644 --- a/api/db/init_data.py +++ b/api/db/init_data.py @@ -121,6 +121,8 @@ def init_llm_factory(): LLMFactoriesService.filter_delete([LLMFactoriesService.model.name == "QAnything"]) LLMService.filter_delete([LLMService.model.fid == "QAnything"]) TenantLLMService.filter_update([TenantLLMService.model.llm_factory == "QAnything"], {"llm_factory": "Youdao"}) + TenantService.filter_update([1 == 1], { + "parser_ids": "naive:General,qa:Q&A,resume:Resume,manual:Manual,table:Table,paper:Paper,book:Book,laws:Laws,presentation:Presentation,picture:Picture,one:One,audio:Audio"}) ## insert openai two embedding models to the current openai user. print("Start to insert 2 OpenAI embedding models...") tenant_ids = set([row["tenant_id"] for row in TenantLLMService.get_openai_models()]) From addfea5f889c6464e904c68357589ed32f6562d1 Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:45:54 +0800 Subject: [PATCH 06/11] Update __init__.py --- agent/component/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/agent/component/__init__.py b/agent/component/__init__.py index 43fa3eeb803..ccd59f9e93c 100644 --- a/agent/component/__init__.py +++ b/agent/component/__init__.py @@ -20,6 +20,7 @@ from .deepl import DeepL, DeepLParam from .github import GitHub, GitHubParam from .baidufanyi import BaiduFanyi, BaiduFanyiParam +from .qweather import QWeather, QWeatherParam def component_class(class_name): m = importlib.import_module("agent.component") From 7ce918d2e363521078da3d43b8e08c3b02864990 Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:08:04 +0800 Subject: [PATCH 07/11] Update api_app.py --- api/apps/api_app.py | 279 +++++++++++++++++++++++++++++++------------- 1 file changed, 200 insertions(+), 79 deletions(-) diff --git a/api/apps/api_app.py b/api/apps/api_app.py index 8d7f00e8bc1..1017499d09b 100644 --- a/api/apps/api_app.py +++ b/api/apps/api_app.py @@ -39,6 +39,10 @@ from api.utils.file_utils import filename_type, thumbnail from rag.utils.minio_conn import MINIO +from api.db.services.canvas_service import CanvasTemplateService, UserCanvasService +from agent.canvas import Canvas +from functools import partial + def generate_confirmation_token(tenent_id): serializer = URLSafeTimedSerializer(tenent_id) @@ -46,7 +50,6 @@ def generate_confirmation_token(tenent_id): @manager.route('/new_token', methods=['POST']) -@validate_request("dialog_id") @login_required def new_token(): req = request.json @@ -57,12 +60,17 @@ def new_token(): tenant_id = tenants[0].tenant_id obj = {"tenant_id": tenant_id, "token": generate_confirmation_token(tenant_id), - "dialog_id": req["dialog_id"], "create_time": current_timestamp(), "create_date": datetime_format(datetime.now()), "update_time": None, "update_date": None } + if req.get("canvas_ids"): + obj["dialog_id"] = req["canvas_ids"] + obj["source"] = "agent" + else: + obj["dialog_id"] = req["dialog_id"] + if not APITokenService.save(**obj): return get_data_error_result(retmsg="Fail to new a dialog!") @@ -112,15 +120,15 @@ def stats(): "from_date", (datetime.now() - timedelta( - days=7)).strftime("%Y-%m-%d 24:00:00")), + days=7)).strftime("%Y-%m-%d 24:00:00")), request.args.get( "to_date", datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) res = { "pv": [(o["dt"], o["pv"]) for o in objs], "uv": [(o["dt"], o["uv"]) for o in objs], - "speed": [(o["dt"], float(o["tokens"])/(float(o["duration"]+0.1))) for o in objs], - "tokens": [(o["dt"], float(o["tokens"])/1000.) for o in objs], + "speed": [(o["dt"], float(o["tokens"]) / (float(o["duration"] + 0.1))) for o in objs], + "tokens": [(o["dt"], float(o["tokens"]) / 1000.) for o in objs], "round": [(o["dt"], o["round"]) for o in objs], "thumb_up": [(o["dt"], o["thumb_up"]) for o in objs] } @@ -138,21 +146,39 @@ def set_conversation(): data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR) req = request.json try: - e, dia = DialogService.get_by_id(objs[0].dialog_id) - if not e: - return get_data_error_result(retmsg="Dialog not found") - conv = { - "id": get_uuid(), - "dialog_id": dia.id, - "user_id": request.args.get("user_id", ""), - "message": [{"role": "assistant", "content": dia.prompt_config["prologue"]}] - } - API4ConversationService.save(**conv) - e, conv = API4ConversationService.get_by_id(conv["id"]) - if not e: - return get_data_error_result(retmsg="Fail to new a conversation!") - conv = conv.to_dict() - return get_json_result(data=conv) + if objs[0].source == "agent": + e, c = UserCanvasService.get_by_id(objs[0].dialog_id) + if not e: + return server_error_response("canvas not found.") + conv = { + "id": get_uuid(), + "dialog_id": c.id, + "user_id": request.args.get("user_id", ""), + "message": [{"role": "assistant", "content": "Hi there!"}], + "source": "agent" + } + API4ConversationService.save(**conv) + e, conv = API4ConversationService.get_by_id(conv["id"]) + if not e: + return get_data_error_result(retmsg="Fail to new a conversation!") + conv = conv.to_dict() + return get_json_result(data=conv) + else: + e, dia = DialogService.get_by_id(objs[0].dialog_id) + if not e: + return get_data_error_result(retmsg="Dialog not found") + conv = { + "id": get_uuid(), + "dialog_id": dia.id, + "user_id": request.args.get("user_id", ""), + "message": [{"role": "assistant", "content": dia.prompt_config["prologue"]}] + } + API4ConversationService.save(**conv) + e, conv = API4ConversationService.get_by_id(conv["id"]) + if not e: + return get_data_error_result(retmsg="Fail to new a conversation!") + conv = conv.to_dict() + return get_json_result(data=conv) except Exception as e: return server_error_response(e) @@ -161,7 +187,8 @@ def set_conversation(): @validate_request("conversation_id", "messages") def completion(): token = request.headers.get('Authorization').split()[1] - if not APIToken.query(token=token): + objs = APIToken.query(token=token) + if not objs: return get_json_result( data=False, retmsg='Token is not valid!"', retcode=RetCode.AUTHENTICATION_ERROR) req = request.json @@ -179,65 +206,159 @@ def completion(): msg.append({"role": m["role"], "content": m["content"]}) try: - conv.message.append(msg[-1]) - e, dia = DialogService.get_by_id(conv.dialog_id) - if not e: - return get_data_error_result(retmsg="Dialog not found!") - del req["conversation_id"] - del req["messages"] + if conv.source == "agent": + stream = req.get("stream", True) + conv.message.append(msg[-1]) + e, cvs = UserCanvasService.get_by_id(conv.dialog_id) + if not e: + return server_error_response("canvas not found.") + del req["conversation_id"] + del req["messages"] - if not conv.reference: - conv.reference = [] - conv.message.append({"role": "assistant", "content": ""}) - conv.reference.append({"chunks": [], "doc_aggs": []}) + if not isinstance(cvs.dsl, str): + cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False) - def fillin_conv(ans): - nonlocal conv if not conv.reference: - conv.reference.append(ans["reference"]) - else: conv.reference[-1] = ans["reference"] - conv.message[-1] = {"role": "assistant", "content": ans["answer"]} - - def rename_field(ans): - reference = ans['reference'] - if not isinstance(reference, dict): - return - for chunk_i in reference.get('chunks', []): - if 'docnm_kwd' in chunk_i: - chunk_i['doc_name'] = chunk_i['docnm_kwd'] - chunk_i.pop('docnm_kwd') - - def stream(): - nonlocal dia, msg, req, conv - try: - for ans in chat(dia, msg, True, **req): - fillin_conv(ans) - rename_field(ans) - yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans}, ensure_ascii=False) + "\n\n" - API4ConversationService.append_message(conv.id, conv.to_dict()) - except Exception as e: - yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e), - "data": {"answer": "**ERROR**: "+str(e), "reference": []}}, - ensure_ascii=False) + "\n\n" - yield "data:"+json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n" - - if req.get("stream", True): - resp = Response(stream(), mimetype="text/event-stream") - resp.headers.add_header("Cache-control", "no-cache") - resp.headers.add_header("Connection", "keep-alive") - resp.headers.add_header("X-Accel-Buffering", "no") - resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8") - return resp - else: - answer = None - for ans in chat(dia, msg, **req): - answer = ans + conv.reference = [] + conv.message.append({"role": "assistant", "content": ""}) + conv.reference.append({"chunks": [], "doc_aggs": []}) + + def fillin_conv(ans): + nonlocal conv + if not conv.reference: + conv.reference.append(ans["reference"]) + else: + conv.reference[-1] = ans["reference"] + conv.message[-1] = {"role": "assistant", "content": ans["answer"]} + + def rename_field(ans): + reference = ans['reference'] + if not isinstance(reference, dict): + return + for chunk_i in reference.get('chunks', []): + if 'docnm_kwd' in chunk_i: + chunk_i['doc_name'] = chunk_i['docnm_kwd'] + chunk_i.pop('docnm_kwd') + + final_ans = {"reference": [], "content": ""} + canvas = Canvas(cvs.dsl, objs[0].tenant_id) + + canvas.messages.append(msg[-1]) + canvas.add_user_input(msg[-1]["content"]) + answer = canvas.run(stream=stream) + + assert answer is not None, "Nothing. Is it over?" + + if stream: + assert isinstance(answer, partial), "Nothing. Is it over?" + + def sse(): + nonlocal answer, cvs, conv + try: + for ans in answer(): + for k in ans.keys(): + final_ans[k] = ans[k] + ans = {"answer": ans["content"], "reference": ans.get("reference", [])} + fillin_conv(ans) + rename_field(ans) + yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans}, + ensure_ascii=False) + "\n\n" + + canvas.messages.append({"role": "assistant", "content": final_ans["content"]}) + if final_ans.get("reference"): + canvas.reference.append(final_ans["reference"]) + cvs.dsl = json.loads(str(canvas)) + API4ConversationService.append_message(conv.id, conv.to_dict()) + except Exception as e: + yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e), + "data": {"answer": "**ERROR**: " + str(e), "reference": []}}, + ensure_ascii=False) + "\n\n" + yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n" + + resp = Response(sse(), mimetype="text/event-stream") + resp.headers.add_header("Cache-control", "no-cache") + resp.headers.add_header("Connection", "keep-alive") + resp.headers.add_header("X-Accel-Buffering", "no") + resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8") + return resp + + final_ans["content"] = "\n".join(answer["content"]) if "content" in answer else "" + canvas.messages.append({"role": "assistant", "content": final_ans["content"]}) + if final_ans.get("reference"): + canvas.reference.append(final_ans["reference"]) + cvs.dsl = json.loads(str(canvas)) + + result = None + for ans in answer(): + ans = {"answer": ans["content"], "reference": ans.get("reference", [])} + result = ans fillin_conv(ans) API4ConversationService.append_message(conv.id, conv.to_dict()) break + rename_field(result) + return get_json_result(data=result) + else: + conv.message.append(msg[-1]) + e, dia = DialogService.get_by_id(conv.dialog_id) + if not e: + return get_data_error_result(retmsg="Dialog not found!") + del req["conversation_id"] + del req["messages"] + + if not conv.reference: + conv.reference = [] + conv.message.append({"role": "assistant", "content": ""}) + conv.reference.append({"chunks": [], "doc_aggs": []}) + + def fillin_conv(ans): + nonlocal conv + if not conv.reference: + conv.reference.append(ans["reference"]) + else: + conv.reference[-1] = ans["reference"] + conv.message[-1] = {"role": "assistant", "content": ans["answer"]} + + def rename_field(ans): + reference = ans['reference'] + if not isinstance(reference, dict): + return + for chunk_i in reference.get('chunks', []): + if 'docnm_kwd' in chunk_i: + chunk_i['doc_name'] = chunk_i['docnm_kwd'] + chunk_i.pop('docnm_kwd') + + def stream(): + nonlocal dia, msg, req, conv + try: + for ans in chat(dia, msg, True, **req): + fillin_conv(ans) + rename_field(ans) + yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans}, + ensure_ascii=False) + "\n\n" + API4ConversationService.append_message(conv.id, conv.to_dict()) + except Exception as e: + yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e), + "data": {"answer": "**ERROR**: " + str(e), "reference": []}}, + ensure_ascii=False) + "\n\n" + yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n" + + if req.get("stream", True): + resp = Response(stream(), mimetype="text/event-stream") + resp.headers.add_header("Cache-control", "no-cache") + resp.headers.add_header("Connection", "keep-alive") + resp.headers.add_header("X-Accel-Buffering", "no") + resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8") + return resp + else: + answer = None + for ans in chat(dia, msg, **req): + answer = ans + fillin_conv(ans) + API4ConversationService.append_message(conv.id, conv.to_dict()) + break - rename_field(answer) - return get_json_result(data=answer) + rename_field(answer) + return get_json_result(data=answer) except Exception as e: return server_error_response(e) @@ -332,7 +453,7 @@ def upload(): "thumbnail": thumbnail(filename, blob) } - form_data=request.form + form_data = request.form if "parser_id" in form_data.keys(): if request.form.get("parser_id").strip() in list(vars(ParserType).values())[1:-3]: doc["parser_id"] = request.form.get("parser_id").strip() @@ -361,7 +482,7 @@ def upload(): if not tenant_id: return get_data_error_result(retmsg="Tenant not found!") - #e, doc = DocumentService.get_by_id(doc["id"]) + # e, doc = DocumentService.get_by_id(doc["id"]) TaskService.filter_delete([Task.doc_id == doc["id"]]) e, doc = DocumentService.get_by_id(doc["id"]) doc = doc.to_dict() @@ -369,7 +490,7 @@ def upload(): bucket, name = File2DocumentService.get_minio_address(doc_id=doc["id"]) queue_tasks(doc, bucket, name) except Exception as e: - return server_error_response(e) + return server_error_response(e) return get_json_result(data=doc_result.to_json()) @@ -448,7 +569,7 @@ def list_kb_docs(): docs = [{"doc_id": doc['id'], "doc_name": doc['name']} for doc in docs] return get_json_result(data={"total": tol, "docs": docs}) - + except Exception as e: return server_error_response(e) @@ -549,7 +670,8 @@ def fillin_conv(ans): nonlocal conv if not conv.reference: conv.reference.append(ans["reference"]) - else: conv.reference[-1] = ans["reference"] + else: + conv.reference[-1] = ans["reference"] conv.message[-1] = {"role": "assistant", "content": ans["answer"]} data_type_picture = { @@ -638,4 +760,3 @@ def retrieval(): return get_json_result(data=False, retmsg=f'No chunk found! Check the chunk status please!', retcode=RetCode.DATA_ERROR) return server_error_response(e) - From b51f9fd52423ced09aa92903090748dcf7a60e4e Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:12:57 +0800 Subject: [PATCH 08/11] Update db_models.py --- api/db/db_models.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/api/db/db_models.py b/api/db/db_models.py index 267c34b7be6..9df1580d354 100644 --- a/api/db/db_models.py +++ b/api/db/db_models.py @@ -858,6 +858,7 @@ class APIToken(DataBaseModel): tenant_id = CharField(max_length=32, null=False, index=True) token = CharField(max_length=255, null=False, index=True) dialog_id = CharField(max_length=32, null=False, index=True) + source = CharField(max_length=16, null=True, help_text="none|agent|dialog", index=True) class Meta: db_table = "api_token" @@ -871,6 +872,7 @@ class API4Conversation(DataBaseModel): message = JSONField(null=True) reference = JSONField(null=True, default=[]) tokens = IntegerField(default=0) + source = CharField(max_length=16, null=True, help_text="none|agent|dialog", index=True) duration = FloatField(default=0, index=True) round = IntegerField(default=0, index=True) @@ -949,3 +951,17 @@ def migrate_db(): ) except Exception as e: pass + try: + migrate( + migrator.add_column('api_token', 'source', + CharField(max_length=16, null=True, help_text="none|agent|dialog", index=True)) + ) + except Exception as e: + pass + try: + migrate( + migrator.add_column('api_4_conversation', 'source', + CharField(max_length=16, null=True, help_text="none|agent|dialog", index=True)) + ) + except Exception as e: + pass From 30c227659d2ec8674e1ac457c582be81f56aa8a4 Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:24:54 +0800 Subject: [PATCH 09/11] Update api_app.py --- api/apps/api_app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/apps/api_app.py b/api/apps/api_app.py index 1017499d09b..2b85d6fa2f2 100644 --- a/api/apps/api_app.py +++ b/api/apps/api_app.py @@ -65,8 +65,8 @@ def new_token(): "update_time": None, "update_date": None } - if req.get("canvas_ids"): - obj["dialog_id"] = req["canvas_ids"] + if req.get("canvas_id"): + obj["dialog_id"] = req["canvas_id"] obj["source"] = "agent" else: obj["dialog_id"] = req["dialog_id"] From ecbf5075cfb22cba5d08939d26bcb5ab512fde98 Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:31:58 +0800 Subject: [PATCH 10/11] Update api_app.py --- api/apps/api_app.py | 69 +++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/api/apps/api_app.py b/api/apps/api_app.py index 2b85d6fa2f2..2db920cb044 100644 --- a/api/apps/api_app.py +++ b/api/apps/api_app.py @@ -205,6 +205,23 @@ def completion(): continue msg.append({"role": m["role"], "content": m["content"]}) + def fillin_conv(ans): + nonlocal conv + if not conv.reference: + conv.reference.append(ans["reference"]) + else: + conv.reference[-1] = ans["reference"] + conv.message[-1] = {"role": "assistant", "content": ans["answer"]} + + def rename_field(ans): + reference = ans['reference'] + if not isinstance(reference, dict): + return + for chunk_i in reference.get('chunks', []): + if 'docnm_kwd' in chunk_i: + chunk_i['doc_name'] = chunk_i['docnm_kwd'] + chunk_i.pop('docnm_kwd') + try: if conv.source == "agent": stream = req.get("stream", True) @@ -223,23 +240,6 @@ def completion(): conv.message.append({"role": "assistant", "content": ""}) conv.reference.append({"chunks": [], "doc_aggs": []}) - def fillin_conv(ans): - nonlocal conv - if not conv.reference: - conv.reference.append(ans["reference"]) - else: - conv.reference[-1] = ans["reference"] - conv.message[-1] = {"role": "assistant", "content": ans["answer"]} - - def rename_field(ans): - reference = ans['reference'] - if not isinstance(reference, dict): - return - for chunk_i in reference.get('chunks', []): - if 'docnm_kwd' in chunk_i: - chunk_i['doc_name'] = chunk_i['docnm_kwd'] - chunk_i.pop('docnm_kwd') - final_ans = {"reference": [], "content": ""} canvas = Canvas(cvs.dsl, objs[0].tenant_id) @@ -310,23 +310,6 @@ def sse(): conv.message.append({"role": "assistant", "content": ""}) conv.reference.append({"chunks": [], "doc_aggs": []}) - def fillin_conv(ans): - nonlocal conv - if not conv.reference: - conv.reference.append(ans["reference"]) - else: - conv.reference[-1] = ans["reference"] - conv.message[-1] = {"role": "assistant", "content": ans["answer"]} - - def rename_field(ans): - reference = ans['reference'] - if not isinstance(reference, dict): - return - for chunk_i in reference.get('chunks', []): - if 'docnm_kwd' in chunk_i: - chunk_i['doc_name'] = chunk_i['docnm_kwd'] - chunk_i.pop('docnm_kwd') - def stream(): nonlocal dia, msg, req, conv try: @@ -349,16 +332,16 @@ def stream(): resp.headers.add_header("X-Accel-Buffering", "no") resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8") return resp - else: - answer = None - for ans in chat(dia, msg, **req): - answer = ans - fillin_conv(ans) - API4ConversationService.append_message(conv.id, conv.to_dict()) - break + + answer = None + for ans in chat(dia, msg, **req): + answer = ans + fillin_conv(ans) + API4ConversationService.append_message(conv.id, conv.to_dict()) + break - rename_field(answer) - return get_json_result(data=answer) + rename_field(answer) + return get_json_result(data=answer) except Exception as e: return server_error_response(e) From eb2c31a6553689d35f53286cf62618fe722c4af7 Mon Sep 17 00:00:00 2001 From: H <43509927+guoyuhao2330@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:50:25 +0800 Subject: [PATCH 11/11] Update api_app.py --- api/apps/api_app.py | 90 +++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 49 deletions(-) diff --git a/api/apps/api_app.py b/api/apps/api_app.py index 2db920cb044..eb9bd6c520e 100644 --- a/api/apps/api_app.py +++ b/api/apps/api_app.py @@ -158,10 +158,6 @@ def set_conversation(): "source": "agent" } API4ConversationService.save(**conv) - e, conv = API4ConversationService.get_by_id(conv["id"]) - if not e: - return get_data_error_result(retmsg="Fail to new a conversation!") - conv = conv.to_dict() return get_json_result(data=conv) else: e, dia = DialogService.get_by_id(objs[0].dialog_id) @@ -174,10 +170,6 @@ def set_conversation(): "message": [{"role": "assistant", "content": dia.prompt_config["prologue"]}] } API4ConversationService.save(**conv) - e, conv = API4ConversationService.get_by_id(conv["id"]) - if not e: - return get_data_error_result(retmsg="Fail to new a conversation!") - conv = conv.to_dict() return get_json_result(data=conv) except Exception as e: return server_error_response(e) @@ -297,51 +289,51 @@ def sse(): break rename_field(result) return get_json_result(data=result) - else: - conv.message.append(msg[-1]) - e, dia = DialogService.get_by_id(conv.dialog_id) - if not e: - return get_data_error_result(retmsg="Dialog not found!") - del req["conversation_id"] - del req["messages"] + + #******************For dialog****************** + conv.message.append(msg[-1]) + e, dia = DialogService.get_by_id(conv.dialog_id) + if not e: + return get_data_error_result(retmsg="Dialog not found!") + del req["conversation_id"] + del req["messages"] - if not conv.reference: - conv.reference = [] - conv.message.append({"role": "assistant", "content": ""}) - conv.reference.append({"chunks": [], "doc_aggs": []}) + if not conv.reference: + conv.reference = [] + conv.message.append({"role": "assistant", "content": ""}) + conv.reference.append({"chunks": [], "doc_aggs": []}) - def stream(): - nonlocal dia, msg, req, conv - try: - for ans in chat(dia, msg, True, **req): - fillin_conv(ans) - rename_field(ans) - yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans}, - ensure_ascii=False) + "\n\n" - API4ConversationService.append_message(conv.id, conv.to_dict()) - except Exception as e: - yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e), - "data": {"answer": "**ERROR**: " + str(e), "reference": []}}, + def stream(): + nonlocal dia, msg, req, conv + try: + for ans in chat(dia, msg, True, **req): + fillin_conv(ans) + rename_field(ans) + yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": ans}, ensure_ascii=False) + "\n\n" - yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n" - - if req.get("stream", True): - resp = Response(stream(), mimetype="text/event-stream") - resp.headers.add_header("Cache-control", "no-cache") - resp.headers.add_header("Connection", "keep-alive") - resp.headers.add_header("X-Accel-Buffering", "no") - resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8") - return resp - - answer = None - for ans in chat(dia, msg, **req): - answer = ans - fillin_conv(ans) API4ConversationService.append_message(conv.id, conv.to_dict()) - break - - rename_field(answer) - return get_json_result(data=answer) + except Exception as e: + yield "data:" + json.dumps({"retcode": 500, "retmsg": str(e), + "data": {"answer": "**ERROR**: " + str(e), "reference": []}}, + ensure_ascii=False) + "\n\n" + yield "data:" + json.dumps({"retcode": 0, "retmsg": "", "data": True}, ensure_ascii=False) + "\n\n" + + if req.get("stream", True): + resp = Response(stream(), mimetype="text/event-stream") + resp.headers.add_header("Cache-control", "no-cache") + resp.headers.add_header("Connection", "keep-alive") + resp.headers.add_header("X-Accel-Buffering", "no") + resp.headers.add_header("Content-Type", "text/event-stream; charset=utf-8") + return resp + + answer = None + for ans in chat(dia, msg, **req): + answer = ans + fillin_conv(ans) + API4ConversationService.append_message(conv.id, conv.to_dict()) + break + rename_field(answer) + return get_json_result(data=answer) except Exception as e: return server_error_response(e)