From e9ce0b10dee35fd414f7aace5fa3997b23c91387 Mon Sep 17 00:00:00 2001 From: Nam Vu Date: Sun, 23 Jun 2024 15:47:44 +0700 Subject: [PATCH 001/161] feat: add Asia/Ho_Chi_Minh timezone (#5521) --- api/core/tools/provider/builtin/time/tools/current_time.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/core/tools/provider/builtin/time/tools/current_time.yaml b/api/core/tools/provider/builtin/time/tools/current_time.yaml index dbdd39e223..52705ace4c 100644 --- a/api/core/tools/provider/builtin/time/tools/current_time.yaml +++ b/api/core/tools/provider/builtin/time/tools/current_time.yaml @@ -69,6 +69,11 @@ parameters: en_US: Asia/Shanghai zh_Hans: 亚洲/上海 pt_BR: Asia/Shanghai + - value: Asia/Ho_Chi_Minh + label: + en_US: Asia/Ho_Chi_Minh + zh_Hans: 亚洲/胡志明市 + pt_BR: Ásia/Ho Chi Minh - value: Asia/Tokyo label: en_US: Asia/Tokyo From 3a626cd2513abd96b7c5bb7504fa64eb3ed78f28 Mon Sep 17 00:00:00 2001 From: Xiao Ley Date: Sun, 23 Jun 2024 17:59:03 +0800 Subject: [PATCH 002/161] fix: added error handling for novita ai tool query (#5506) Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- .../builtin/novitaai/tools/novitaai_modelquery.py | 11 ++++++----- .../builtin/novitaai/tools/novitaai_modelquery.yaml | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/api/core/tools/provider/builtin/novitaai/tools/novitaai_modelquery.py b/api/core/tools/provider/builtin/novitaai/tools/novitaai_modelquery.py index 637dd70e55..ec2927675e 100644 --- a/api/core/tools/provider/builtin/novitaai/tools/novitaai_modelquery.py +++ b/api/core/tools/provider/builtin/novitaai/tools/novitaai_modelquery.py @@ -42,17 +42,18 @@ class NovitaAiModelQueryTool(BuiltinTool): result_str = '' if result_type == 'first sd_name': - result_str = models_data[0]['sd_name_in_api'] + result_str = models_data[0]['sd_name_in_api'] if len(models_data) > 0 else '' elif result_type == 'first name sd_name pair': - result_str = json.dumps({'name': models_data[0]['name'], 'sd_name': models_data[0]['sd_name_in_api']}) + result_str = json.dumps({'name': models_data[0]['name'], 'sd_name': models_data[0]['sd_name_in_api']}) if len(models_data) > 0 else '' elif result_type == 'sd_name array': - sd_name_array = [model['sd_name_in_api'] for model in models_data] + sd_name_array = [model['sd_name_in_api'] for model in models_data] if len(models_data) > 0 else [] result_str = json.dumps(sd_name_array) elif result_type == 'name array': - name_array = [model['name'] for model in models_data] + name_array = [model['name'] for model in models_data] if len(models_data) > 0 else [] result_str = json.dumps(name_array) elif result_type == 'name sd_name pair array': - name_sd_name_pair_array = [{'name': model['name'], 'sd_name': model['sd_name_in_api']} for model in models_data] + name_sd_name_pair_array = [{'name': model['name'], 'sd_name': model['sd_name_in_api']} + for model in models_data] if len(models_data) > 0 else [] result_str = json.dumps(name_sd_name_pair_array) elif result_type == 'whole info array': result_str = json.dumps(models_data) diff --git a/api/core/tools/provider/builtin/novitaai/tools/novitaai_modelquery.yaml b/api/core/tools/provider/builtin/novitaai/tools/novitaai_modelquery.yaml index a933f76d0e..a14795e45e 100644 --- a/api/core/tools/provider/builtin/novitaai/tools/novitaai_modelquery.yaml +++ b/api/core/tools/provider/builtin/novitaai/tools/novitaai_modelquery.yaml @@ -19,7 +19,8 @@ parameters: human_description: en_US: Seaching the content of sd_name, name, tags. zh_Hans: 搜索 sd_name、name、tags 中的内容 - form: form + llm_description: Enter the content to search + form: llm - name: result_type type: select default: "first sd_name" From ea29007bc0bb34203d532ff65a22e687749733a8 Mon Sep 17 00:00:00 2001 From: kurokobo Date: Mon, 24 Jun 2024 01:45:33 +0900 Subject: [PATCH 003/161] fix: apply best practices for the latest buildkit (#5527) --- api/Dockerfile | 22 +++++++++++----------- web/Dockerfile | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/api/Dockerfile b/api/Dockerfile index 15fd9d88e0..4f0e7f65e3 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -1,5 +1,5 @@ # base image -FROM python:3.10-slim-bookworm as base +FROM python:3.10-slim-bookworm AS base WORKDIR /app/api @@ -14,7 +14,7 @@ ENV POETRY_NO_INTERACTION=1 ENV POETRY_VIRTUALENVS_IN_PROJECT=true ENV POETRY_VIRTUALENVS_CREATE=true -FROM base as packages +FROM base AS packages RUN apt-get update \ && apt-get install -y --no-install-recommends gcc g++ libc-dev libffi-dev libgmp-dev libmpfr-dev libmpc-dev @@ -27,18 +27,18 @@ RUN poetry install --sync --no-cache --no-root # production stage FROM base AS production -ENV FLASK_APP app.py -ENV EDITION SELF_HOSTED -ENV DEPLOY_ENV PRODUCTION -ENV CONSOLE_API_URL http://127.0.0.1:5001 -ENV CONSOLE_WEB_URL http://127.0.0.1:3000 -ENV SERVICE_API_URL http://127.0.0.1:5001 -ENV APP_WEB_URL http://127.0.0.1:3000 +ENV FLASK_APP=app.py +ENV EDITION=SELF_HOSTED +ENV DEPLOY_ENV=PRODUCTION +ENV CONSOLE_API_URL=http://127.0.0.1:5001 +ENV CONSOLE_WEB_URL=http://127.0.0.1:3000 +ENV SERVICE_API_URL=http://127.0.0.1:5001 +ENV APP_WEB_URL=http://127.0.0.1:3000 EXPOSE 5001 # set timezone -ENV TZ UTC +ENV TZ=UTC WORKDIR /app/api @@ -61,6 +61,6 @@ RUN chmod +x /entrypoint.sh ARG COMMIT_SHA -ENV COMMIT_SHA ${COMMIT_SHA} +ENV COMMIT_SHA=${COMMIT_SHA} ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] diff --git a/web/Dockerfile b/web/Dockerfile index f2fc4af2f8..56957f0927 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -9,7 +9,7 @@ RUN apk add --no-cache tzdata # install packages -FROM base as packages +FROM base AS packages WORKDIR /app/web @@ -22,7 +22,7 @@ COPY yarn.lock . RUN yarn install --frozen-lockfile # build resources -FROM base as builder +FROM base AS builder WORKDIR /app/web COPY --from=packages /app/web/ . COPY . . @@ -31,17 +31,17 @@ RUN yarn build # production stage -FROM base as production +FROM base AS production -ENV NODE_ENV production -ENV EDITION SELF_HOSTED -ENV DEPLOY_ENV PRODUCTION -ENV CONSOLE_API_URL http://127.0.0.1:5001 -ENV APP_API_URL http://127.0.0.1:5001 -ENV PORT 3000 +ENV NODE_ENV=production +ENV EDITION=SELF_HOSTED +ENV DEPLOY_ENV=PRODUCTION +ENV CONSOLE_API_URL=http://127.0.0.1:5001 +ENV APP_API_URL=http://127.0.0.1:5001 +ENV PORT=3000 # set timezone -ENV TZ UTC +ENV TZ=UTC RUN ln -s /usr/share/zoneinfo/${TZ} /etc/localtime \ && echo ${TZ} > /etc/timezone @@ -59,7 +59,7 @@ COPY docker/pm2.json ./pm2.json COPY docker/entrypoint.sh ./entrypoint.sh ARG COMMIT_SHA -ENV COMMIT_SHA ${COMMIT_SHA} +ENV COMMIT_SHA=${COMMIT_SHA} EXPOSE 3000 ENTRYPOINT ["/bin/sh", "./entrypoint.sh"] From dcec9d7bb7b530a01607f8edb7defe808f22b599 Mon Sep 17 00:00:00 2001 From: Xiao Ley Date: Mon, 24 Jun 2024 01:06:26 +0800 Subject: [PATCH 004/161] feat: add new features to enhance image and link handling in Jina tool (#5517) --- .../builtin/jina/tools/jina_reader.py | 19 ++++++--- .../builtin/jina/tools/jina_reader.yaml | 42 +++++++++++++++++++ .../builtin/jina/tools/jina_search.py | 9 ++++ .../builtin/jina/tools/jina_search.yaml | 42 +++++++++++++++++++ 4 files changed, 107 insertions(+), 5 deletions(-) diff --git a/api/core/tools/provider/builtin/jina/tools/jina_reader.py b/api/core/tools/provider/builtin/jina/tools/jina_reader.py index b0bd478846..0d0eaef25b 100644 --- a/api/core/tools/provider/builtin/jina/tools/jina_reader.py +++ b/api/core/tools/provider/builtin/jina/tools/jina_reader.py @@ -10,10 +10,10 @@ from core.tools.tool.builtin_tool import BuiltinTool class JinaReaderTool(BuiltinTool): _jina_reader_endpoint = 'https://r.jina.ai/' - def _invoke(self, + def _invoke(self, user_id: str, - tool_parameters: dict[str, Any], - ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]: + tool_parameters: dict[str, Any], + ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]: """ invoke tools """ @@ -34,6 +34,15 @@ class JinaReaderTool(BuiltinTool): if wait_for_selector is not None and wait_for_selector != '': headers['X-Wait-For-Selector'] = wait_for_selector + if tool_parameters.get('image_caption', False): + headers['X-With-Generated-Alt'] = 'true' + + if tool_parameters.get('gather_all_links_at_the_end', False): + headers['X-With-Links-Summary'] = 'true' + + if tool_parameters.get('gather_all_images_at_the_end', False): + headers['X-With-Images-Summary'] = 'true' + proxy_server = tool_parameters.get('proxy_server', None) if proxy_server is not None and proxy_server != '': headers['X-Proxy-Url'] = proxy_server @@ -42,12 +51,12 @@ class JinaReaderTool(BuiltinTool): headers['X-No-Cache'] = 'true' response = ssrf_proxy.get( - str(URL(self._jina_reader_endpoint + url)), + str(URL(self._jina_reader_endpoint + url)), headers=headers, timeout=(10, 60) ) if tool_parameters.get('summary', False): return self.create_text_message(self.summary(user_id, response.text)) - + return self.create_text_message(response.text) diff --git a/api/core/tools/provider/builtin/jina/tools/jina_reader.yaml b/api/core/tools/provider/builtin/jina/tools/jina_reader.yaml index 703fa3d389..5eb2692ea5 100644 --- a/api/core/tools/provider/builtin/jina/tools/jina_reader.yaml +++ b/api/core/tools/provider/builtin/jina/tools/jina_reader.yaml @@ -51,6 +51,48 @@ parameters: pt_BR: css selector for waiting for specific elements llm_description: css selector of the target element to wait for form: form + - name: image_caption + type: boolean + required: false + default: false + label: + en_US: Image caption + zh_Hans: 图片说明 + pt_BR: Legenda da imagem + human_description: + en_US: "Captions all images at the specified URL, adding 'Image [idx]: [caption]' as an alt tag for those without one. This allows downstream LLMs to interact with the images in activities such as reasoning and summarizing." + zh_Hans: "为指定 URL 上的所有图像添加标题,为没有标题的图像添加“Image [idx]: [caption]”作为 alt 标签。这允许下游 LLM 在推理和总结等活动中与图像进行交互。" + pt_BR: "Captions all images at the specified URL, adding 'Image [idx]: [caption]' as an alt tag for those without one. This allows downstream LLMs to interact with the images in activities such as reasoning and summarizing." + llm_description: Captions all images at the specified URL + form: form + - name: gather_all_links_at_the_end + type: boolean + required: false + default: false + label: + en_US: Gather all links at the end + zh_Hans: 将所有链接集中到最后 + pt_BR: Coletar todos os links ao final + human_description: + en_US: A "Buttons & Links" section will be created at the end. This helps the downstream LLMs or web agents navigating the page or take further actions. + zh_Hans: 最后会创建一个“按钮和链接”部分。这可以帮助下游 LLM 或 Web 代理浏览页面或采取进一步的行动。 + pt_BR: A "Buttons & Links" section will be created at the end. This helps the downstream LLMs or web agents navigating the page or take further actions. + llm_description: Gather all links at the end + form: form + - name: gather_all_images_at_the_end + type: boolean + required: false + default: false + label: + en_US: Gather all images at the end + zh_Hans: 将所有图片集中到最后 + pt_BR: Coletar todas as imagens ao final + human_description: + en_US: An "Images" section will be created at the end. This gives the downstream LLMs an overview of all visuals on the page, which may improve reasoning. + zh_Hans: 最后会创建一个“图像”部分。这可以让下游的 LLM 概览页面上的所有视觉效果,从而提高推理能力。 + pt_BR: An "Images" section will be created at the end. This gives the downstream LLMs an overview of all visuals on the page, which may improve reasoning. + llm_description: Gather all images at the end + form: form - name: proxy_server type: string required: false diff --git a/api/core/tools/provider/builtin/jina/tools/jina_search.py b/api/core/tools/provider/builtin/jina/tools/jina_search.py index c13f58d0cd..3eda2c5a22 100644 --- a/api/core/tools/provider/builtin/jina/tools/jina_search.py +++ b/api/core/tools/provider/builtin/jina/tools/jina_search.py @@ -24,6 +24,15 @@ class JinaSearchTool(BuiltinTool): if 'api_key' in self.runtime.credentials and self.runtime.credentials.get('api_key'): headers['Authorization'] = "Bearer " + self.runtime.credentials.get('api_key') + if tool_parameters.get('image_caption', False): + headers['X-With-Generated-Alt'] = 'true' + + if tool_parameters.get('gather_all_links_at_the_end', False): + headers['X-With-Links-Summary'] = 'true' + + if tool_parameters.get('gather_all_images_at_the_end', False): + headers['X-With-Images-Summary'] = 'true' + proxy_server = tool_parameters.get('proxy_server', None) if proxy_server is not None and proxy_server != '': headers['X-Proxy-Url'] = proxy_server diff --git a/api/core/tools/provider/builtin/jina/tools/jina_search.yaml b/api/core/tools/provider/builtin/jina/tools/jina_search.yaml index f3b6c0737a..da0a300c6c 100644 --- a/api/core/tools/provider/builtin/jina/tools/jina_search.yaml +++ b/api/core/tools/provider/builtin/jina/tools/jina_search.yaml @@ -22,6 +22,48 @@ parameters: zh_Hans: 在网络上搜索信息 llm_description: simple question to ask on the web form: llm + - name: image_caption + type: boolean + required: false + default: false + label: + en_US: Image caption + zh_Hans: 图片说明 + pt_BR: Legenda da imagem + human_description: + en_US: "Captions all images at the specified URL, adding 'Image [idx]: [caption]' as an alt tag for those without one. This allows downstream LLMs to interact with the images in activities such as reasoning and summarizing." + zh_Hans: "为指定 URL 上的所有图像添加标题,为没有标题的图像添加“Image [idx]: [caption]”作为 alt 标签。这允许下游 LLM 在推理和总结等活动中与图像进行交互。" + pt_BR: "Captions all images at the specified URL, adding 'Image [idx]: [caption]' as an alt tag for those without one. This allows downstream LLMs to interact with the images in activities such as reasoning and summarizing." + llm_description: Captions all images at the specified URL + form: form + - name: gather_all_links_at_the_end + type: boolean + required: false + default: false + label: + en_US: Gather all links at the end + zh_Hans: 将所有链接集中到最后 + pt_BR: Coletar todos os links ao final + human_description: + en_US: A "Buttons & Links" section will be created at the end. This helps the downstream LLMs or web agents navigating the page or take further actions. + zh_Hans: 最后会创建一个“按钮和链接”部分。这可以帮助下游 LLM 或 Web 代理浏览页面或采取进一步的行动。 + pt_BR: A "Buttons & Links" section will be created at the end. This helps the downstream LLMs or web agents navigating the page or take further actions. + llm_description: Gather all links at the end + form: form + - name: gather_all_images_at_the_end + type: boolean + required: false + default: false + label: + en_US: Gather all images at the end + zh_Hans: 将所有图片集中到最后 + pt_BR: Coletar todas as imagens ao final + human_description: + en_US: An "Images" section will be created at the end. This gives the downstream LLMs an overview of all visuals on the page, which may improve reasoning. + zh_Hans: 最后会创建一个“图像”部分。这可以让下游的 LLM 概览页面上的所有视觉效果,从而提高推理能力。 + pt_BR: An "Images" section will be created at the end. This gives the downstream LLMs an overview of all visuals on the page, which may improve reasoning. + llm_description: Gather all images at the end + form: form - name: proxy_server type: string required: false From 47a5d4527bab9d840411fe4684242c0e0b27e45f Mon Sep 17 00:00:00 2001 From: crazywoola <100913391+crazywoola@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:53:26 +0800 Subject: [PATCH 005/161] feat: use root dir to start python and celery (#5515) --- {api/.vscode => .vscode}/launch.json | 47 ++++++++++++++-------------- 1 file changed, 23 insertions(+), 24 deletions(-) rename {api/.vscode => .vscode}/launch.json (71%) diff --git a/api/.vscode/launch.json b/.vscode/launch.json similarity index 71% rename from api/.vscode/launch.json rename to .vscode/launch.json index 2039d2ca94..55fdbb8b50 100644 --- a/api/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,30 +1,16 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { - "name": "Python: Celery", - "type": "debugpy", - "request": "launch", - "module": "celery", - "justMyCode": true, - "args": ["-A", "app.celery", "worker", "-P", "gevent", "-c", "1", "--loglevel", "info", "-Q", "dataset,generation,mail"], - "envFile": "${workspaceFolder}/.env", - "env": { - "FLASK_APP": "app.py", - "FLASK_DEBUG": "1", - "GEVENT_SUPPORT": "True" - }, - "console": "integratedTerminal", - "python": "${command:python.interpreterPath}" - }, { "name": "Python: Flask", "type": "debugpy", "request": "launch", + "python": "${workspaceFolder}/api/.venv/bin/python", + "cwd": "${workspaceFolder}/api", + "envFile": ".env", "module": "flask", + "justMyCode": true, + "jinja": true, "env": { "FLASK_APP": "app.py", "FLASK_DEBUG": "1", @@ -34,11 +20,24 @@ "run", "--host=0.0.0.0", "--port=5001", - "--debug" - ], - "jinja": true, + ] + }, + { + "name": "Python: Celery", + "type": "debugpy", + "request": "launch", + "python": "${workspaceFolder}/api/.venv/bin/python", + "cwd": "${workspaceFolder}/api", + "module": "celery", "justMyCode": true, - "python": "${command:python.interpreterPath}" - } + "envFile": ".env", + "console": "integratedTerminal", + "env": { + "FLASK_APP": "app.py", + "FLASK_DEBUG": "1", + "GEVENT_SUPPORT": "True" + }, + "args": ["-A", "app.celery", "worker", "-P", "gevent", "-c", "1", "--loglevel", "info", "-Q", "dataset,generation,mail"], + }, ] } \ No newline at end of file From 8294e97113484a32e05a693a72e1d390c28d607c Mon Sep 17 00:00:00 2001 From: KVOJJJin Date: Mon, 24 Jun 2024 12:29:14 +0800 Subject: [PATCH 006/161] Chore: chat log refactor (#5523) --- web/app/(shareLayout)/chat/[token]/page.tsx | 5 +- .../(shareLayout)/chatbot/[token]/page.tsx | 4 +- .../(shareLayout)/completion/[token]/page.tsx | 7 +- .../(shareLayout)/workflow/[token]/page.tsx | 6 +- web/app/components/app/chat/answer/index.tsx | 428 -------- .../app/chat/icon-component/index.tsx | 43 - web/app/components/app/chat/icons/answer.svg | 3 - .../app/chat/icons/default-avatar.jpg | Bin 2183 -> 0 bytes web/app/components/app/chat/icons/edit.svg | 3 - .../components/app/chat/icons/question.svg | 3 - web/app/components/app/chat/icons/robot.svg | 10 - .../components/app/chat/icons/send-active.svg | 3 - web/app/components/app/chat/icons/send.svg | 3 - web/app/components/app/chat/icons/typing.svg | 19 - web/app/components/app/chat/icons/user.svg | 10 - web/app/components/app/chat/index.tsx | 455 --------- .../components/app/chat/more-info/index.tsx | 23 - .../components/app/chat/operation/index.tsx | 14 - .../components/app/chat/question/index.tsx | 52 - web/app/components/app/chat/style.module.css | 136 --- .../app/chat/thought/style.module.css | 7 - .../debug-with-multiple-model/chat-item.tsx | 4 +- .../debug/debug-with-single-model/index.tsx | 4 +- web/app/components/app/log/list.tsx | 157 ++- .../app/overview/embedded/index.tsx | 2 +- web/app/components/app/store.ts | 2 +- .../app/text-generate/item/index.tsx | 2 +- .../base/agent-log-modal/detail.tsx | 2 +- .../components/base/agent-log-modal/index.tsx | 2 +- .../chat-with-history/config-panel/index.tsx | 4 +- .../chat/chat-with-history/sidebar/index.tsx | 2 +- .../sidebar/rename-modal.tsx} | 0 .../base/chat/chat/answer/agent-content.tsx | 2 +- .../base/chat/chat/answer/index.tsx | 4 +- .../base/chat/chat/answer/operation.tsx | 4 +- .../chat}/chat/citation/index.tsx | 0 .../chat}/chat/citation/popup.tsx | 0 .../chat}/chat/citation/progress-tooltip.tsx | 0 .../chat}/chat/citation/tooltip.tsx | 0 web/app/components/base/chat/chat/index.tsx | 3 + .../chat}/chat/loading-anim/index.tsx | 0 .../chat}/chat/loading-anim/style.module.css | 0 .../{app => base/chat}/chat/log/index.tsx | 2 +- .../{app => base/chat}/chat/thought/index.tsx | 2 +- .../{app => base/chat}/chat/thought/panel.tsx | 0 .../{app => base/chat}/chat/thought/tool.tsx | 0 .../{app => base/chat}/chat/type.ts | 2 +- .../embedded-chatbot/config-panel/index.tsx | 4 +- .../base/chat/embedded-chatbot/header.tsx | 9 +- web/app/components/base/chat/types.ts | 2 +- .../{app/chat => base}/copy-btn/index.tsx | 0 .../chat => base}/copy-btn/style.module.css | 0 web/app/components/base/markdown.tsx | 6 +- .../{app/chat => base}/mermaid/index.tsx | 0 .../base/message-log-modal/index.tsx | 2 +- .../base/prompt-log-modal/index.tsx | 2 +- .../{app/chat => base}/svg/index.tsx | 0 .../{app/chat => base}/svg/style.module.css | 0 .../share/chat/config-scence/index.tsx | 13 - .../share/chat/hooks/use-conversation.ts | 73 -- web/app/components/share/chat/index.tsx | 953 ------------------ .../share/chat/sidebar/app-info/index.tsx | 28 - .../share/chat/sidebar/card.module.css | 3 - .../components/share/chat/sidebar/card.tsx | 19 - .../components/share/chat/sidebar/index.tsx | 167 --- .../share/chat/sidebar/list/index.tsx | 143 --- .../share/chat/sidebar/list/item.tsx | 77 -- .../share/chat/value-panel/index.tsx | 77 -- .../share/chat/value-panel/style.module.css | 3 - .../components/share/chat/welcome/index.tsx | 388 ------- .../share/chat/welcome/massive-component.tsx | 74 -- .../share/chat/welcome/style.module.css | 22 - .../share/chatbot/config-scence/index.tsx | 13 - .../share/chatbot/hooks/use-conversation.ts | 72 -- web/app/components/share/chatbot/index.tsx | 824 --------------- .../share/chatbot/sidebar/app-info/index.tsx | 28 - .../share/chatbot/sidebar/card.module.css | 3 - .../components/share/chatbot/sidebar/card.tsx | 19 - .../share/chatbot/sidebar/index.tsx | 152 --- .../share/chatbot/sidebar/list/index.tsx | 115 --- .../chatbot/sidebar/list/style.module.css | 7 - .../share/chatbot/value-panel/index.tsx | 77 -- .../chatbot/value-panel/style.module.css | 3 - .../share/chatbot/welcome/index.tsx | 389 ------- .../chatbot/welcome/massive-component.tsx | 75 -- .../share/chatbot/welcome/style.module.css | 22 - web/app/components/share/header.tsx | 88 -- .../share/text-generation/result/content.tsx | 2 +- .../share/text-generation/result/header.tsx | 2 +- .../share/text-generation/result/index.tsx | 2 +- web/app/components/tools/utils/index.ts | 2 +- .../workflow/panel/chat-record/index.tsx | 10 +- .../components/workflow/run/output-panel.tsx | 2 +- .../components/workflow/run/result-text.tsx | 2 +- web/service/base.ts | 2 +- web/service/debug.ts | 2 +- web/service/share.ts | 2 +- 97 files changed, 165 insertions(+), 5249 deletions(-) delete mode 100644 web/app/components/app/chat/answer/index.tsx delete mode 100644 web/app/components/app/chat/icon-component/index.tsx delete mode 100644 web/app/components/app/chat/icons/answer.svg delete mode 100644 web/app/components/app/chat/icons/default-avatar.jpg delete mode 100644 web/app/components/app/chat/icons/edit.svg delete mode 100644 web/app/components/app/chat/icons/question.svg delete mode 100644 web/app/components/app/chat/icons/robot.svg delete mode 100644 web/app/components/app/chat/icons/send-active.svg delete mode 100644 web/app/components/app/chat/icons/send.svg delete mode 100644 web/app/components/app/chat/icons/typing.svg delete mode 100644 web/app/components/app/chat/icons/user.svg delete mode 100644 web/app/components/app/chat/index.tsx delete mode 100644 web/app/components/app/chat/more-info/index.tsx delete mode 100644 web/app/components/app/chat/operation/index.tsx delete mode 100644 web/app/components/app/chat/question/index.tsx delete mode 100644 web/app/components/app/chat/style.module.css delete mode 100644 web/app/components/app/chat/thought/style.module.css rename web/app/components/{share/chat/sidebar/rename-modal/index.tsx => base/chat/chat-with-history/sidebar/rename-modal.tsx} (100%) rename web/app/components/{app => base/chat}/chat/citation/index.tsx (100%) rename web/app/components/{app => base/chat}/chat/citation/popup.tsx (100%) rename web/app/components/{app => base/chat}/chat/citation/progress-tooltip.tsx (100%) rename web/app/components/{app => base/chat}/chat/citation/tooltip.tsx (100%) rename web/app/components/{app => base/chat}/chat/loading-anim/index.tsx (100%) rename web/app/components/{app => base/chat}/chat/loading-anim/style.module.css (100%) rename web/app/components/{app => base/chat}/chat/log/index.tsx (95%) rename web/app/components/{app => base/chat}/chat/thought/index.tsx (96%) rename web/app/components/{app => base/chat}/chat/thought/panel.tsx (100%) rename web/app/components/{app => base/chat}/chat/thought/tool.tsx (100%) rename web/app/components/{app => base/chat}/chat/type.ts (95%) rename web/app/components/{app/chat => base}/copy-btn/index.tsx (100%) rename web/app/components/{app/chat => base}/copy-btn/style.module.css (100%) rename web/app/components/{app/chat => base}/mermaid/index.tsx (100%) rename web/app/components/{app/chat => base}/svg/index.tsx (100%) rename web/app/components/{app/chat => base}/svg/style.module.css (100%) delete mode 100644 web/app/components/share/chat/config-scence/index.tsx delete mode 100644 web/app/components/share/chat/hooks/use-conversation.ts delete mode 100644 web/app/components/share/chat/index.tsx delete mode 100644 web/app/components/share/chat/sidebar/app-info/index.tsx delete mode 100644 web/app/components/share/chat/sidebar/card.module.css delete mode 100644 web/app/components/share/chat/sidebar/card.tsx delete mode 100644 web/app/components/share/chat/sidebar/index.tsx delete mode 100644 web/app/components/share/chat/sidebar/list/index.tsx delete mode 100644 web/app/components/share/chat/sidebar/list/item.tsx delete mode 100644 web/app/components/share/chat/value-panel/index.tsx delete mode 100644 web/app/components/share/chat/value-panel/style.module.css delete mode 100644 web/app/components/share/chat/welcome/index.tsx delete mode 100644 web/app/components/share/chat/welcome/massive-component.tsx delete mode 100644 web/app/components/share/chat/welcome/style.module.css delete mode 100644 web/app/components/share/chatbot/config-scence/index.tsx delete mode 100644 web/app/components/share/chatbot/hooks/use-conversation.ts delete mode 100644 web/app/components/share/chatbot/index.tsx delete mode 100644 web/app/components/share/chatbot/sidebar/app-info/index.tsx delete mode 100644 web/app/components/share/chatbot/sidebar/card.module.css delete mode 100644 web/app/components/share/chatbot/sidebar/card.tsx delete mode 100644 web/app/components/share/chatbot/sidebar/index.tsx delete mode 100644 web/app/components/share/chatbot/sidebar/list/index.tsx delete mode 100644 web/app/components/share/chatbot/sidebar/list/style.module.css delete mode 100644 web/app/components/share/chatbot/value-panel/index.tsx delete mode 100644 web/app/components/share/chatbot/value-panel/style.module.css delete mode 100644 web/app/components/share/chatbot/welcome/index.tsx delete mode 100644 web/app/components/share/chatbot/welcome/massive-component.tsx delete mode 100644 web/app/components/share/chatbot/welcome/style.module.css delete mode 100644 web/app/components/share/header.tsx diff --git a/web/app/(shareLayout)/chat/[token]/page.tsx b/web/app/(shareLayout)/chat/[token]/page.tsx index 56b2e0da7d..640c40378f 100644 --- a/web/app/(shareLayout)/chat/[token]/page.tsx +++ b/web/app/(shareLayout)/chat/[token]/page.tsx @@ -1,11 +1,8 @@ 'use client' -import type { FC } from 'react' import React from 'react' - -import type { IMainProps } from '@/app/components/share/chat' import ChatWithHistoryWrap from '@/app/components/base/chat/chat-with-history' -const Chat: FC = () => { +const Chat = () => { return ( ) diff --git a/web/app/(shareLayout)/chatbot/[token]/page.tsx b/web/app/(shareLayout)/chatbot/[token]/page.tsx index b78680c503..1db5c7e458 100644 --- a/web/app/(shareLayout)/chatbot/[token]/page.tsx +++ b/web/app/(shareLayout)/chatbot/[token]/page.tsx @@ -1,14 +1,12 @@ 'use client' -import type { FC } from 'react' import React, { useEffect } from 'react' import cn from 'classnames' -import type { IMainProps } from '@/app/components/share/chat' import EmbeddedChatbot from '@/app/components/base/chat/embedded-chatbot' import Loading from '@/app/components/base/loading' import { fetchSystemFeatures } from '@/service/share' import LogoSite from '@/app/components/base/logo/logo-site' -const Chatbot: FC = () => { +const Chatbot = () => { const [isSSOEnforced, setIsSSOEnforced] = React.useState(true) const [loading, setLoading] = React.useState(true) diff --git a/web/app/(shareLayout)/completion/[token]/page.tsx b/web/app/(shareLayout)/completion/[token]/page.tsx index 28bbfa68da..e8bc9d79f5 100644 --- a/web/app/(shareLayout)/completion/[token]/page.tsx +++ b/web/app/(shareLayout)/completion/[token]/page.tsx @@ -1,13 +1,10 @@ -import type { FC } from 'react' import React from 'react' - -import type { IMainProps } from '@/app/components/share/chat' import Main from '@/app/components/share/text-generation' -const TextGeneration: FC = () => { +const Completion = () => { return (
) } -export default React.memo(TextGeneration) +export default React.memo(Completion) diff --git a/web/app/(shareLayout)/workflow/[token]/page.tsx b/web/app/(shareLayout)/workflow/[token]/page.tsx index c1d7fa13a5..e93bc8c1af 100644 --- a/web/app/(shareLayout)/workflow/[token]/page.tsx +++ b/web/app/(shareLayout)/workflow/[token]/page.tsx @@ -1,13 +1,11 @@ -import type { FC } from 'react' import React from 'react' -import type { IMainProps } from '@/app/components/share/text-generation' import Main from '@/app/components/share/text-generation' -const TextGeneration: FC = () => { +const Workflow = () => { return (
) } -export default React.memo(TextGeneration) +export default React.memo(Workflow) diff --git a/web/app/components/app/chat/answer/index.tsx b/web/app/components/app/chat/answer/index.tsx deleted file mode 100644 index 1ba033911a..0000000000 --- a/web/app/components/app/chat/answer/index.tsx +++ /dev/null @@ -1,428 +0,0 @@ -'use client' -import type { FC, ReactNode } from 'react' -import React, { useEffect, useMemo, useRef, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { UserCircleIcon } from '@heroicons/react/24/solid' -import cn from 'classnames' -import type { CitationItem, DisplayScene, FeedbackFunc, Feedbacktype, IChatItem } from '../type' -import OperationBtn from '../operation' -import LoadingAnim from '../loading-anim' -import { RatingIcon } from '../icon-component' -import s from '../style.module.css' -import MoreInfo from '../more-info' -import CopyBtn from '../copy-btn' -import Thought from '../thought' -import Citation from '../citation' -import AudioBtn from '@/app/components/base/audio-btn' -import { randomString } from '@/utils' -import type { MessageRating } from '@/models/log' -import Tooltip from '@/app/components/base/tooltip' -import { Markdown } from '@/app/components/base/markdown' -import type { DataSet } from '@/models/datasets' -import AnnotationCtrlBtn from '@/app/components/app/configuration/toolbox/annotation/annotation-ctrl-btn' -import EditReplyModal from '@/app/components/app/annotation/edit-annotation-modal' -import { EditTitle } from '@/app/components/app/annotation/edit-annotation-modal/edit-item' -import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication' -import type { Emoji } from '@/app/components/tools/types' -import type { VisionFile } from '@/types/app' -import ImageGallery from '@/app/components/base/image-gallery' -import Log from '@/app/components/app/chat/log' - -const IconWrapper: FC<{ children: React.ReactNode | string }> = ({ children }) => { - return
- {children} -
-} -export type IAnswerProps = { - item: IChatItem - index: number - feedbackDisabled: boolean - isHideFeedbackEdit: boolean - onQueryChange: (query: string) => void - onFeedback?: FeedbackFunc - displayScene: DisplayScene - isResponding?: boolean - answerIcon?: ReactNode - citation?: CitationItem[] - dataSets?: DataSet[] - isShowCitation?: boolean - isShowCitationHitInfo?: boolean - isShowTextToSpeech?: boolean - // Annotation props - supportAnnotation?: boolean - appId?: string - question: string - onAnnotationEdited?: (question: string, answer: string, index: number) => void - onAnnotationAdded?: (annotationId: string, authorName: string, question: string, answer: string, index: number) => void - onAnnotationRemoved?: (index: number) => void - allToolIcons?: Record - isShowPromptLog?: boolean -} -// The component needs to maintain its own state to control whether to display input component -const Answer: FC = ({ - item, - index, - onQueryChange, - feedbackDisabled = false, - isHideFeedbackEdit = false, - onFeedback, - displayScene = 'web', - isResponding, - answerIcon, - citation, - isShowCitation, - isShowCitationHitInfo = false, - isShowTextToSpeech, - supportAnnotation, - appId, - question, - onAnnotationEdited, - onAnnotationAdded, - onAnnotationRemoved, - allToolIcons, - isShowPromptLog, -}) => { - const { id, content, more, feedback, adminFeedback, annotation, agent_thoughts } = item - const isAgentMode = !!agent_thoughts && agent_thoughts.length > 0 - const hasAnnotation = useMemo(() => !!annotation, [annotation]) - // const [annotation, setAnnotation] = useState(initAnnotation) - // const [inputValue, setInputValue] = useState(initAnnotation?.content ?? '') - const [localAdminFeedback, setLocalAdminFeedback] = useState(adminFeedback) - // const { userProfile } = useContext(AppContext) - const { t } = useTranslation() - - const [isShowReplyModal, setIsShowReplyModal] = useState(false) - - /** - * Render feedback results (distinguish between users and administrators) - * User reviews cannot be cancelled in Console - * @param rating feedback result - * @param isUserFeedback Whether it is user's feedback - * @param isWebScene Whether it is web scene - * @returns comp - */ - const renderFeedbackRating = (rating: MessageRating | undefined, isUserFeedback = true, isWebScene = true) => { - if (!rating) - return null - - const isLike = rating === 'like' - const ratingIconClassname = isLike ? 'text-primary-600 bg-primary-100 hover:bg-primary-200' : 'text-red-600 bg-red-100 hover:bg-red-200' - const UserSymbol = - // The tooltip is always displayed, but the content is different for different scenarios. - return ( - -
{ - const res = await onFeedback?.(id, { rating: null }) - if (res && !isWebScene) - setLocalAdminFeedback({ rating: null }) - }, - } - : {})} - > -
- -
- {!isWebScene && isUserFeedback && UserSymbol} -
-
- ) - } - - /** - * Different scenarios have different operation items. - * @param isWebScene Whether it is web scene - * @returns comp - */ - const renderItemOperation = (isWebScene = true) => { - const userOperation = () => { - return feedback?.rating - ? null - :
- - {OperationBtn({ innerContent: , onClick: () => onFeedback?.(id, { rating: 'like' }) })} - - - {OperationBtn({ innerContent: , onClick: () => onFeedback?.(id, { rating: 'dislike' }) })} - -
- } - - const adminOperation = () => { - return
- {!localAdminFeedback?.rating && <> - - {OperationBtn({ - innerContent: , - onClick: async () => { - const res = await onFeedback?.(id, { rating: 'like' }) - if (res) - setLocalAdminFeedback({ rating: 'like' }) - }, - })} - - - {OperationBtn({ - innerContent: , - onClick: async () => { - const res = await onFeedback?.(id, { rating: 'dislike' }) - if (res) - setLocalAdminFeedback({ rating: 'dislike' }) - }, - })} - - } -
- } - - return ( -
- {isWebScene ? userOperation() : adminOperation()} -
- ) - } - - const getImgs = (list?: VisionFile[]) => { - if (!list) - return [] - return list.filter(file => file.type === 'image' && file.belongs_to === 'assistant') - } - - const agentModeAnswer = ( -
- {agent_thoughts?.map((item, index) => ( -
- {item.thought && ( - - )} - {/* {item.tool} */} - {/* perhaps not use tool */} - {!!item.tool && ( - - )} - - {getImgs(item.message_files).length > 0 && ( - item.url)} /> - )} -
- ))} -
- ) - - const [containerWidth, setContainerWidth] = useState(0) - const [contentWidth, setContentWidth] = useState(0) - const containerRef = useRef(null) - const contentRef = useRef(null) - - const getContainerWidth = () => { - if (containerRef.current) - setContainerWidth(containerRef.current?.clientWidth + 24) - } - const getContentWidth = () => { - if (contentRef.current) - setContentWidth(contentRef.current?.clientWidth) - } - - useEffect(() => { - getContainerWidth() - }, []) - - useEffect(() => { - if (!isResponding) - getContentWidth() - }, [isResponding]) - - const operationWidth = useMemo(() => { - let width = 0 - if (!item.isOpeningStatement) - width += 28 - if (!item.isOpeningStatement && isShowPromptLog) - width += 102 + 8 - if (!item.isOpeningStatement && isShowTextToSpeech) - width += 33 - if (!item.isOpeningStatement && supportAnnotation) - width += 96 + 8 - if (!feedbackDisabled && !item.feedbackDisabled) - width += 60 + 8 - if (!feedbackDisabled && localAdminFeedback?.rating && !item.isOpeningStatement) - width += 60 + 8 - if (!feedbackDisabled && feedback?.rating && !item.isOpeningStatement) - width += 28 + 8 - return width - }, [item.isOpeningStatement, item.feedbackDisabled, isShowPromptLog, isShowTextToSpeech, supportAnnotation, feedbackDisabled, localAdminFeedback?.rating, feedback?.rating]) - - const positionRight = useMemo(() => operationWidth < containerWidth - contentWidth - 4, [operationWidth, containerWidth, contentWidth]) - - return ( - // data-id for debug the item message is right -
-
- { - answerIcon || ( -
- {isResponding - &&
- -
- } -
- ) - } -
-
-
-
- {(isResponding && (isAgentMode ? (!content && (agent_thoughts || []).filter(item => !!item.thought || !!item.tool).length === 0) : !content)) - ? ( -
- -
- ) - : ( -
- {annotation?.logAnnotation && ( -
-
- {isAgentMode - ? (
{agentModeAnswer}
) - : ( - - )} -
- -
- )} -
- {annotation?.logAnnotation - ? ( - - ) - : (isAgentMode - ? agentModeAnswer - : ( - - ))} -
- {(hasAnnotation && !annotation?.logAnnotation) && ( - - )} - {item.isOpeningStatement && item.suggestedQuestions && item.suggestedQuestions.filter(q => !!q && q.trim()).length > 0 && ( -
- {item.suggestedQuestions.filter(q => !!q && q.trim()).map((question, index) => ( -
onQueryChange(question)} - > - {question} -
), - )} -
- )} -
- )} - { - !!citation?.length && isShowCitation && !isResponding && ( - - ) - } -
- {hasAnnotation && ( -
-
- -
-
- )} -
- {!item.isOpeningStatement && ( - - )} - {((isShowPromptLog && !isResponding) || (!item.isOpeningStatement && isShowTextToSpeech)) && ( -
- {isShowPromptLog && !isResponding && ( - - )} - {!item.isOpeningStatement && isShowTextToSpeech && ( - <> -
- - - )} -
- )} - {(!item.isOpeningStatement && supportAnnotation) && ( - onAnnotationAdded?.(id, authorName, question, content, index)} - onEdit={() => setIsShowReplyModal(true)} - onRemoved={() => onAnnotationRemoved!(index)} - /> - )} - - setIsShowReplyModal(false)} - query={question} - answer={content} - onEdited={(editedQuery, editedAnswer) => onAnnotationEdited!(editedQuery, editedAnswer, index)} - onAdded={(annotationId, authorName, editedQuery, editedAnswer) => onAnnotationAdded!(annotationId, authorName, editedQuery, editedAnswer, index)} - appId={appId!} - messageId={id} - annotationId={annotation?.id || ''} - createdAt={annotation?.created_at} - onRemove={() => { }} - /> - - {!feedbackDisabled && !item.feedbackDisabled && renderItemOperation(displayScene !== 'console')} - {/* Admin feedback is displayed only in the background. */} - {!feedbackDisabled && renderFeedbackRating(localAdminFeedback?.rating, false, false)} - {/* User feedback must be displayed */} - {!feedbackDisabled && renderFeedbackRating(feedback?.rating, !isHideFeedbackEdit, displayScene !== 'console')} -
-
- {more && } -
-
-
-
- ) -} -export default React.memo(Answer) diff --git a/web/app/components/app/chat/icon-component/index.tsx b/web/app/components/app/chat/icon-component/index.tsx deleted file mode 100644 index c35fb77855..0000000000 --- a/web/app/components/app/chat/icon-component/index.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import type { FC, SVGProps } from 'react' -import { HandThumbDownIcon, HandThumbUpIcon } from '@heroicons/react/24/outline' - -export const stopIcon = ( - - - -) - -export const OpeningStatementIcon = ({ className }: SVGProps) => ( - - - -) - -export const RatingIcon: FC<{ isLike: boolean }> = ({ isLike }) => { - return isLike ? : -} - -export const EditIcon = ({ className }: SVGProps) => { - return - - -} - -export const EditIconSolid = ({ className }: SVGProps) => { - return - - - -} - -export const TryToAskIcon = ( - - - -) - -export const ReplayIcon = ({ className }: SVGProps) => ( - - - -) diff --git a/web/app/components/app/chat/icons/answer.svg b/web/app/components/app/chat/icons/answer.svg deleted file mode 100644 index e983039306..0000000000 --- a/web/app/components/app/chat/icons/answer.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/app/components/app/chat/icons/default-avatar.jpg b/web/app/components/app/chat/icons/default-avatar.jpg deleted file mode 100644 index 396d5dd291b44bc440da35e655774626ce1bae20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2183 zcmbW1dpy*67stQ9-^?(^ZColeZo6z$YLw_{G2>R`(&Q3P$P|@rz+)uxgs0ag5l@gWAD)E zztA`D(UG@k-xAs}i#AW9jT7jzDYRxB?V3j?-lLUc=<^x0WeRPXMk`;VBg<&>6xuO| zb}yh4D;AvqNG~|pTDf0@7JHs$CenyFYW-Zs4OXfDLKrKrNVU{m6_R}8|2gx#r8V7_ zu#RojVL#RQ^_7(FO6M(2WbLlCYc%WKR~`}8&U|cF?a^;Ns!%OLhU>L^?P$zv1;p%G z;61YPTTv*Zz;6*4y`u4?_~K zQqbJ?=)s-S8cffbilaX37m=ysrYVl*ZC+K$zFQO-IkG9;=&CG~qoL@L+ni()Yd%o% zvnHQe&R&+4=^Ilh6A!WwU<|+tO6W#N=$?G;$wJ^uVIyo%C#K$c!5XQw_I)S z1Z2~8Y6RVt5hU<2wE>~zogfg01G-cY>fi+gcsw`*rN^gX?!Y5suEKPND8Yp$Q>fw& zZ^vXJS~39wyEbSKKk}EC&>rej@0x8%1COglR2)Zc;cDc9H&0qTK1fq3RC0$6;234W zA3AQ}1}I1fHFlCOB)DUWV88AMpUh^grja4g4^=`9gp+E;vOUtZa^r^)W5kL|D3~zp z3DwZ+eWb`TWL&70N%neE z!NIUhD180*HV}?1+uX+0C{}h@}s%j=J}k-0&IZxj?WE2aP&fmv==Lr{$?$M*J9I~ zRzhKPj-q>6>B)1Er=vgRh+urbz81GJEA3QiH!HYcSJ>HX-@!er`-FuqrzdU=Pf}RC z9MMcyzrLjp8sX`BUD}rA&CPW@QAIV&{5>dMJfNE2TmS2GN6O3dB9D#Kr*S8_sg2z4 z7hklONheu~6BuS~N0PY!-e_8;!G6yFs0$hSU; z8rqcK6JtqA9%>znm`_iBXlR}h#Uh=HDSJiEuWpbZa86!TWnR!w815wWHMHCrjkFrv zY>cWZ_Gxx82I17PJ}-y!W7Ex-A|DxvozL5`Bb-{@f}YOp&pdRBskSz7Gmay#by}-# z;J#3xDh$&2G04ke2*dQGk(IAAKC>JD>9Z{S6Ke^1 zLrHXuvT#nLTs@F0Y9wB6^4-Exep0;FUg9!kclBL1nSgd9^OVY=o7)1rPfcVJYUM$LRTv;Exn$M!-o7v3J_wrUk8QOZ9G8#Y)zjTfhM&d$$ z1<^2t>M^pWv(fU%F)C&};H|Khe(wN|9==85XK`F>0hT6NqC&a0OE}~aOjYLsnv?;! z34I56P`X6Zf$}^Fn#EE2NamTmm|~5|Ih;QDgNq%n!j{)>VePUUR5D-FmjCi-i>y^h)bkP=}A~&jR21OCU8Ak1&9yfi68+$)PD$nKMjx- zF31^Roven4k~|0{0fj_)XcDON4d^o6>98DRuByrI zxQ86EdQH;7v_Uo;TDGM`_aI-NR`aA#h3h$an905aGB3}EDU-q_WAbB1?ADuZE5qFS s87)kBr-f92fg@+YmECigj^Xs982;qb2t(s+qc0?Iuye63wWhQG290UxH2?qr diff --git a/web/app/components/app/chat/icons/edit.svg b/web/app/components/app/chat/icons/edit.svg deleted file mode 100644 index a922970b6c..0000000000 --- a/web/app/components/app/chat/icons/edit.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/web/app/components/app/chat/icons/question.svg b/web/app/components/app/chat/icons/question.svg deleted file mode 100644 index 39904f52a5..0000000000 --- a/web/app/components/app/chat/icons/question.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/app/components/app/chat/icons/robot.svg b/web/app/components/app/chat/icons/robot.svg deleted file mode 100644 index a50c8886d1..0000000000 --- a/web/app/components/app/chat/icons/robot.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/web/app/components/app/chat/icons/send-active.svg b/web/app/components/app/chat/icons/send-active.svg deleted file mode 100644 index 03d4734bc6..0000000000 --- a/web/app/components/app/chat/icons/send-active.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/app/components/app/chat/icons/send.svg b/web/app/components/app/chat/icons/send.svg deleted file mode 100644 index e977ef95bb..0000000000 --- a/web/app/components/app/chat/icons/send.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/app/components/app/chat/icons/typing.svg b/web/app/components/app/chat/icons/typing.svg deleted file mode 100644 index 7b28f0ef78..0000000000 --- a/web/app/components/app/chat/icons/typing.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/web/app/components/app/chat/icons/user.svg b/web/app/components/app/chat/icons/user.svg deleted file mode 100644 index 556aaf7bfb..0000000000 --- a/web/app/components/app/chat/icons/user.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/web/app/components/app/chat/index.tsx b/web/app/components/app/chat/index.tsx deleted file mode 100644 index d861ddb2de..0000000000 --- a/web/app/components/app/chat/index.tsx +++ /dev/null @@ -1,455 +0,0 @@ -'use client' -import type { FC, ReactNode } from 'react' -import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react' -import Textarea from 'rc-textarea' -import { useContext } from 'use-context-selector' -import cn from 'classnames' -import Recorder from 'js-audio-recorder' -import { useTranslation } from 'react-i18next' -import s from './style.module.css' -import type { DisplayScene, FeedbackFunc, IChatItem } from './type' -import { TryToAskIcon, stopIcon } from './icon-component' -import Answer from './answer' -import Question from './question' -import TooltipPlus from '@/app/components/base/tooltip-plus' -import { ToastContext } from '@/app/components/base/toast' -import Button from '@/app/components/base/button' -import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' -import VoiceInput from '@/app/components/base/voice-input' -import { Microphone01 } from '@/app/components/base/icons/src/vender/line/mediaAndDevices' -import { Microphone01 as Microphone01Solid } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices' -import { XCircle } from '@/app/components/base/icons/src/vender/solid/general' -import type { DataSet } from '@/models/datasets' -import ChatImageUploader from '@/app/components/base/image-uploader/chat-image-uploader' -import ImageList from '@/app/components/base/image-uploader/image-list' -import { TransferMethod, type VisionFile, type VisionSettings } from '@/types/app' -import { useClipboardUploader, useDraggableUploader, useImageFiles } from '@/app/components/base/image-uploader/hooks' -import type { Annotation } from '@/models/log' -import type { Emoji } from '@/app/components/tools/types' - -export type IChatProps = { - appId?: string - configElem?: React.ReactNode - chatList: IChatItem[] - onChatListChange?: (chatList: IChatItem[]) => void - controlChatUpdateAllConversation?: number - /** - * Whether to display the editing area and rating status - */ - feedbackDisabled?: boolean - /** - * Whether to display the input area - */ - isHideFeedbackEdit?: boolean - isHideSendInput?: boolean - onFeedback?: FeedbackFunc - checkCanSend?: () => boolean - query?: string - onQueryChange?: (query: string) => void - onSend?: (message: string, files: VisionFile[]) => void - displayScene?: DisplayScene - useCurrentUserAvatar?: boolean - isResponding?: boolean - canStopResponding?: boolean - abortResponding?: () => void - controlClearQuery?: number - controlFocus?: number - isShowSuggestion?: boolean - suggestionList?: string[] - isShowSpeechToText?: boolean - isShowTextToSpeech?: boolean - isShowCitation?: boolean - answerIcon?: ReactNode - isShowConfigElem?: boolean - dataSets?: DataSet[] - isShowCitationHitInfo?: boolean - isShowPromptLog?: boolean - visionConfig?: VisionSettings - supportAnnotation?: boolean - allToolIcons?: Record - customDisclaimer?: string -} - -const Chat: FC = ({ - configElem, - chatList, - query = '', - onQueryChange = () => { }, - feedbackDisabled = false, - isHideFeedbackEdit = false, - isHideSendInput = false, - onFeedback, - checkCanSend, - onSend = () => { }, - displayScene, - useCurrentUserAvatar, - isResponding, - canStopResponding, - abortResponding, - controlClearQuery, - controlFocus, - isShowSuggestion, - suggestionList, - isShowSpeechToText, - isShowTextToSpeech, - isShowCitation, - answerIcon, - isShowConfigElem, - dataSets, - isShowCitationHitInfo, - isShowPromptLog, - visionConfig, - appId, - supportAnnotation, - onChatListChange, - allToolIcons, - customDisclaimer, -}) => { - const { t } = useTranslation() - const { notify } = useContext(ToastContext) - const { - files, - onUpload, - onRemove, - onReUpload, - onImageLinkLoadError, - onImageLinkLoadSuccess, - onClear, - } = useImageFiles() - const { onPaste } = useClipboardUploader({ onUpload, visionConfig, files }) - const { onDragEnter, onDragLeave, onDragOver, onDrop, isDragActive } = useDraggableUploader({ onUpload, files, visionConfig }) - const isUseInputMethod = useRef(false) - - const handleContentChange = (e: React.ChangeEvent) => { - const value = e.target.value - onQueryChange(value) - } - - const logError = (message: string) => { - notify({ type: 'error', message, duration: 3000 }) - } - - const valid = (q?: string) => { - const sendQuery = q || query - if (!sendQuery || sendQuery.trim() === '') { - logError('Message cannot be empty') - return false - } - return true - } - - useEffect(() => { - if (controlClearQuery) - onQueryChange('') - }, [controlClearQuery]) - - const handleSend = (q?: string) => { - if (!valid(q) || (checkCanSend && !checkCanSend())) - return - onSend(q || query, files.filter(file => file.progress !== -1).map(fileItem => ({ - type: 'image', - transfer_method: fileItem.type, - url: fileItem.url, - upload_file_id: fileItem.fileId, - }))) - if (!files.find(item => item.type === TransferMethod.local_file && !item.fileId)) { - if (files.length) - onClear() - if (!isResponding) - onQueryChange('') - } - } - - const handleKeyUp = (e: React.KeyboardEvent) => { - if (e.code === 'Enter') { - e.preventDefault() - // prevent send message when using input method enter - if (!e.shiftKey && !isUseInputMethod.current) - handleSend() - } - } - - const handleKeyDown = (e: React.KeyboardEvent) => { - isUseInputMethod.current = e.nativeEvent.isComposing - if (e.code === 'Enter' && !e.shiftKey) { - onQueryChange(query.replace(/\n$/, '')) - e.preventDefault() - } - } - - const media = useBreakpoints() - const isMobile = media === MediaType.mobile - const sendBtn =
handleSend()}>
- - const suggestionListRef = useRef(null) - const [hasScrollbar, setHasScrollbar] = useState(false) - useLayoutEffect(() => { - if (suggestionListRef.current) { - const listDom = suggestionListRef.current - const hasScrollbar = listDom.scrollWidth > listDom.clientWidth - setHasScrollbar(hasScrollbar) - } - }, [suggestionList]) - - const [voiceInputShow, setVoiceInputShow] = useState(false) - const handleVoiceInputShow = () => { - (Recorder as any).getPermission().then(() => { - setVoiceInputShow(true) - }, () => { - logError(t('common.voiceInput.notAllow')) - }) - } - const handleQueryChangeFromAnswer = useCallback((val: string) => { - onQueryChange(val) - handleSend(val) - }, []) - const handleAnnotationEdited = useCallback((query: string, answer: string, index: number) => { - onChatListChange?.(chatList.map((item, i) => { - if (i === index - 1) { - return { - ...item, - content: query, - } - } - if (i === index) { - return { - ...item, - annotation: { - ...item.annotation, - logAnnotation: { - ...item.annotation?.logAnnotation, - content: answer, - }, - } as any, - } - } - return item - })) - }, [chatList]) - const handleAnnotationAdded = useCallback((annotationId: string, authorName: string, query: string, answer: string, index: number) => { - onChatListChange?.(chatList.map((item, i) => { - if (i === index - 1) { - return { - ...item, - content: query, - } - } - if (i === index) { - const answerItem = { - ...item, - content: item.content, - annotation: { - id: annotationId, - authorName, - logAnnotation: { - content: answer, - account: { - id: '', - name: authorName, - email: '', - }, - }, - } as Annotation, - } - return answerItem - } - return item - })) - }, [chatList]) - const handleAnnotationRemoved = useCallback((index: number) => { - onChatListChange?.(chatList.map((item, i) => { - if (i === index) { - return { - ...item, - content: item.content, - annotation: undefined, - } - } - return item - })) - }, [chatList]) - - return ( -
- {isShowConfigElem && (configElem || null)} - {/* Chat List */} -
- {chatList.map((item, index) => { - if (item.isAnswer) { - const isLast = item.id === chatList[chatList.length - 1].id - const citation = item.citation - return - } - return ( - - ) - })} -
- {!isHideSendInput && ( -
- {/* Thinking is sync and can not be stopped */} - {(isResponding && canStopResponding && ((!!chatList[chatList.length - 1]?.content) || (chatList[chatList.length - 1]?.agent_thoughts && chatList[chatList.length - 1].agent_thoughts!.length > 0))) && ( -
- -
- )} - {isShowSuggestion && ( -
-
-
-
- {TryToAskIcon} - {t('appDebug.feature.suggestedQuestionsAfterAnswer.tryToAsk')} -
-
-
- {/* has scrollbar would hide part of first item */} -
- {suggestionList?.map((item, index) => ( -
- -
- ))} -
-
- )} -
-
- {visionConfig?.enabled && ( - <> -
- = visionConfig.number_limits} - /> -
-
-
- -
- - )} -