diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..a8de724 Binary files /dev/null and b/.DS_Store differ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..eb15b1f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,53 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +This is a 1:1 pixel-perfect clone of the Google Gemini chat interface, built with Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS 4, and shadcn/ui. It was generated via [v0.app](https://v0.app/chat/lx6pc6oofZh) and auto-synced to this repo. Deployed on Vercel. + +## Commands + +```bash +npm install # Install dependencies +npm run dev # Start dev server (localhost:3000) +npm run build # Build for production +npm run lint # Run ESLint +npm start # Start production server +``` + +## Architecture + +### Entry Point +- `app/page.tsx` — renders `` only; all logic lives in components + +### Core Component: `components/gemini/GeminiChat.tsx` +The root stateful component. Owns all state: sidebar open/close, active conversation, message list, typing indicator. Composes all other Gemini components. + +### Gemini Component Breakdown + +| Component | Purpose | +|---|---| +| `GeminiSidebar.tsx` | Left sidebar — logo, new chat button, conversation history list, bottom nav (Help/Activity/Extensions), user avatar | +| `GeminiTopbar.tsx` | Top bar — hamburger toggle, model selector dropdown (Gemini 2.0 Flash etc.), settings + avatar | +| `GeminiWelcome.tsx` | Empty state — gradient greeting, 4 suggestion cards | +| `GeminiMessage.tsx` | Single message — user bubble (right-aligned, bg pill) vs AI response (left-aligned, ◆ icon, no bubble, markdown-like rendering) | +| `GeminiInput.tsx` | Bottom input — rounded container, attachment icon, auto-resize textarea, mic + send button | +| `GeminiTypingIndicator.tsx` | Animated dots shown while AI is "responding" | +| `ExtensionsPanel.tsx` | Extensions panel UI | + +### Styling +- Tailwind CSS 4 with `@tailwindcss/postcss` +- Dark theme only — hardcoded color palette: + - Page bg: `#131314`, Sidebar: `#1e1e1e`, Hover/card: `#2a2a2a`, Border: `#3a3a3a` + - Primary text: `#e3e3e3`, Muted: `#9aa0a6` + - Accent gradient: `from-[#4285f4] to-[#a855f7]` +- `components/ui/` — standard shadcn/ui primitives (do not modify directly) + +### Key Patterns +- All components use `"use client"` — no server components beyond the page shell +- `cn()` from `@/lib/utils` for conditional class merging +- No external API calls — all data is mock/local state in `GeminiChat.tsx` + +## Sync Workflow +This repo is auto-synced from v0.app. Changes made on v0.app are pushed here automatically, then deployed to Vercel. Manual edits here may be overwritten on the next v0 sync. diff --git a/EXTERNAL_SERVICES.md b/EXTERNAL_SERVICES.md new file mode 100644 index 0000000..a26b689 --- /dev/null +++ b/EXTERNAL_SERVICES.md @@ -0,0 +1,151 @@ +# 外部服务接入配置 + +> **使用说明**:此文档用于记录外部服务的接入方式、环境变量和调用示例,便于开发、联调与排障。 +> +> 当前服务按“代码已支持 + 部署环境变量由 Azure Web App 提供”的口径记录为已接入;实际运行效果仍以部署环境变量是否正确配置为准。 +> +> 已接入的服务会标注 ✅。 + +--- + +## 1. LLM 大语言模型 ✅ 已接入 + +> 当前使用 Azure OpenAI,已在后端 graph.py / main.py 中集成。 + +### 环境变量(已配置) +``` +AZURE_OPENAI_ENDPOINT=https://ai-gzy0016231ai975636166896.cognitiveservices.azure.com/openai/responses?api-version=2025-04-01-preview/ +AZURE_OPENAI_API_KEY=DlsBBFJ0RgMGdKxsdBWnlYj6IRdULzflGsKFCXnMBzqs4ZVHMtqZJQQJ99CCACHYHv6XJ3w3AAAAACOG45do +AZURE_OPENAI_API_VERSION=2025-04-01-preview +AZURE_OPENAI_DEPLOYMENT=gpt-5.4 +``` + +### 请求示例 +```bash +curl -X POST "${AZURE_OPENAI_ENDPOINT}/openai/deployments/${AZURE_OPENAI_DEPLOYMENT}/chat/completions?api-version=${AZURE_OPENAI_API_VERSION}" \ + -H "Content-Type: application/json" \ + -H "api-key: ${AZURE_OPENAI_API_KEY}" \ + -d '{ + "messages": [{"role": "user", "content": "你好"}], + "max_tokens": 1000 + }' +``` + +--- + +## 2. 内部知识库检索 ✅ 已接入 + +> 当前通过 agnetdoc Function App 调用 Azure AI Search。 + +### 环境变量(已配置) +``` +KB_AGENT_URL=https://agnetdoc-cve0guf5h8eggmej.southeastasia-01.azurewebsites.net +KB_AGENT_API_KEY=LdyzZlS3Nn1xFejqPsHn1nW-zsj9FLpC5KCbopCkQWKCAzFuLEUU4w== +KB_AGENT_SEARCH_PATH=/api/v1/search +KB_AGENT_SEARCH_TIMEOUT_SEC=15 +``` + +### 请求示例 +```bash +curl -X POST "${KB_AGENT_URL}/api/v1/search" \ + -H "Content-Type: application/json" \ + -H "api-key: ${KB_AGENT_API_KEY}" \ + -d '{ + "query": "Taiji Agent 产品规划", + "top": 8, + "search_mode": "hybrid" + }' +``` + +### 响应格式 +```json +{ + "results": [ + { + "id": "xxx", + "title": "文档标题", + "content": "文档内容...", + "category": "分类", + "score": 0.85, + "url": "https://...", + "tags": ["tag1"], + "project": "项目名" + } + ] +} +``` + +--- + +## 3. 外部 AI 搜索 ✅ 已接入 +目前外部搜索采用https://mcp.jina.ai/sse 或者 /v1 可优先测试 +jina_e26dc30420a44a1e859216528065b203TkMRmsoz-FgMDQC5FZX9jr5oF2CI +要求使用搜索和读取两个工具,并且要结合重排模型使用。 +满足企业级的搜索准确度,包括不限于图片和视频 +按照深度和快速来定义搜索内容和搜索的质量,还需要满足前端的展示。 + + + +--- + +## 4. 沙盒代码执行 ✅ 已接入 +沙盒采用现成的解决方案。https://docs.langchain.com/oss/python/integrations/sandboxes/daytona + +https://app.daytona.io/api +dtn_066b83f57f0337c96fae2ef1f5c8456477a39dfbd5fc615456263fd4947108c2 +依然要满足前端输出要求。 + + +## 5. 文档生成 Agent ✅ 已接入 +http://doc-creator-agent-b0d02105-a557fe.taijiagnet.com +sk-t5R8jkEp6IA7_ghJ6Hy1rQ +http://agnetdoc.taijiaicloud.com/node/019cd223-9d13-7566-a2ea-52ee67645463 + + +## 6. 工单系统 ✅ 已接入 + +> gongdan 工单系统,只读集成。 + +### 环境变量(已配置) +``` +GONGDAN_API_BASE=https://gongdan-b5fzbtgteqd5gzfb.eastasia-01.azurewebsites.net +GONGDAN_API_KEY=gd_live_a28b3db84385be75d1d3b6b6023784c27200d045 +``` + +### 请求示例 +```bash +# 工单列表 +curl -X GET "${GONGDAN_API_BASE}/api/tickets?page=1&pageSize=20" \ + -H "X-Api-Key: ${GONGDAN_API_KEY}" + +# 工单详情 +curl -X GET "${GONGDAN_API_BASE}/api/tickets/{ticketId}" \ + -H "X-Api-Key: ${GONGDAN_API_KEY}" +``` + +--- + +## 7. 数据库 ✅ 已接入(可选) + +> 当前代码支持 `DATABASE_URL` 持久化;未配置时会回退到内存模式。 + +### 当前代码侧现状 +- `persistence.py` 已支持 PostgreSQL +- 线程 / 分支等数据可持久化 +- 文档 workspace 元数据、sandbox 运行记录等也有数据库侧支持 +- 若未配置 `DATABASE_URL`,系统仍可运行,但持久化能力会受限 + +### 当前示例 +``` +DATABASE_URL=postgresql://USER:PASSWORD@:5432/yydn?sslmode=require +``` +dataope.postgres.database.azure.com +azuredb:h13nYoFJX6QrfLzB8bdipEUCjsZq2P7W + +### 说明 +- 如果后续要迁移数据库主机,请单独更新部署环境变量与运维文档 + + + +--- + diff --git a/claudehd.md b/claudehd.md new file mode 100644 index 0000000..cc869c0 --- /dev/null +++ b/claudehd.md @@ -0,0 +1,106 @@ +# claudehd.md — so-c-chat-clone 后端功能方案 + +**前端代码未经明确指定不允许修改。** + +--- + +## 功能一:基础对话 + +**做什么:** 用户发送消息,后端调用 LLM 生成回复,返回 Markdown 文本给前端渲染。 + +**用什么:** +- **FastAPI**(Python)— 提供 `POST /chat` 接口,接收 `message` + `thread_id` + `model` +- **Azure OpenAI SDK(异步)** — 调用 gpt-5.4 部署,返回文本内容 +- **内存字典** — 按 `thread_id` 存储多轮对话历史,拼入每次请求的 messages 数组实现上下文连续 + +**模型行为:** +- `model=flash` → `max_tokens=500`,`temperature=0.2`,快速简洁 +- `model=pro` → `max_tokens=4096`,`temperature=0.3`,深度详细 + +--- + +## 功能二:内部知识库检索 + +**做什么:** 用户在输入框激活"内部知识库"工具后,发送消息前先检索企业知识库,将相关文档片段注入 LLM prompt,让回复基于内部知识。 + +**用什么:** +- **httpx(异步)** — 调用 KB Agent REST API(Azure AI Search 代理) +- 检索参数:`search_mode=hybrid`,`top=5` +- 检索结果格式化为背景材料追加到 system prompt,LLM 基于此生成回复 + +--- + +## 功能三:外部 AI 搜索 + +**做什么:** 用户激活"搜索"工具后,后端联网检索实时信息(含图片、视频),经重排后注入 LLM,回复引用真实来源。 + +**用什么:** +- **Jina Search API** (`https://s.jina.ai/`) — 搜索网页,返回标题+摘要+URL +- **Jina Reader API** (`https://r.jina.ai/{url}`) — 读取搜索结果全文 +- **Jina Rerank API** (`jina-reranker-v2-base-multilingual`) — 对结果按相关性重排,提升准确度 +- **httpx(异步)** — 并发调用以上三个接口 + +**按模型深度区分:** +- `flash` → 搜索 top=3,timeout=8s,跳过重排,追求速度 +- `pro` → 搜索 top=10,timeout=20s,Rerank 取 top=5,追求准确 + +--- + +## 功能四:沙盒代码执行 + +**做什么:** 用户激活"沙盒"工具并提出编程需求时,后端在隔离环境中执行代码,将 stdout/stderr 格式化为 Markdown 代码块注入回复。 + +**用什么:** +- **Daytona API** (`https://app.daytona.io/api`) — 创建隔离 workspace → 上传代码 → 执行 → 获取输出 → 销毁 workspace +- **httpx(异步)** — 调用 Daytona REST API +- 执行结果以 Markdown 代码块形式追加到 LLM 最终回复 + +--- + +## 功能五:文档生成 + +**做什么:** 用户激活"文档生成"工具并描述需求时,后端调用 Doc Creator Agent 生成 Word/PPT/表格文件,将下载链接追加到回复末尾。 + +**用什么:** +- **Doc Creator Agent** (`http://doc-creator-agent-b0d02105-a557fe.taijiagnet.com`) — 传入 prompt,返回生成文件的 URL +- **httpx(异步)** — 调用 Agent REST API +- 输出类型自动识别:含 ppt/slides → PPT;含 table/excel → 表格;其余 → Word + +--- + +## 功能六:工单数据接入 + +**做什么:** 前端 ExtensionsPanel 连接工单系统后,展示真实工单列表(P0-P3 优先级、状态)。后端作为代理拉取 Gongdan 工单数据。 + +**用什么:** +- **FastAPI** — 提供 `GET /tickets` 接口,支持 `page` / `pageSize` 分页参数 +- **httpx(异步)** — 代理调用 Gongdan API,透传工单数据 +- 返回字段严格对齐前端 `TicketData` 类型:`id / title / status / priority / createdAt` + +--- + +## 功能七:多轮对话持久化 + +**做什么:** 对话历史在服务重启后不丢失,支持恢复历史对话上下文。 + +**用什么:** +- **PostgreSQL**(Azure,`dataope.postgres.database.azure.com`)— 存储 thread 和 message 记录 +- **asyncpg** — 异步数据库驱动,不阻塞事件循环 +- 未配置 `DATABASE_URL` 时自动降级为内存字典(开发模式) + +--- + +## 技术栈总览 + +| 层 | 技术 | +|----|------| +| Web 框架 | FastAPI + Uvicorn | +| LLM | Azure OpenAI SDK (AsyncAzureOpenAI) | +| HTTP 客户端 | httpx(全异步) | +| 外部搜索 | Jina Search / Reader / Rerank | +| 知识库 | KB Agent (Azure AI Search 代理) | +| 沙盒 | Daytona API | +| 文档生成 | Doc Creator Agent | +| 工单 | Gongdan API(只读代理) | +| 数据库 | PostgreSQL / asyncpg(可选) | +| 部署 | Azure Web App (Python 3.11) | diff --git a/README.md b/frontend/README.md similarity index 100% rename from README.md rename to frontend/README.md diff --git a/app/globals.css b/frontend/app/globals.css similarity index 100% rename from app/globals.css rename to frontend/app/globals.css diff --git a/app/layout.tsx b/frontend/app/layout.tsx similarity index 100% rename from app/layout.tsx rename to frontend/app/layout.tsx diff --git a/app/page.tsx b/frontend/app/page.tsx similarity index 100% rename from app/page.tsx rename to frontend/app/page.tsx diff --git a/components.json b/frontend/components.json similarity index 100% rename from components.json rename to frontend/components.json diff --git a/components/gemini/ExtensionsPanel.tsx b/frontend/components/gemini/ExtensionsPanel.tsx similarity index 100% rename from components/gemini/ExtensionsPanel.tsx rename to frontend/components/gemini/ExtensionsPanel.tsx diff --git a/components/gemini/GeminiChat.tsx b/frontend/components/gemini/GeminiChat.tsx similarity index 100% rename from components/gemini/GeminiChat.tsx rename to frontend/components/gemini/GeminiChat.tsx diff --git a/components/gemini/GeminiInput.tsx b/frontend/components/gemini/GeminiInput.tsx similarity index 100% rename from components/gemini/GeminiInput.tsx rename to frontend/components/gemini/GeminiInput.tsx diff --git a/components/gemini/GeminiMessage.tsx b/frontend/components/gemini/GeminiMessage.tsx similarity index 100% rename from components/gemini/GeminiMessage.tsx rename to frontend/components/gemini/GeminiMessage.tsx diff --git a/components/gemini/GeminiSidebar.tsx b/frontend/components/gemini/GeminiSidebar.tsx similarity index 100% rename from components/gemini/GeminiSidebar.tsx rename to frontend/components/gemini/GeminiSidebar.tsx diff --git a/components/gemini/GeminiTopbar.tsx b/frontend/components/gemini/GeminiTopbar.tsx similarity index 100% rename from components/gemini/GeminiTopbar.tsx rename to frontend/components/gemini/GeminiTopbar.tsx diff --git a/components/gemini/GeminiTypingIndicator.tsx b/frontend/components/gemini/GeminiTypingIndicator.tsx similarity index 100% rename from components/gemini/GeminiTypingIndicator.tsx rename to frontend/components/gemini/GeminiTypingIndicator.tsx diff --git a/components/gemini/GeminiWelcome.tsx b/frontend/components/gemini/GeminiWelcome.tsx similarity index 100% rename from components/gemini/GeminiWelcome.tsx rename to frontend/components/gemini/GeminiWelcome.tsx diff --git a/components/theme-provider.tsx b/frontend/components/theme-provider.tsx similarity index 100% rename from components/theme-provider.tsx rename to frontend/components/theme-provider.tsx diff --git a/components/ui/accordion.tsx b/frontend/components/ui/accordion.tsx similarity index 100% rename from components/ui/accordion.tsx rename to frontend/components/ui/accordion.tsx diff --git a/components/ui/alert-dialog.tsx b/frontend/components/ui/alert-dialog.tsx similarity index 100% rename from components/ui/alert-dialog.tsx rename to frontend/components/ui/alert-dialog.tsx diff --git a/components/ui/alert.tsx b/frontend/components/ui/alert.tsx similarity index 100% rename from components/ui/alert.tsx rename to frontend/components/ui/alert.tsx diff --git a/components/ui/aspect-ratio.tsx b/frontend/components/ui/aspect-ratio.tsx similarity index 100% rename from components/ui/aspect-ratio.tsx rename to frontend/components/ui/aspect-ratio.tsx diff --git a/components/ui/avatar.tsx b/frontend/components/ui/avatar.tsx similarity index 100% rename from components/ui/avatar.tsx rename to frontend/components/ui/avatar.tsx diff --git a/components/ui/badge.tsx b/frontend/components/ui/badge.tsx similarity index 100% rename from components/ui/badge.tsx rename to frontend/components/ui/badge.tsx diff --git a/components/ui/breadcrumb.tsx b/frontend/components/ui/breadcrumb.tsx similarity index 100% rename from components/ui/breadcrumb.tsx rename to frontend/components/ui/breadcrumb.tsx diff --git a/components/ui/button-group.tsx b/frontend/components/ui/button-group.tsx similarity index 100% rename from components/ui/button-group.tsx rename to frontend/components/ui/button-group.tsx diff --git a/components/ui/button.tsx b/frontend/components/ui/button.tsx similarity index 100% rename from components/ui/button.tsx rename to frontend/components/ui/button.tsx diff --git a/components/ui/calendar.tsx b/frontend/components/ui/calendar.tsx similarity index 100% rename from components/ui/calendar.tsx rename to frontend/components/ui/calendar.tsx diff --git a/components/ui/card.tsx b/frontend/components/ui/card.tsx similarity index 100% rename from components/ui/card.tsx rename to frontend/components/ui/card.tsx diff --git a/components/ui/carousel.tsx b/frontend/components/ui/carousel.tsx similarity index 100% rename from components/ui/carousel.tsx rename to frontend/components/ui/carousel.tsx diff --git a/components/ui/chart.tsx b/frontend/components/ui/chart.tsx similarity index 100% rename from components/ui/chart.tsx rename to frontend/components/ui/chart.tsx diff --git a/components/ui/checkbox.tsx b/frontend/components/ui/checkbox.tsx similarity index 100% rename from components/ui/checkbox.tsx rename to frontend/components/ui/checkbox.tsx diff --git a/components/ui/collapsible.tsx b/frontend/components/ui/collapsible.tsx similarity index 100% rename from components/ui/collapsible.tsx rename to frontend/components/ui/collapsible.tsx diff --git a/components/ui/command.tsx b/frontend/components/ui/command.tsx similarity index 100% rename from components/ui/command.tsx rename to frontend/components/ui/command.tsx diff --git a/components/ui/context-menu.tsx b/frontend/components/ui/context-menu.tsx similarity index 100% rename from components/ui/context-menu.tsx rename to frontend/components/ui/context-menu.tsx diff --git a/components/ui/dialog.tsx b/frontend/components/ui/dialog.tsx similarity index 100% rename from components/ui/dialog.tsx rename to frontend/components/ui/dialog.tsx diff --git a/components/ui/drawer.tsx b/frontend/components/ui/drawer.tsx similarity index 100% rename from components/ui/drawer.tsx rename to frontend/components/ui/drawer.tsx diff --git a/components/ui/dropdown-menu.tsx b/frontend/components/ui/dropdown-menu.tsx similarity index 100% rename from components/ui/dropdown-menu.tsx rename to frontend/components/ui/dropdown-menu.tsx diff --git a/components/ui/empty.tsx b/frontend/components/ui/empty.tsx similarity index 100% rename from components/ui/empty.tsx rename to frontend/components/ui/empty.tsx diff --git a/components/ui/field.tsx b/frontend/components/ui/field.tsx similarity index 100% rename from components/ui/field.tsx rename to frontend/components/ui/field.tsx diff --git a/components/ui/form.tsx b/frontend/components/ui/form.tsx similarity index 100% rename from components/ui/form.tsx rename to frontend/components/ui/form.tsx diff --git a/components/ui/hover-card.tsx b/frontend/components/ui/hover-card.tsx similarity index 100% rename from components/ui/hover-card.tsx rename to frontend/components/ui/hover-card.tsx diff --git a/components/ui/input-group.tsx b/frontend/components/ui/input-group.tsx similarity index 100% rename from components/ui/input-group.tsx rename to frontend/components/ui/input-group.tsx diff --git a/components/ui/input-otp.tsx b/frontend/components/ui/input-otp.tsx similarity index 100% rename from components/ui/input-otp.tsx rename to frontend/components/ui/input-otp.tsx diff --git a/components/ui/input.tsx b/frontend/components/ui/input.tsx similarity index 100% rename from components/ui/input.tsx rename to frontend/components/ui/input.tsx diff --git a/components/ui/item.tsx b/frontend/components/ui/item.tsx similarity index 100% rename from components/ui/item.tsx rename to frontend/components/ui/item.tsx diff --git a/components/ui/kbd.tsx b/frontend/components/ui/kbd.tsx similarity index 100% rename from components/ui/kbd.tsx rename to frontend/components/ui/kbd.tsx diff --git a/components/ui/label.tsx b/frontend/components/ui/label.tsx similarity index 100% rename from components/ui/label.tsx rename to frontend/components/ui/label.tsx diff --git a/components/ui/menubar.tsx b/frontend/components/ui/menubar.tsx similarity index 100% rename from components/ui/menubar.tsx rename to frontend/components/ui/menubar.tsx diff --git a/components/ui/navigation-menu.tsx b/frontend/components/ui/navigation-menu.tsx similarity index 100% rename from components/ui/navigation-menu.tsx rename to frontend/components/ui/navigation-menu.tsx diff --git a/components/ui/pagination.tsx b/frontend/components/ui/pagination.tsx similarity index 100% rename from components/ui/pagination.tsx rename to frontend/components/ui/pagination.tsx diff --git a/components/ui/popover.tsx b/frontend/components/ui/popover.tsx similarity index 100% rename from components/ui/popover.tsx rename to frontend/components/ui/popover.tsx diff --git a/components/ui/progress.tsx b/frontend/components/ui/progress.tsx similarity index 100% rename from components/ui/progress.tsx rename to frontend/components/ui/progress.tsx diff --git a/components/ui/radio-group.tsx b/frontend/components/ui/radio-group.tsx similarity index 100% rename from components/ui/radio-group.tsx rename to frontend/components/ui/radio-group.tsx diff --git a/components/ui/resizable.tsx b/frontend/components/ui/resizable.tsx similarity index 100% rename from components/ui/resizable.tsx rename to frontend/components/ui/resizable.tsx diff --git a/components/ui/scroll-area.tsx b/frontend/components/ui/scroll-area.tsx similarity index 100% rename from components/ui/scroll-area.tsx rename to frontend/components/ui/scroll-area.tsx diff --git a/components/ui/select.tsx b/frontend/components/ui/select.tsx similarity index 100% rename from components/ui/select.tsx rename to frontend/components/ui/select.tsx diff --git a/components/ui/separator.tsx b/frontend/components/ui/separator.tsx similarity index 100% rename from components/ui/separator.tsx rename to frontend/components/ui/separator.tsx diff --git a/components/ui/sheet.tsx b/frontend/components/ui/sheet.tsx similarity index 100% rename from components/ui/sheet.tsx rename to frontend/components/ui/sheet.tsx diff --git a/components/ui/sidebar.tsx b/frontend/components/ui/sidebar.tsx similarity index 100% rename from components/ui/sidebar.tsx rename to frontend/components/ui/sidebar.tsx diff --git a/components/ui/skeleton.tsx b/frontend/components/ui/skeleton.tsx similarity index 100% rename from components/ui/skeleton.tsx rename to frontend/components/ui/skeleton.tsx diff --git a/components/ui/slider.tsx b/frontend/components/ui/slider.tsx similarity index 100% rename from components/ui/slider.tsx rename to frontend/components/ui/slider.tsx diff --git a/components/ui/sonner.tsx b/frontend/components/ui/sonner.tsx similarity index 100% rename from components/ui/sonner.tsx rename to frontend/components/ui/sonner.tsx diff --git a/components/ui/spinner.tsx b/frontend/components/ui/spinner.tsx similarity index 100% rename from components/ui/spinner.tsx rename to frontend/components/ui/spinner.tsx diff --git a/components/ui/switch.tsx b/frontend/components/ui/switch.tsx similarity index 100% rename from components/ui/switch.tsx rename to frontend/components/ui/switch.tsx diff --git a/components/ui/table.tsx b/frontend/components/ui/table.tsx similarity index 100% rename from components/ui/table.tsx rename to frontend/components/ui/table.tsx diff --git a/components/ui/tabs.tsx b/frontend/components/ui/tabs.tsx similarity index 100% rename from components/ui/tabs.tsx rename to frontend/components/ui/tabs.tsx diff --git a/components/ui/textarea.tsx b/frontend/components/ui/textarea.tsx similarity index 100% rename from components/ui/textarea.tsx rename to frontend/components/ui/textarea.tsx diff --git a/components/ui/toast.tsx b/frontend/components/ui/toast.tsx similarity index 100% rename from components/ui/toast.tsx rename to frontend/components/ui/toast.tsx diff --git a/components/ui/toaster.tsx b/frontend/components/ui/toaster.tsx similarity index 100% rename from components/ui/toaster.tsx rename to frontend/components/ui/toaster.tsx diff --git a/components/ui/toggle-group.tsx b/frontend/components/ui/toggle-group.tsx similarity index 100% rename from components/ui/toggle-group.tsx rename to frontend/components/ui/toggle-group.tsx diff --git a/components/ui/toggle.tsx b/frontend/components/ui/toggle.tsx similarity index 100% rename from components/ui/toggle.tsx rename to frontend/components/ui/toggle.tsx diff --git a/components/ui/tooltip.tsx b/frontend/components/ui/tooltip.tsx similarity index 100% rename from components/ui/tooltip.tsx rename to frontend/components/ui/tooltip.tsx diff --git a/components/ui/use-mobile.tsx b/frontend/components/ui/use-mobile.tsx similarity index 100% rename from components/ui/use-mobile.tsx rename to frontend/components/ui/use-mobile.tsx diff --git a/components/ui/use-toast.ts b/frontend/components/ui/use-toast.ts similarity index 100% rename from components/ui/use-toast.ts rename to frontend/components/ui/use-toast.ts diff --git a/hooks/use-mobile.ts b/frontend/hooks/use-mobile.ts similarity index 100% rename from hooks/use-mobile.ts rename to frontend/hooks/use-mobile.ts diff --git a/hooks/use-toast.ts b/frontend/hooks/use-toast.ts similarity index 100% rename from hooks/use-toast.ts rename to frontend/hooks/use-toast.ts diff --git a/lib/utils.ts b/frontend/lib/utils.ts similarity index 100% rename from lib/utils.ts rename to frontend/lib/utils.ts diff --git a/next.config.mjs b/frontend/next.config.mjs similarity index 100% rename from next.config.mjs rename to frontend/next.config.mjs diff --git a/package.json b/frontend/package.json similarity index 100% rename from package.json rename to frontend/package.json diff --git a/postcss.config.mjs b/frontend/postcss.config.mjs similarity index 100% rename from postcss.config.mjs rename to frontend/postcss.config.mjs diff --git a/public/apple-icon.png b/frontend/public/apple-icon.png similarity index 100% rename from public/apple-icon.png rename to frontend/public/apple-icon.png diff --git a/public/icon-dark-32x32.png b/frontend/public/icon-dark-32x32.png similarity index 100% rename from public/icon-dark-32x32.png rename to frontend/public/icon-dark-32x32.png diff --git a/public/icon-light-32x32.png b/frontend/public/icon-light-32x32.png similarity index 100% rename from public/icon-light-32x32.png rename to frontend/public/icon-light-32x32.png diff --git a/public/icon.svg b/frontend/public/icon.svg similarity index 100% rename from public/icon.svg rename to frontend/public/icon.svg diff --git a/public/placeholder-logo.png b/frontend/public/placeholder-logo.png similarity index 100% rename from public/placeholder-logo.png rename to frontend/public/placeholder-logo.png diff --git a/public/placeholder-logo.svg b/frontend/public/placeholder-logo.svg similarity index 100% rename from public/placeholder-logo.svg rename to frontend/public/placeholder-logo.svg diff --git a/public/placeholder-user.jpg b/frontend/public/placeholder-user.jpg similarity index 100% rename from public/placeholder-user.jpg rename to frontend/public/placeholder-user.jpg diff --git a/public/placeholder.jpg b/frontend/public/placeholder.jpg similarity index 100% rename from public/placeholder.jpg rename to frontend/public/placeholder.jpg diff --git a/public/placeholder.svg b/frontend/public/placeholder.svg similarity index 100% rename from public/placeholder.svg rename to frontend/public/placeholder.svg diff --git a/styles/globals.css b/frontend/styles/globals.css similarity index 100% rename from styles/globals.css rename to frontend/styles/globals.css diff --git a/tsconfig.json b/frontend/tsconfig.json similarity index 100% rename from tsconfig.json rename to frontend/tsconfig.json diff --git a/gpthd.md b/gpthd.md new file mode 100644 index 0000000..4fdb024 --- /dev/null +++ b/gpthd.md @@ -0,0 +1,433 @@ +# SOC 项目后端功能方案(按功能拆解) + +> 约束:在未获得明确允许前,不修改前端交互,只补后端能力、接口和数据层。 +> 目标:严格围绕当前 `~/go/soc` 这个 Gemini 风格前端,为每一个功能明确说明“用什么技术,完成什么功能,怎么落地”。 + +--- + +## 1. 对话流式回复 + +### 要完成什么功能 +- 用户在当前聊天输入框发送消息 +- 后端实时返回回答内容 +- 支持“思考中 / 检索中 / 生成中”的流式状态 +- 不改变现有前端交互,只替换当前前端 `simulateAIResponse()` + +### 用什么技术 +- **FastAPI**:提供聊天接口 +- **SSE(Server-Sent Events)**:把大模型回答流式推给前端 +- **Azure OpenAI**:生成最终回答 +- **PostgreSQL**:保存消息记录和会话记录 + +### 怎么落地 +- 新增接口:`POST /api/chat/stream` +- 前端发送用户消息到后端 +- 后端先写入用户消息 +- 再调用 Azure OpenAI 流式生成 +- 将生成过程通过 SSE 持续返回给前端 +- 最终把 assistant 回复保存入库 + +### 输出结果 +- 前端保持当前 Gemini 风格交互不变 +- 用户发送后能看到真实流式回答 +- 替换掉前端 mock 返回逻辑 + +--- + +## 2. 会话管理 + +### 要完成什么功能 +- 左侧历史会话列表从真实数据读取 +- 支持新建会话 +- 支持切换会话 +- 支持删除会话 +- 支持自动生成会话标题 + +### 用什么技术 +- **FastAPI**:提供 REST API +- **PostgreSQL**:保存 conversation 和 message +- **SQLAlchemy / SQLModel**:管理数据表和查询 + +### 怎么落地 +- 新增接口: + - `GET /api/conversations` + - `POST /api/conversations` + - `GET /api/conversations/{id}` + - `PATCH /api/conversations/{id}` + - `DELETE /api/conversations/{id}` +- 用户首次发送消息时自动创建会话 +- 默认用首条消息前 20~30 字生成标题 +- 前端左侧栏改为读取真实会话数据 + +### 输出结果 +- 当前左侧 mock 会话列表替换成数据库真实数据 +- 用户聊天记录可恢复 + +--- + +## 3. 内部知识库检索 + +### 要完成什么功能 +- 当用户提问产品、方案、配置、内部资料时 +- 后端优先查询内部知识库 +- 再把知识库结果交给大模型总结回答 +- 回答中带来源信息 + +### 用什么技术 +- **KB_AGENT 接口**:调用内部知识库搜索 +- **FastAPI service layer**:封装知识库调用 +- **Azure OpenAI**:对检索结果总结与生成回答 + +### 怎么落地 +- 新增服务模块:`kb_agent.py` +- 根据 `EXTERNAL_SERVICES.md` 中的: + - `KB_AGENT_URL` + - `KB_AGENT_API_KEY` + - `KB_AGENT_SEARCH_PATH` +- 后端在识别为内部知识问题时: + 1. 请求知识库搜索 + 2. 获取 top-k 文档片段 + 3. 做摘要裁剪 + 4. 将结果作为上下文交给 Azure OpenAI +- 前端不改交互,只在回答里附带引用来源块 + +### 输出结果 +- 当前产品类问题不再纯靠大模型空想 +- 回答能基于内部知识库 +- 更适合售前、售后、研发支持场景 + +--- + +## 4. 外部 AI 搜索 + +### 要完成什么功能 +- 当用户问实时互联网信息、行业动态、外部资料时 +- 后端自动执行外部搜索 +- 支持网页搜索、内容读取、结果重排 +- 满足快速模式和深度模式 +- 后续支持图片和视频结果展示 + +### 用什么技术 +- **Jina Search API**:做外部搜索 +- **Jina Reader**:读取网页正文 +- **Rerank 模型**:对结果重排 +- **Azure OpenAI**:基于外部资料生成答案 + +### 怎么落地 +- 新增模块: + - `jina_search.py` + - `jina_reader.py` + - `reranker.py` +- 固定流程: + - Search -> Read -> Rerank -> LLM +- 提供三种模式: + - `fast`:低延迟,少量搜索 + - `deep`:高质量,多轮检索 + - `auto`:后端自动判断 +- 前端仍保持原有聊天区交互,只增加来源区块展示 + +### 输出结果 +- 外部问题可获得更准确结果 +- 不再只依赖大模型参数知识 +- 满足企业级搜索准确度要求 + +--- + +## 5. 工单系统只读接入 + +### 要完成什么功能 +- 支持查询工单列表 +- 支持查询工单详情 +- 支持汇总最近高优先级工单 +- 支持在聊天中回答“最近有什么 P0/P1 工单”“某类问题集中在哪里” +- 支持首页/聊天区展示工单摘要数据 + +### 用什么技术 +- **Gongdan HTTP API**:工单数据来源 +- **FastAPI**:对前端提供统一工单接口 +- **PostgreSQL(可选缓存)**:保存摘要缓存或查询记录 +- **Azure OpenAI**:对工单数据做归纳总结 + +### 怎么落地 +- 新增模块:`gongdan_client.py` +- 新增接口: + - `GET /api/tickets/summary` + - `GET /api/tickets` + - `GET /api/tickets/{id}` +- 对话场景下: + - 用户问工单问题 + - 后端查询 gongdan + - 将结果整理后交给大模型总结 +- 非对话场景下: + - 前端通过 summary 接口读取摘要 + +### 输出结果 +- 当前前端 mock 工单摘要可替换为真实工单数据 +- 用户能直接在聊天里分析工单问题 + +--- + +## 6. 文档生成 + +### 要完成什么功能 +- 用户在聊天中要求生成方案、汇报、纪要、总结 +- 后端把需求提交给文档生成 Agent +- 返回任务状态 +- 文档完成后可返回下载地址或结果卡片 + +### 用什么技术 +- **Doc Creator Agent HTTP API**:生成正式文档 +- **FastAPI BackgroundTasks / 异步任务机制**:管理任务状态 +- **PostgreSQL**:保存文档任务记录 +- **Azure OpenAI**:前置整理文档提纲或结构 + +### 怎么落地 +- 新增接口: + - `POST /api/documents/generate` + - `GET /api/documents/{task_id}` +- 对话中识别“生成文档”类意图 +- 后端创建任务记录 +- 调用 doc creator agent +- 前端保持当前聊天交互,后续只在消息中增加文档结果卡片 + +### 输出结果 +- 用户可从聊天直接发起正式文档生成 +- 满足销售、售前、汇报场景 + +--- + +## 7. 沙盒代码执行 + +### 要完成什么功能 +- 处理表格、JSON、日志、数据分析类任务 +- 允许后端在安全沙盒中执行代码 +- 返回执行结果、图表、文件 +- 不直接改前端交互,只把结果作为消息内容或附件返回 + +### 用什么技术 +- **Daytona Sandbox**:安全执行环境 +- **FastAPI**:封装沙盒执行入口 +- **Python 工具链**:pandas / matplotlib / json / csv 等 +- **PostgreSQL**:记录执行任务 + +### 怎么落地 +- 新增接口:`POST /api/sandbox/run` +- 第一阶段不开放任意代码执行 +- 先封装几类固定能力: + - CSV 汇总 + - JSON 转换 + - 数据统计 + - 图表生成 +- 对话编排层按意图决定是否调用 sandbox + +### 输出结果 +- 数据分析、表格处理能力可真正执行 +- 后端具备“算”的能力,而不只是“说”的能力 + +--- + +## 8. 附件上传与解析 + +### 要完成什么功能 +- 用户上传文件后,后端能接收附件 +- 保存附件元数据 +- 提取文本内容供知识理解、搜索或分析使用 +- 后续支持文档总结、数据分析、代码执行 + +### 用什么技术 +- **FastAPI UploadFile**:接收文件 +- **对象存储/本地文件存储**:保存附件 +- **文本解析库**:PDF、DOCX、TXT、CSV 解析 +- **PostgreSQL**:保存附件元数据 + +### 怎么落地 +- 新增接口: + - `POST /api/attachments` + - `GET /api/attachments/{id}` +- 后端保存文件路径与文件类型 +- 针对不同格式做解析 +- 将解析文本挂到对应消息上下文里 + +### 输出结果 +- 后续聊天可真正支持“基于附件分析” +- 为文档生成、沙盒分析、知识问答提供基础能力 + +--- + +## 9. 工具编排层 + +### 要完成什么功能 +- 判断用户问题该调用哪个能力 +- 决定先查 KB、还是先查工单、还是先外部搜索 +- 决定是否进入文档生成或沙盒执行 +- 把多个工具结果统一整理成大模型上下文 + +### 用什么技术 +- **Python Orchestrator**:自定义编排逻辑 +- **Azure OpenAI**:辅助做工具选择与结果总结 +- **FastAPI service layer**:承接 API 和工具层 + +### 怎么落地 +- 新增模块: + - `planner.py` + - `chat_orchestrator.py` + - `context_builder.py` +- 第一阶段可以先做规则驱动: + - 问产品/项目 -> KB + - 问实时外部信息 -> Search + - 问工单 -> Tickets + - 问生成汇报 -> Documents + - 问数据处理 -> Sandbox +- 第二阶段再逐步引入 LLM 辅助路由 + +### 输出结果 +- 后端从“多个孤立接口”升级成“统一智能后端” +- 前端仍然只需要一个对话入口 + +--- + +## 10. 数据持久化 + +### 要完成什么功能 +- 保存历史会话 +- 保存聊天消息 +- 保存工具调用记录 +- 保存附件记录 +- 保存文档任务记录 + +### 用什么技术 +- **PostgreSQL**:主数据库 +- **SQLAlchemy / SQLModel**:ORM +- **Alembic**:数据库迁移 + +### 怎么落地 +- 至少建立以下表: + - `conversations` + - `messages` + - `tool_runs` + - `attachments` + - `document_tasks` +- 以后如需多租户,再增加: + - `users` + - `organizations` + - `memberships` + - `audit_logs` + +### 输出结果 +- 数据不丢失 +- 会话可追溯 +- 工具调用过程可排查 + +--- + +## 11. 接口层总表 + +### 第一阶段建议建设的接口 + +#### 基础接口 +- `GET /health` + +#### 会话接口 +- `GET /api/conversations` +- `POST /api/conversations` +- `GET /api/conversations/{id}` +- `PATCH /api/conversations/{id}` +- `DELETE /api/conversations/{id}` + +#### 聊天接口 +- `POST /api/chat/stream` + +#### 工单接口 +- `GET /api/tickets/summary` +- `GET /api/tickets` +- `GET /api/tickets/{id}` + +#### 搜索接口 +- `POST /api/search/internal` +- `POST /api/search/external` + +#### 文档接口 +- `POST /api/documents/generate` +- `GET /api/documents/{task_id}` + +#### 附件接口 +- `POST /api/attachments` +- `GET /api/attachments/{id}` + +#### 沙盒接口 +- `POST /api/sandbox/run` + +--- + +## 12. 推荐技术组合总结 + +### 基础后端框架 +- **FastAPI**:API 服务 +- **Uvicorn / Gunicorn**:服务运行 + +### 数据层 +- **PostgreSQL**:数据持久化 +- **SQLAlchemy / SQLModel**:ORM +- **Alembic**:迁移管理 + +### AI 与搜索 +- **Azure OpenAI**:LLM 生成与总结 +- **KB_AGENT**:内部知识库检索 +- **Jina Search / Reader / Rerank**:外部搜索链路 + +### 外部业务系统 +- **Gongdan API**:工单只读 +- **Doc Creator Agent**:文档生成 +- **Daytona Sandbox**:受控代码执行 + +### 交互协议 +- **SSE**:流式输出 +- **REST API**:管理类接口 + +--- + +## 13. 第一阶段开发顺序 + +### 第一步 +先完成: +- FastAPI 基础框架 +- PostgreSQL 接入 +- conversations/messages 表 +- `/api/chat/stream` +- `/api/conversations` + +### 第二步 +接入: +- Azure OpenAI +- KB_AGENT +- 工单系统 + +### 第三步 +接入: +- Jina 外部搜索 +- 来源引用 +- 工具状态流式事件 + +### 第四步 +接入: +- 文档生成任务 +- 附件解析 +- Sandbox + +--- + +## 14. 最终结论 + +这个项目当前最合适的后端建设方式,不是泛泛而谈“做一个 AI 平台后端”,而是严格按功能拆: + +- 用 **FastAPI + SSE** 完成真实聊天流式回复 +- 用 **PostgreSQL** 完成会话和消息持久化 +- 用 **Azure OpenAI** 完成回答生成 +- 用 **KB_AGENT** 完成内部知识检索 +- 用 **Jina Search/Reader/Rerank** 完成外部搜索 +- 用 **Gongdan API** 完成工单只读分析 +- 用 **Doc Creator Agent** 完成正式文档生成 +- 用 **Daytona Sandbox** 完成安全数据处理与代码执行 + +而且整个过程中: +**前端交互不改,只替换数据来源和后端能力。**