From 48fb28d5aec7a037d184af9e7b41e230a4e3d31c Mon Sep 17 00:00:00 2001 From: Yongbozzz Date: Mon, 21 Apr 2025 13:40:17 +0800 Subject: [PATCH 1/3] chat history feature enable for v1.5 release Signed-off-by: Yongbozzz --- EdgeCraftRAG/Dockerfile.server | 1 - EdgeCraftRAG/chatqna.py | 0 .../intel/gpu/arc/compose_vllm_multi-arc.yaml | 2 +- EdgeCraftRAG/docker_image_build/build.yaml | 8 +- EdgeCraftRAG/edgecraftrag/VERSION | 1 + EdgeCraftRAG/edgecraftrag/api/v1/chatqna.py | 45 ++++- EdgeCraftRAG/edgecraftrag/api_schema.py | 4 +- EdgeCraftRAG/edgecraftrag/components/data.py | 2 +- .../edgecraftrag/components/pipeline.py | 10 +- EdgeCraftRAG/edgecraftrag/requirements.txt | 6 +- EdgeCraftRAG/edgecraftrag/utils.py | 14 ++ EdgeCraftRAG/ui/gradio/ecrag_client.py | 20 +-- EdgeCraftRAG/ui/vue/components.d.ts | 10 +- EdgeCraftRAG/ui/vue/package.json | 2 + .../ui/vue/src/assets/iconFont/iconfont.css | 44 ++++- .../ui/vue/src/assets/iconFont/iconfont.js | 69 +------ .../ui/vue/src/assets/iconFont/iconfont.json | 63 +++++++ .../ui/vue/src/assets/iconFont/iconfont.ttf | Bin 6480 -> 8328 bytes .../ui/vue/src/assets/iconFont/iconfont.woff | Bin 4332 -> 5548 bytes .../ui/vue/src/assets/iconFont/iconfont.woff2 | Bin 3596 -> 4636 bytes EdgeCraftRAG/ui/vue/src/auto-imports.d.ts | 168 ++++++++---------- EdgeCraftRAG/ui/vue/src/theme/markdown.less | 75 ++++++++ EdgeCraftRAG/ui/vue/src/theme/variables.less | 53 +++++- EdgeCraftRAG/ui/vue/src/utils/common.ts | 15 +- .../ui/vue/src/utils/customRenderer.ts | 131 ++++++++++++++ .../src/views/chatbot/components/Chatbot.vue | 17 +- .../views/chatbot/components/MessageItem.vue | 16 +- .../views/chatbot/components/UploadFile.vue | 6 +- EdgeCraftRAG/ui/vue/src/views/chatbot/type.ts | 2 +- 29 files changed, 555 insertions(+), 229 deletions(-) mode change 100644 => 100755 EdgeCraftRAG/Dockerfile.server mode change 100644 => 100755 EdgeCraftRAG/chatqna.py create mode 100644 EdgeCraftRAG/edgecraftrag/VERSION mode change 100644 => 100755 EdgeCraftRAG/edgecraftrag/api/v1/chatqna.py mode change 100644 => 100755 EdgeCraftRAG/edgecraftrag/components/data.py mode change 100644 => 100755 EdgeCraftRAG/edgecraftrag/requirements.txt create mode 100644 EdgeCraftRAG/ui/vue/src/utils/customRenderer.ts diff --git a/EdgeCraftRAG/Dockerfile.server b/EdgeCraftRAG/Dockerfile.server old mode 100644 new mode 100755 index 5d0aee5cd1..ea1f88786f --- a/EdgeCraftRAG/Dockerfile.server +++ b/EdgeCraftRAG/Dockerfile.server @@ -46,5 +46,4 @@ WORKDIR /home/user/ RUN git clone https://github.com/openvinotoolkit/openvino.genai.git genai ENV PYTHONPATH="$PYTHONPATH:/home/user/genai/tools/llm_bench" - ENTRYPOINT ["python", "-m", "edgecraftrag.server"] \ No newline at end of file diff --git a/EdgeCraftRAG/chatqna.py b/EdgeCraftRAG/chatqna.py old mode 100644 new mode 100755 diff --git a/EdgeCraftRAG/docker_compose/intel/gpu/arc/compose_vllm_multi-arc.yaml b/EdgeCraftRAG/docker_compose/intel/gpu/arc/compose_vllm_multi-arc.yaml index d82f9c9747..cd13d9b41c 100644 --- a/EdgeCraftRAG/docker_compose/intel/gpu/arc/compose_vllm_multi-arc.yaml +++ b/EdgeCraftRAG/docker_compose/intel/gpu/arc/compose_vllm_multi-arc.yaml @@ -90,4 +90,4 @@ services: bash start-vllm-service.sh" networks: default: - driver: bridge + driver: bridge \ No newline at end of file diff --git a/EdgeCraftRAG/docker_image_build/build.yaml b/EdgeCraftRAG/docker_image_build/build.yaml index 9c80955d9e..c4f2189deb 100644 --- a/EdgeCraftRAG/docker_image_build/build.yaml +++ b/EdgeCraftRAG/docker_image_build/build.yaml @@ -4,7 +4,7 @@ services: edgecraftrag-server: build: - context: ../ + context: .. args: http_proxy: ${http_proxy} https_proxy: ${https_proxy} @@ -12,7 +12,7 @@ services: image: ${REGISTRY:-opea}/edgecraftrag-server:${TAG:-latest} edgecraftrag-ui: build: - context: ../ + context: .. args: http_proxy: ${http_proxy} https_proxy: ${https_proxy} @@ -20,7 +20,7 @@ services: image: ${REGISTRY:-opea}/edgecraftrag-ui:${TAG:-latest} edgecraftrag-ui-gradio: build: - context: ../ + context: .. args: http_proxy: ${http_proxy} https_proxy: ${https_proxy} @@ -28,7 +28,7 @@ services: image: ${REGISTRY:-opea}/edgecraftrag-ui-gradio:${TAG:-latest} edgecraftrag: build: - context: ../ + context: .. args: http_proxy: ${http_proxy} https_proxy: ${https_proxy} diff --git a/EdgeCraftRAG/edgecraftrag/VERSION b/EdgeCraftRAG/edgecraftrag/VERSION new file mode 100644 index 0000000000..e0ecd51705 --- /dev/null +++ b/EdgeCraftRAG/edgecraftrag/VERSION @@ -0,0 +1 @@ +25.05-dev diff --git a/EdgeCraftRAG/edgecraftrag/api/v1/chatqna.py b/EdgeCraftRAG/edgecraftrag/api/v1/chatqna.py old mode 100644 new mode 100755 index d0236c82e8..c5bceee041 --- a/EdgeCraftRAG/edgecraftrag/api/v1/chatqna.py +++ b/EdgeCraftRAG/edgecraftrag/api/v1/chatqna.py @@ -5,6 +5,7 @@ from comps.cores.proto.api_protocol import ChatCompletionRequest from edgecraftrag.api_schema import RagOut from edgecraftrag.context import ctx +from edgecraftrag.utils import serialize_contexts from fastapi import FastAPI, File, HTTPException, UploadFile, status from fastapi.responses import StreamingResponse @@ -29,14 +30,15 @@ async def retrieval(request: ChatCompletionRequest): @chatqna_app.post(path="/v1/chatqna") async def chatqna(request: ChatCompletionRequest): try: + request.messages = convert_message(request.messages) generator = ctx.get_pipeline_mgr().get_active_pipeline().generator if generator: request.model = generator.model_id if request.stream: - ret, retri_res = ctx.get_pipeline_mgr().run_pipeline(chat_request=request) + ret, contexts = ctx.get_pipeline_mgr().run_pipeline(chat_request=request) return ret else: - ret, retri_res = ctx.get_pipeline_mgr().run_pipeline(chat_request=request) + ret, contexts = ctx.get_pipeline_mgr().run_pipeline(chat_request=request) return str(ret) except Exception as e: raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e)) @@ -46,7 +48,8 @@ async def chatqna(request: ChatCompletionRequest): @chatqna_app.post(path="/v1/ragqna") async def ragqna(request: ChatCompletionRequest): try: - res, retri_res = ctx.get_pipeline_mgr().run_pipeline(chat_request=request) + request.messages = convert_message(request.messages) + res, contexts = ctx.get_pipeline_mgr().run_pipeline(chat_request=request) if isinstance(res, GeneratedDoc): res = res.text elif isinstance(res, StreamingResponse): @@ -55,10 +58,9 @@ async def ragqna(request: ChatCompletionRequest): collected_data.append(chunk) res = "".join(collected_data) - ragout = RagOut(query=request.messages, contexts=[], response=str(res)) - for n in retri_res: - origin_text = n.node.get_text() - ragout.contexts.append(origin_text.strip()) + serialized_contexts = serialize_contexts(contexts) + + ragout = RagOut(query=request.messages, contexts=serialized_contexts, response=str(res)) return ragout except Exception as e: raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e)) @@ -88,3 +90,32 @@ async def reset_prompt(): return "Reset LLM Prompt Successfully" except Exception as e: raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e)) + +def convert_message(messages, history_prompt: str = None): + messages_list = [] + if isinstance(messages, str): + str_message = messages + else: + str_message = "" + user_indexs = [i for i, msg in enumerate(messages) if msg.get("role") == "user"] + last_user_index = user_indexs[-1] if user_indexs else -1 + + for idx, message in enumerate(messages): + msg_role = message["role"] + if msg_role in ["user", "assistant"]: + content = message["content"] + if idx == last_user_index and msg_role == "user": + messages_list.append(("system", f"{history_prompt}")) + if isinstance(content, str): + messages_list.append((msg_role, content)) + else: + raise ValueError(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Only text content is supported.") + else: + raise ValueError(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Unknown role: {msg_role}") + + for role, content in messages_list: + str_message += f"{role}: {content}\n" + if len(str_message) > 8192: + str_message = str_message[-8192:] + return str_message \ No newline at end of file diff --git a/EdgeCraftRAG/edgecraftrag/api_schema.py b/EdgeCraftRAG/edgecraftrag/api_schema.py index 7a8a493b1e..294dedb476 100644 --- a/EdgeCraftRAG/edgecraftrag/api_schema.py +++ b/EdgeCraftRAG/edgecraftrag/api_schema.py @@ -1,7 +1,7 @@ # Copyright (C) 2024 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -from typing import Optional +from typing import Optional, Any from pydantic import BaseModel @@ -65,5 +65,5 @@ class FilesIn(BaseModel): class RagOut(BaseModel): query: str - contexts: Optional[list[str]] = None + contexts: Optional[dict[str, Any]] = None response: str diff --git a/EdgeCraftRAG/edgecraftrag/components/data.py b/EdgeCraftRAG/edgecraftrag/components/data.py old mode 100644 new mode 100755 index e7fa19e7ad..cd51f7d6ee --- a/EdgeCraftRAG/edgecraftrag/components/data.py +++ b/EdgeCraftRAG/edgecraftrag/components/data.py @@ -54,7 +54,7 @@ def convert_text_to_documents(text) -> List[Document]: def convert_file_to_documents(file_path) -> List[Document]: from llama_index.core import SimpleDirectoryReader - supported_exts = [".pdf", ".txt", ".doc", ".docx", ".pptx", ".ppt", ".csv", ".md", ".html", ".rst"] + supported_exts = [".pdf", ".txt", ".doc", ".docx", ".pptx", ".ppt", ".csv", ".md", ".html", ".rst",".epub"] if file_path.is_dir(): docs = SimpleDirectoryReader(input_dir=file_path, recursive=True, required_exts=supported_exts).load_data() elif file_path.is_file(): diff --git a/EdgeCraftRAG/edgecraftrag/components/pipeline.py b/EdgeCraftRAG/edgecraftrag/components/pipeline.py index e0a01eba96..a7dd8c4cce 100644 --- a/EdgeCraftRAG/edgecraftrag/components/pipeline.py +++ b/EdgeCraftRAG/edgecraftrag/components/pipeline.py @@ -221,11 +221,13 @@ async def timing_wrapper(): def run_test_generator_ben(pl: Pipeline, chat_request: ChatCompletionRequest) -> Any: benchmark_index, benchmark_data = pl.benchmark.init_benchmark_data() + contexts = {} start = time.perf_counter() query = chat_request.messages retri_res = pl.retriever.run(query=query) query_bundle = QueryBundle(query) benchmark_data[CompType.RETRIEVER] = time.perf_counter() - start + contexts[CompType.RETRIEVER] = retri_res start = time.perf_counter() if pl.postprocessor: @@ -236,6 +238,7 @@ def run_test_generator_ben(pl: Pipeline, chat_request: ChatCompletionRequest) -> ): processor.top_n = chat_request.top_n retri_res = processor.run(retri_res=retri_res, query_bundle=query_bundle) + contexts[CompType.POSTPROCESSOR] = retri_res benchmark_data[CompType.POSTPROCESSOR] = time.perf_counter() - start if pl.generator is None: @@ -260,12 +263,14 @@ def run_test_generator_ben(pl: Pipeline, chat_request: ChatCompletionRequest) -> benchmark_data[CompType.GENERATOR] = end - start pl.benchmark.insert_llm_data(benchmark_index, input_token_size) pl.benchmark.insert_benchmark_data(benchmark_data) - return ret, retri_res + return ret, contexts def run_test_generator(pl: Pipeline, chat_request: ChatCompletionRequest) -> Any: query = chat_request.messages + contexts = {} retri_res = pl.retriever.run(query=query) + contexts[CompType.RETRIEVER] = retri_res query_bundle = QueryBundle(query) if pl.postprocessor: @@ -276,6 +281,7 @@ def run_test_generator(pl: Pipeline, chat_request: ChatCompletionRequest) -> Any ): processor.top_n = chat_request.top_n retri_res = processor.run(retri_res=retri_res, query_bundle=query_bundle) + contexts[CompType.POSTPROCESSOR] = retri_res if pl.generator is None: raise ValueError("No Generator Specified") @@ -286,4 +292,4 @@ def run_test_generator(pl: Pipeline, chat_request: ChatCompletionRequest) -> Any ret = pl.generator.run_vllm(chat_request, retri_res, np_type) else: raise ValueError("LLM inference_type not supported") - return ret, retri_res + return ret, contexts diff --git a/EdgeCraftRAG/edgecraftrag/requirements.txt b/EdgeCraftRAG/edgecraftrag/requirements.txt old mode 100644 new mode 100755 index b1026a1d24..de3af739de --- a/EdgeCraftRAG/edgecraftrag/requirements.txt +++ b/EdgeCraftRAG/edgecraftrag/requirements.txt @@ -1,7 +1,5 @@ docx2txt -EbookLib>=0.18 faiss-cpu>=1.8.0.post1 -html2text>=2025.4.15 langchain-core>=0.2.29 llama-index>=0.11.0 llama-index-embeddings-openvino>=0.4.0 @@ -13,7 +11,9 @@ llama-index-retrievers-bm25>=0.3.0 llama-index-vector-stores-faiss>=0.2.1 opea-comps>=1.2 pillow>=10.4.0 -py-cpuinfo>=9.0.0 python-docx==1.1.2 unstructured==0.16.11 unstructured[pdf] +EbookLib>=0.18 +html2text>=2025.4.15 +py-cpuinfo>=9.0.0 \ No newline at end of file diff --git a/EdgeCraftRAG/edgecraftrag/utils.py b/EdgeCraftRAG/edgecraftrag/utils.py index be83f47135..af68c89618 100644 --- a/EdgeCraftRAG/edgecraftrag/utils.py +++ b/EdgeCraftRAG/edgecraftrag/utils.py @@ -29,3 +29,17 @@ def iter_elements(cls, paragraph: Paragraph, opts: DocxPartitionerOptions) -> It image.save(image_path) element_metadata = ElementMetadata(image_path=image_path) yield Image(text="IMAGE", metadata=element_metadata) + + +def serialize_node_with_score(node_with_score): + return { + "node": node_with_score.node.__dict__, + "score": node_with_score.score.item() if hasattr(node_with_score.score, "item") else node_with_score.score, + } + + +def serialize_contexts(contexts): + return { + key: [serialize_node_with_score(node) for node in nodes] + for key, nodes in contexts.items() + } diff --git a/EdgeCraftRAG/ui/gradio/ecrag_client.py b/EdgeCraftRAG/ui/gradio/ecrag_client.py index a2d9eb85bd..eeb0a529f7 100644 --- a/EdgeCraftRAG/ui/gradio/ecrag_client.py +++ b/EdgeCraftRAG/ui/gradio/ecrag_client.py @@ -156,16 +156,16 @@ def get_benchmark(name): if data.get("Benchmark enabled", False): benchmark_data = data.get("last_benchmark_data", {}) - if benchmark_data and "generator" in benchmark_data: - if benchmark_data.get("generator", "N/A"): - benchmark = ( - f"Retrieval: {benchmark_data.get('retriever', 0.0):.4f}s " - f"Post-process: {benchmark_data.get('postprocessor', 0.0):.4f}s " - f"Generation: {benchmark_data.get('generator', 0.0):.4f}s" - ).rstrip() - return benchmark - else: - return None + if benchmark_data and 'generator' in benchmark_data: + if benchmark_data.get("generator", "N/A"): + benchmark = ( + f"Retrieval: {benchmark_data.get('retriever', 0.0):.4f}s " + f"Post-process: {benchmark_data.get('postprocessor', 0.0):.4f}s " + f"Generation: {benchmark_data.get('generator', 0.0):.4f}s" + ).rstrip() + return benchmark + else: + return None else: return None else: diff --git a/EdgeCraftRAG/ui/vue/components.d.ts b/EdgeCraftRAG/ui/vue/components.d.ts index 64ca06335b..1f2f9ed52a 100644 --- a/EdgeCraftRAG/ui/vue/components.d.ts +++ b/EdgeCraftRAG/ui/vue/components.d.ts @@ -1,11 +1,8 @@ -// Copyright (C) 2025 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - /* eslint-disable */ // @ts-nocheck // Generated by unplugin-vue-components // Read more: https://github.com/vuejs/core/pull/3399 -export {}; +export {} /* prettier-ignore */ declare module 'vue' { @@ -32,17 +29,22 @@ declare module 'vue' { AModal: typeof import('ant-design-vue/es')['Modal'] APagination: typeof import('ant-design-vue/es')['Pagination'] APopover: typeof import('ant-design-vue/es')['Popover'] + AProgress: typeof import('ant-design-vue/es')['Progress'] ARadio: typeof import('ant-design-vue/es')['Radio'] ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup'] + ARate: typeof import('ant-design-vue/es')['Rate'] ARow: typeof import('ant-design-vue/es')['Row'] ASelect: typeof import('ant-design-vue/es')['Select'] ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] ASlider: typeof import('ant-design-vue/es')['Slider'] ASpace: typeof import('ant-design-vue/es')['Space'] ASteps: typeof import('ant-design-vue/es')['Steps'] + ASwitch: typeof import('ant-design-vue/es')['Switch'] ATable: typeof import('ant-design-vue/es')['Table'] ATag: typeof import('ant-design-vue/es')['Tag'] + ATextarea: typeof import('ant-design-vue/es')['Textarea'] ATooltip: typeof import('ant-design-vue/es')['Tooltip'] + AUpload: typeof import('ant-design-vue/es')['Upload'] AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger'] FormTooltip: typeof import('./src/components/FormTooltip.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] diff --git a/EdgeCraftRAG/ui/vue/package.json b/EdgeCraftRAG/ui/vue/package.json index 0c3e32bc11..29539d7c55 100644 --- a/EdgeCraftRAG/ui/vue/package.json +++ b/EdgeCraftRAG/ui/vue/package.json @@ -12,8 +12,10 @@ "@vueuse/i18n": "^4.0.0-beta.12", "ant-design-vue": "^4.0.0-rc.6", "axios": "^1.7.9", + "clipboard": "^2.0.11", "echarts": "^5.5.1", "event-source-polyfill": "^1.0.31", + "highlight.js": "^11.11.1", "http": "^0.0.1-security", "js-cookie": "^3.0.5", "lodash": "^4.17.21", diff --git a/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.css b/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.css index 0fd282ff5e..831b524b2b 100644 --- a/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.css +++ b/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.css @@ -1,9 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 4784207 */ - src: - url("iconfont.woff2?t=1739238081968") format("woff2"), - url("iconfont.woff?t=1739238081968") format("woff"), - url("iconfont.ttf?t=1739238081968") format("truetype"); + src: url('iconfont.woff2?t=1744699312006') format('woff2'), + url('iconfont.woff?t=1744699312006') format('woff'), + url('iconfont.ttf?t=1744699312006') format('truetype'); } .iconfont { @@ -14,6 +13,42 @@ -moz-osx-font-smoothing: grayscale; } +.icon-export:before { + content: "\e619"; +} + +.icon-rename:before { + content: "\e618"; +} + +.icon-delete:before { + content: "\e664"; +} + +.icon-setting1:before { + content: "\e61b"; +} + +.icon-upload:before { + content: "\e617"; +} + +.icon-clear:before { + content: "\e765"; +} + +.icon-copy-success:before { + content: "\e666"; +} + +.icon-copy:before { + content: "\e660"; +} + +.icon-subway:before { + content: "\e6ed"; +} + .icon-stop:before { content: "\e904"; } @@ -97,3 +132,4 @@ .icon-active:before { content: "\e795"; } + diff --git a/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.js b/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.js index 5c567a1196..f148b6b81b 100644 --- a/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.js +++ b/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.js @@ -1,68 +1 @@ -// Copyright (C) 2025 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -(window._iconfont_svg_string_4784207 = - ''), - ((l) => { - var a = (t = (t = document.getElementsByTagName("script"))[t.length - 1]).getAttribute("data-injectcss"), - t = t.getAttribute("data-disable-injectsvg"); - if (!t) { - var h, - i, - o, - e, - c, - v = function (a, t) { - t.parentNode.insertBefore(a, t); - }; - if (a && !l.__iconfont__svg__cssinject__) { - l.__iconfont__svg__cssinject__ = !0; - try { - document.write( - "", - ); - } catch (a) { - console && console.log(a); - } - } - (h = function () { - var a, - t = document.createElement("div"); - (t.innerHTML = l._iconfont_svg_string_4784207), - (t = t.getElementsByTagName("svg")[0]) && - (t.setAttribute("aria-hidden", "true"), - (t.style.position = "absolute"), - (t.style.width = 0), - (t.style.height = 0), - (t.style.overflow = "hidden"), - (t = t), - (a = document.body).firstChild ? v(t, a.firstChild) : a.appendChild(t)); - }), - document.addEventListener - ? ~["complete", "loaded", "interactive"].indexOf(document.readyState) - ? setTimeout(h, 0) - : ((i = function () { - document.removeEventListener("DOMContentLoaded", i, !1), h(); - }), - document.addEventListener("DOMContentLoaded", i, !1)) - : document.attachEvent && - ((o = h), - (e = l.document), - (c = !1), - d(), - (e.onreadystatechange = function () { - "complete" == e.readyState && ((e.onreadystatechange = null), n()); - })); - } - function n() { - c || ((c = !0), o()); - } - function d() { - try { - e.documentElement.doScroll("left"); - } catch (a) { - return void setTimeout(d, 50); - } - n(); - } - })(window); +window._iconfont_svg_string_4784207='',(h=>{var l=(a=(a=document.getElementsByTagName("script"))[a.length-1]).getAttribute("data-injectcss"),a=a.getAttribute("data-disable-injectsvg");if(!a){var t,c,i,o,e,v=function(l,a){a.parentNode.insertBefore(l,a)};if(l&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}t=function(){var l,a=document.createElement("div");a.innerHTML=h._iconfont_svg_string_4784207,(a=a.getElementsByTagName("svg")[0])&&(a.setAttribute("aria-hidden","true"),a.style.position="absolute",a.style.width=0,a.style.height=0,a.style.overflow="hidden",a=a,(l=document.body).firstChild?v(a,l.firstChild):l.appendChild(a))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(c=function(){document.removeEventListener("DOMContentLoaded",c,!1),t()},document.addEventListener("DOMContentLoaded",c,!1)):document.attachEvent&&(i=t,o=h.document,e=!1,d(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,s())})}function s(){e||(e=!0,i())}function d(){try{o.documentElement.doScroll("left")}catch(l){return void setTimeout(d,50)}s()}})(window); \ No newline at end of file diff --git a/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.json b/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.json index f00702b38d..9caf20d219 100644 --- a/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.json +++ b/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.json @@ -5,6 +5,69 @@ "css_prefix_text": "icon-", "description": "", "glyphs": [ + { + "icon_id": "43924556", + "name": "export", + "font_class": "export", + "unicode": "e619", + "unicode_decimal": 58905 + }, + { + "icon_id": "43924554", + "name": "rename", + "font_class": "rename", + "unicode": "e618", + "unicode_decimal": 58904 + }, + { + "icon_id": "2570142", + "name": "delete", + "font_class": "delete", + "unicode": "e664", + "unicode_decimal": 58980 + }, + { + "icon_id": "13253937", + "name": "setting", + "font_class": "setting1", + "unicode": "e61b", + "unicode_decimal": 58907 + }, + { + "icon_id": "43796752", + "name": "upload", + "font_class": "upload", + "unicode": "e617", + "unicode_decimal": 58903 + }, + { + "icon_id": "42194548", + "name": "clear", + "font_class": "clear", + "unicode": "e765", + "unicode_decimal": 59237 + }, + { + "icon_id": "1198529", + "name": "copy-success", + "font_class": "copy-success", + "unicode": "e666", + "unicode_decimal": 58982 + }, + { + "icon_id": "9080698", + "name": "copy", + "font_class": "copy", + "unicode": "e660", + "unicode_decimal": 58976 + }, + { + "icon_id": "796912", + "name": "地铁", + "font_class": "subway", + "unicode": "e6ed", + "unicode_decimal": 59117 + }, { "icon_id": "42853460", "name": "stop", diff --git a/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.ttf b/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.ttf index 38480000d31e32f85f015b1177cce49b56053dfe..95023b5beb2ca60599920cbd57a41186d88531aa 100644 GIT binary patch delta 2588 zcma)8Yit}>6+UO~?#%4$dS2d{+1~y^hm5 zv1>cUfs##8T7gnW0XM1|z?4v-s1a2q`lnKW3Zf`T1wo_cM~lj%Xf}3Q@erUOv9p}J zqY8e2)Yo9 zOLMpbzD)gGPaPXSTGhWd@Cv}jOEl-^kFBI|eWgdRSGEi4N~aJd^w)%P zs~d1Tu$Huyo(cs~h5&N^J&=L`sBYZd;O=t|xQE;^cha45kGPBON%vXzHTQ#htiHWo zt)H)7tiQ7sSbwTXal7V6dVl3dLf6VDi_9WTH1LsrgD^;8#UTdm5P>iRDNm#jE!YSf zC~F21*boIB5}-i{I=}!CIza^oOiHbd2oYCC*d3ZTT#Jw|BAB;yb@IS{&5aX~$nR4)Dwf>Y3UIl*DAP;BZ zuXqu!xDBDWfC>l{Qo6h9>jAE`B!lF^UDlCo0^hUoP8^tr%yxZRGYpeUPHhPJ3@)35i>Zu=y_gHcL{zDcAoy+B9mal~swdgQm z+P3YSd86W_9!w1-yZ4r$`BKv>x*bic==eC)zN{S*0uT$HYPdNB~EY-M--w)}E zqKB3hO`&_4L^24MN3?ic8}YTqoE=YC!UHeXWJQs^tGva5|1DD{ew~-8&J!?4IrQ2| z>_n$hZap=UxvpW97fKQ($0k9=ZB#fx#jGUesXT>zp(XU-5LdP#7ixpllq=;*Ax|Y8 zBtP6Rh{g7diqTH&9mG-(3f;2CHfoMJBDafoi;N{@McOTgFsR7)GA4={#-w4%knhp; zjs#QXy&;WtYI-EHSJuUT8juo$QgC-Di~`Ei1HphOrDG$Tu!BGyyc6%WRkq_6|CAdiiH0SZkdXrSdN9qde38%I`)iD(2Egx?;5~MFWd`lXN5P7~A3d z#@>b8BD~eOY{ui}skkZZ_l3q)0X%pKPnq%kjhm;8c-$Z{UVn>s^JbXdB{MggjhZj* z7rHMWh#MX~y_e#f;&ktiXXA7eopio8PqV+UIr_vz=~I-3o$xsrBU=6|D#nB2Au(b* zSjzh<%Sb9pV$`ACV)s@C>EJ3Ada#ghFQlbxr3Y(N-$8*^yin}z6#2H7oSc*{;L8_i z(S$E3nzpD}R)=kO;dQScZ&;lc-G7=obnr~RP{^M-c<2}Z5g)OT z|619xP&U9Dlb$Q7mpk}yhA)bH#0jv8Jw7@j?YIXX6H`a bwQzi5qPnmU;EK3#{PSNJKe6(q*o}V!rp6#L delta 765 zcmZ{i!D|yi6vn^V-E68&ZB3gH@X#1Nls4ATLr+BrhzRCjFSRJ825p-{(-xXTdP(q5 z@ThLPgLtYUqFujn@Yq>?JNstd%zWRQy_w%0xs|I| zA5V`1&RM|4+`{VY%irhgK%@fnTrABLuMfWZ#TXySXo&;S5AI!lH_6FTxl)}};Xa_g zGM-#mx>h{BIaK9(?uX%WvAV1Vu*&%q?x3V%QNSemsYwePfq=YK& z-oGK>8@-vyEc?UE+k=NUj5A2{%aNoMWJ0E7UMfozok-p?7w@_F5PM5==3xM;AH~#Zma^qnQLEID$jeOV`Q|9=iL%YZVC| zcz!*`)uttk9t(Ga^jf$tq|ah}ipe893zD>$VoAZm^C1%!DuGN{s0lJ}p*jeE21A`f zAvFsnL)I-6581NN1~hNmKts?u3#~zKSd0PPu+T1a%R=MOI~JAzyDWjhTwZ$(qvi!u z7q&CFkDqE*y?3rUpWL{6&VBA>y=LTc5@A*HXwdiKF-7$b?mtw8BN(LkSS%u(5 I|2vl8FVN<_2LJ#7 diff --git a/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.woff b/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.woff index c16ad1f1714c7581f51277a853687ab173affdf3..1746c97f969c3da22aa9e7f8486ba7a37c60d204 100644 GIT binary patch delta 5077 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 delta 3844 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 GPPqUKC_@DR diff --git a/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.woff2 b/EdgeCraftRAG/ui/vue/src/assets/iconFont/iconfont.woff2 index 45249bf369a73bad8d42522727051e12c3c9c5cd..d871db62f24fb57b894647f8a1881b9df4bc59f1 100644 GIT binary patch literal 4636 zcmV+%665W6Pew8T0RR9101_Mk3jhEB03e6}01?dq0RR9100000000000000000000 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 S3X9t2J8=4iPqMWkEBKs?B%5X2*u5{4a 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 :last-child { + margin-bottom: 0; + } + + table tr { + font-size: 14px; + border-top: 1px solid var(--border-main-color); + } + + blockquote { + color: var(--blockquote-color); + border-left: 3px solid var(--bg-scrollbar); + margin: 8px 0px; + padding: 0px 10px; + } + .intel-highlighter { + width: 100%; + border-radius: 4px; + overflow: hidden; + margin-top: 16px; + margin-bottom: 12px; + .header-wrap { + align-items: center; + background-color: var(--code-header-bg); + color: var(--code-header-font); + display: flex; + align-items: center; + justify-content: space-between; + font-size: 14px; + height: 32px; + padding: 0 14px; + .copy-icon { + display: block; + color: var(--font-main-color); + cursor: pointer; + } + .success-icon { + display: none; + color: var(--color-success); + } + } + .content-wrap { + overflow-x: auto; + background: var(--code-content-bg); + padding: 16px; + font-size: 13px; + margin-top: 0; + color: var(--font-main-color); + } + } } diff --git a/EdgeCraftRAG/ui/vue/src/theme/variables.less b/EdgeCraftRAG/ui/vue/src/theme/variables.less index e8914623af..fd3c73958c 100644 --- a/EdgeCraftRAG/ui/vue/src/theme/variables.less +++ b/EdgeCraftRAG/ui/vue/src/theme/variables.less @@ -6,18 +6,23 @@ --color-primary: #00377c; --color-primary-hover: #0054ae; --color-primaryBg: #e0eaff; + --color-second-primaryBg: #d4e1fd; --color-error: #ce0000; --color-error-hover: #ff5d52; + --color-errorBg: #ffa3a3; --color-info: #aaaaaa; + --color-infoBg: #ffffff; --color-success: #179958; - --color-warning: #faad14; - --color-big-icon: #111111; --color-successBg: #d6ffe8; + --color-second-successBg: #f0fdf4; + --color-warning: #faad14; + --color-second-warning: #854d0e; --color-warningBg: #feefd0; - --color-errorBg: #ffa3a3; - --color-infoBg: #ffffff; + --color-second-warningBg: #fefce8; + --color-big-icon: #111111; --bg-main-color: #f5f5f5; --bg-card-color: #f9f9f9; + --bg-second-card-bg: var(--color-white); --bg-loading-color: rgba(0, 0, 0, 0.45); --bg-content-color: var(--color-white); --font-main-color: #333333; @@ -31,15 +36,30 @@ 0px 10px 15px -3px rgba(0, 0, 0, 0.1); --menu-bg: var(--bg-main-color); --color-switch-theme: #e5e7eb; - + --think-done-icon: #356bfd; + --think-done-bg: linear-gradient(180deg, #f3f5fc 30%, #ffffff 100%); + --font-think-color: #5e5e5e; + --face-icon-bg: #a6a6a6; + --bg-switch: var(--color-primaryBg); //边框 --border-main-color: #e5e7eb; + --border-warning: var(--color-warningBg); + --border-success: var(--color-successBg); + --border-primary: var(--color-second-primaryBg); //黑色按钮 --bg-black-color: #434343; --bg-black-hover-color: #595959; --bg-black-active-color: #262626; --border-black-color: #434343; + + //md显示 + --code-header-bg: #dddddd; + --code-header-font: #2c2c36; + --code-content-bg: #f0f0f0; + --table-th-bg: #dddddd; + --table-td-bg: #f0f0f0; + --blockquote-color: var(--font-info-color); } [data-theme="dark"] { @@ -51,26 +71,41 @@ --font-text-color: #e9e9e9; --font-info-color: #aeaeae; --font-tip-color: #aeaeae; - --bg-scrollbar: #dddddd; - --bg-scrollbar-hover: #bbbbbb; + --bg-scrollbar: #595959; + --bg-scrollbar-hover: #666666; --color-primary: #0054ae; --color-primary-hover: #1668dc; --color-primaryBg: #95b5fa; + --color-second-primaryBg: #d4e1fd; --bg-box-shadow: rgba(109, 153, 233, 0.05); --bg-gradient-shadow: 0px 4px 6px -4px rgba(255, 255, 255, 0.1), 0px 5px 8px 1px rgba(255, 255, 255, 0.1); --menu-bg: #3e3e3e; --color-big-icon: #ffffff; + --bg-second-card-bg: #111111; --color-switch-theme: var(--color-primary-hover); - + --think-done-bg: linear-gradient(180deg, #32313a 30%, #2d2d2d 100%); + --font-think-color: #e0ecffcc; + --bg-switch: var(--bg-card-color); //边框 - --border-main-color: #2b2b2b; + --border-main-color: #3b3b3b; + --border-warning: #f8e9ca; + --border-success: #d7f8e8; + --border-primary: #d5daf8; //黑色按钮 --bg-black-color: #434343; --bg-black-hover-color: #595959; --bg-black-active-color: #262626; --border-black-color: #434343; + + //md显示 + --code-header-bg: #585a73; + --code-header-font: #fafafc; + --code-content-bg: #2c2c36; + --table-th-bg: #585a73; + --table-td-bg: #2c2c36; + --blockquote-color: var(--bg-scrollbar-hover); } @use "ant-design-vue/es/style/themes/default.less"; diff --git a/EdgeCraftRAG/ui/vue/src/utils/common.ts b/EdgeCraftRAG/ui/vue/src/utils/common.ts index efdf142be9..fbcf97d9ee 100644 --- a/EdgeCraftRAG/ui/vue/src/utils/common.ts +++ b/EdgeCraftRAG/ui/vue/src/utils/common.ts @@ -5,7 +5,8 @@ import { inject } from "vue"; import { customNotification } from "./notification"; export const useNotification = () => { - const customNotificationInjected = inject("customNotification"); + const customNotificationInjected = + inject("customNotification"); if (!customNotificationInjected) { throw new Error("Notification service not provided"); @@ -19,3 +20,15 @@ export const formatDecimals = (num: number, decimalPlaces: number = 2) => { const factor = Math.pow(10, decimalPlaces); return Math.round(num * factor) / factor; }; + +export const formatCapitalize = ( + string: string, + start: number = 0, + length: number = 1 +) => { + const end = start + length; + const part1 = string.slice(0, start); + const part2 = string.slice(start, end).toUpperCase(); + const part3 = string.slice(end); + return part1 + part2 + part3; +}; diff --git a/EdgeCraftRAG/ui/vue/src/utils/customRenderer.ts b/EdgeCraftRAG/ui/vue/src/utils/customRenderer.ts new file mode 100644 index 0000000000..0af877d3fe --- /dev/null +++ b/EdgeCraftRAG/ui/vue/src/utils/customRenderer.ts @@ -0,0 +1,131 @@ +import { marked } from "marked"; +import hljs from "highlight.js"; +import { formatCapitalize } from "./common"; +import ClipboardJS from "clipboard"; +import { message } from "ant-design-vue"; + +interface CodeRenderParams { + text: string; + lang?: string; +} + +class ClipboardManager { + private clipboard: ClipboardJS | null = null; + private observer: MutationObserver | null = null; + + constructor() { + this.autoInit(); + } + + private autoInit() { + if (typeof document === "undefined") return; + const init = () => { + this.init(".copy-btn"); + this.setupMutationObserver(); + }; + + if (document.readyState === "complete") { + init(); + } else { + document.addEventListener("DOMContentLoaded", init); + } + } + + private init(selector: string) { + this.destroy(); + + this.clipboard = new ClipboardJS(selector, { container: document.body }); + + this.clipboard.on("success", (e) => this.handleSuccess(e)); + this.clipboard.on("error", (e) => this.handleError(e)); + } + + private setupMutationObserver() { + this.observer = new MutationObserver((mutations) => { + const hasNewButtons = mutations.some((mutation) => + Array.from(mutation.addedNodes).some( + (node) => + node instanceof HTMLElement && + (node.matches(".copy-btn") || node.querySelector(".copy-btn")) + ) + ); + if (hasNewButtons) this.init(".copy-btn"); + }); + + this.observer.observe(document.body, { + childList: true, + subtree: true, + }); + } + + destroy() { + this.clipboard?.destroy(); + this.observer?.disconnect(); + this.clipboard = null; + this.observer = null; + } + + private handleSuccess(e: ClipboardJS.Event) { + e.clearSelection(); + message.success("Copy Successful !"); + const button = e.trigger as HTMLElement; + const copyIcon = button.querySelector(".copy-icon") as HTMLElement; + const successIcon = button.querySelector(".success-icon") as HTMLElement; + + copyIcon.style.display = "none"; + successIcon.style.display = "block"; + + let timeout = null; + if (timeout) clearTimeout(timeout); + + timeout = setTimeout(() => { + copyIcon.style.display = "block"; + successIcon.style.display = "none"; + }, 2000); + } + + private handleError(e: ClipboardJS.Event) { + message.error("Copy Failure !"); + } +} + +export const clipboardManager = new ClipboardManager(); + +const createCustomRenderer = () => { + const renderer = new marked.Renderer(); + + renderer.link = ({ href, title, text }) => { + return `${text}`; + }; + + renderer.code = ({ text, lang }: CodeRenderParams) => { + const language = hljs.getLanguage(lang || "") ? lang : "plaintext"; + const codeTitle = formatCapitalize(language || "Code"); + const codeHtml = hljs.highlight(text, { + language: language || "plaintext", + }).value; + const uniqueId = `code-${Date.now()}-${Math.random() + .toString(16) + .slice(2)}`; + + return ` +
+
+ ${codeTitle} + + + + +
+
${codeHtml}
+
+ `; + }; + + return renderer; +}; + +const CustomRenderer = createCustomRenderer(); +export default CustomRenderer; diff --git a/EdgeCraftRAG/ui/vue/src/views/chatbot/components/Chatbot.vue b/EdgeCraftRAG/ui/vue/src/views/chatbot/components/Chatbot.vue index 34464506bd..e4eaa7f032 100644 --- a/EdgeCraftRAG/ui/vue/src/views/chatbot/components/Chatbot.vue +++ b/EdgeCraftRAG/ui/vue/src/views/chatbot/components/Chatbot.vue @@ -102,7 +102,7 @@ const defaultBenchmark = reactive({ const messagesList = ref([ { - author: "Bot", + role: "assistant", content: "Hello! I am an Edge AI assistant. May I help you?", }, ]); @@ -145,18 +145,27 @@ const formatFormParam = () => { const { configuration } = props; return Object.assign({}, configuration, { - messages: inputKeywords.value, + messages: formatHistoryMessages(), }); }; + +const formatHistoryMessages = () => { + const messagesData = messagesList.value.slice(1, -1); + const historyMessages = messagesData.map(({ role, content }) => ({ + role, + content, + })); + return historyMessages; +}; const handleSendMessage = async () => { if (!inputKeywords.value.trim()) return; messagesList.value.push( { - author: "User", + role: "user", content: inputKeywords.value, }, { - author: "Bot", + role: "assistant", content: "", benchmark: _.cloneDeep(defaultBenchmark), } diff --git a/EdgeCraftRAG/ui/vue/src/views/chatbot/components/MessageItem.vue b/EdgeCraftRAG/ui/vue/src/views/chatbot/components/MessageItem.vue index e1a828c165..5edb5745e8 100644 --- a/EdgeCraftRAG/ui/vue/src/views/chatbot/components/MessageItem.vue +++ b/EdgeCraftRAG/ui/vue/src/views/chatbot/components/MessageItem.vue @@ -1,6 +1,6 @@