diff --git a/.gitignore b/.gitignore index 4eef6be..e35bf4a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ docs .workspace.codex .env -.vscode \ No newline at end of file +.vscode +.codex \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..0d47eba --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third_party/kvstore"] + path = third_party/kvstore + url = http://gitlab.0voice.com/lianyiheng/9.1-kvstore.git diff --git a/README.md b/README.md index 5c4b727..cdc78a6 100644 --- a/README.md +++ b/README.md @@ -8,23 +8,8 @@ protoc \ ``` ```shell -# ai-chat-web +git submodule update --init --recursive -# ai-chat-backend -docker build -t ai-chat-backend:1.0.0 . +./script/run.sh -# ai-chat-service -docker build -t ai-chat-service:1.0.0 . - -# chatgpt-web-frontend -HUSKY=0 pnpm bootstrap -pnpm dev - -docker build -t chatgpt-web-frontend:1.0.0 . - -# tokenizer -docker build -t tokenizer:1.0.0 . - -# keywords-filter -docker build -t keywords-filter:1.0.0 . ``` \ No newline at end of file diff --git a/ai-chat-service/docker.config.yaml b/ai-chat-service/docker.config.yaml index e819b02..a9c6240 100644 --- a/ai-chat-service/docker.config.yaml +++ b/ai-chat-service/docker.config.yaml @@ -17,9 +17,9 @@ chat: bot_desc: "你是一个AI助手,我需要你模拟一名资深的软件工程师来回答我的问题" min_response_tokens: 600 redis: - host: "redis" - port: 6379 - pwd: "" + host: "host.docker.internal" + port: 8888 + pwd: "123456" dependOn: sensitive: address: "sensitive-filter:50053" diff --git a/ai-chat-stack/compose.yaml b/ai-chat-stack/compose.yaml index 8205301..26167f8 100644 --- a/ai-chat-stack/compose.yaml +++ b/ai-chat-stack/compose.yaml @@ -74,6 +74,8 @@ services: - .env volumes: - ./configs/ai-chat-service.yaml:/app/config.yaml:ro + extra_hosts: + - "host.docker.internal:host-gateway" ports: - "50055:50055" depends_on: diff --git a/ai-chat-stack/configs/ai-chat-service.yaml b/ai-chat-stack/configs/ai-chat-service.yaml index 09919f7..7710524 100644 --- a/ai-chat-stack/configs/ai-chat-service.yaml +++ b/ai-chat-stack/configs/ai-chat-service.yaml @@ -17,9 +17,9 @@ chat: bot_desc: "你是一个AI助手,我需要你模拟一名资深的软件工程师来回答我的问题" min_response_tokens: 600 redis: - host: "127.0.0.1" + host: "host.docker.internal" port: 8888 - pwd: "" + pwd: "123456" dependOn: sensitive: address: "sensitive-filter:50053" diff --git a/ai-chat-web/src/locales/en-US.ts b/ai-chat-web/src/locales/en-US.ts index cb791ab..ff8bc90 100644 --- a/ai-chat-web/src/locales/en-US.ts +++ b/ai-chat-web/src/locales/en-US.ts @@ -50,6 +50,8 @@ export default { showRawText: 'Show as raw text', sourceSemantic: 'Semantic Match', sourceLlm: 'LLM Output', + inputTokensShort: 'Input', + outputTokensShort: 'Output', inputTokens: 'Input {count}', outputTokens: 'Output {count}', sessionTokens: 'Session {count} tokens', diff --git a/ai-chat-web/src/locales/zh-CN.ts b/ai-chat-web/src/locales/zh-CN.ts index 16d05dd..364f9e7 100644 --- a/ai-chat-web/src/locales/zh-CN.ts +++ b/ai-chat-web/src/locales/zh-CN.ts @@ -50,6 +50,8 @@ export default { showRawText: '显示原文', sourceSemantic: '语义匹配', sourceLlm: '大模型输出', + inputTokensShort: '输入', + outputTokensShort: '输出', inputTokens: 'Input {count}', outputTokens: 'Output {count}', sessionTokens: '本轮消耗 {count} tokens', diff --git a/ai-chat-web/src/locales/zh-TW.ts b/ai-chat-web/src/locales/zh-TW.ts index 111f37b..aa62786 100644 --- a/ai-chat-web/src/locales/zh-TW.ts +++ b/ai-chat-web/src/locales/zh-TW.ts @@ -50,6 +50,8 @@ export default { showRawText: '顯示原文', sourceSemantic: '語義匹配', sourceLlm: '大模型輸出', + inputTokensShort: '輸入', + outputTokensShort: '輸出', inputTokens: 'Input {count}', outputTokens: 'Output {count}', sessionTokens: '本輪消耗 {count} tokens', diff --git a/ai-chat-web/src/views/chat/components/Message/index.vue b/ai-chat-web/src/views/chat/components/Message/index.vue index 332c9b2..8c40a41 100644 --- a/ai-chat-web/src/views/chat/components/Message/index.vue +++ b/ai-chat-web/src/views/chat/components/Message/index.vue @@ -54,28 +54,43 @@ const sourceLabel = computed(() => { const sourceClass = computed(() => { switch (props.messageMeta?.source) { case 'semantic_match': - return 'border-sky-200 bg-sky-50 text-sky-700 dark:border-sky-900/60 dark:bg-sky-950/40 dark:text-sky-300' case 'llm': - return 'border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/40 dark:text-amber-300' + return 'border-[#d8e2eb] bg-[#f7fafc] text-[#52606d] dark:border-neutral-700 dark:bg-[#1a1d22] dark:text-neutral-200' default: return 'border-[#d0d7de] bg-white text-[#57606a] dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-300' } }) -const inputUsageLabel = computed(() => { - const usage = props.messageMeta?.usage - if (!usage || props.inversion) - return '' - - return t('chat.inputTokens', { count: usage.prompt_tokens }) +const sourceIconClass = computed(() => { + switch (props.messageMeta?.source) { + case 'semantic_match': + return 'bg-emerald-50 text-emerald-600 shadow-[inset_0_0_0_1px_rgba(52,211,153,0.18)] dark:bg-emerald-950/35 dark:text-emerald-300' + case 'llm': + return 'bg-slate-100 text-slate-500 shadow-[inset_0_0_0_1px_rgba(148,163,184,0.18)] dark:bg-slate-800/70 dark:text-slate-300' + default: + return 'bg-white/90 text-[#52606d] shadow-[inset_0_0_0_1px_rgba(130,140,150,0.14)] dark:bg-neutral-800 dark:text-neutral-300' + } }) -const outputUsageLabel = computed(() => { +const tokenStats = computed(() => { const usage = props.messageMeta?.usage if (!usage || props.inversion) - return '' + return [] - return t('chat.outputTokens', { count: usage.completion_tokens }) + return [ + { + key: 'input', + label: t('chat.inputTokensShort'), + count: usage.prompt_tokens, + icon: 'ri:arrow-right-up-line', + }, + { + key: 'output', + label: t('chat.outputTokensShort'), + count: usage.completion_tokens, + icon: 'ri:sparkling-line', + }, + ] }) const options = computed(() => { @@ -138,30 +153,29 @@ function handleRegenerate() {