{"id":34955979,"url":"https://github.com/null-object-0000/newbie-web-llm-api","last_synced_at":"2025-12-26T22:10:59.541Z","repository":{"id":328892412,"uuid":"1116670881","full_name":"null-object-0000/newbie-web-llm-api","owner":"null-object-0000","description":"Turn web-based LLMs (e.g., DeepSeek) into standard OpenAI-compatible APIs. （将网页版 LLM 转换为标准的 OpenAI 兼容 API。）","archived":false,"fork":false,"pushed_at":"2025-12-16T12:10:41.000Z","size":131,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-19T13:23:32.630Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/null-object-0000.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-15T08:03:41.000Z","updated_at":"2025-12-16T12:10:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/null-object-0000/newbie-web-llm-api","commit_stats":null,"previous_names":["null-object-0000/newbie-web-llm-api"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/null-object-0000/newbie-web-llm-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fnewbie-web-llm-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fnewbie-web-llm-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fnewbie-web-llm-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fnewbie-web-llm-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/null-object-0000","download_url":"https://codeload.github.com/null-object-0000/newbie-web-llm-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fnewbie-web-llm-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28062355,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-26T02:00:06.189Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-26T22:10:58.875Z","updated_at":"2025-12-26T22:10:59.525Z","avatar_url":"https://github.com/null-object-0000.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Web-LLM-API\n\n将网页版 LLM（如 DeepSeek）转换为标准的 OpenAI 兼容 API，支持流式响应、多模型管理和对话历史管理。\n\n## ✨ 功能特性\n\n- 🔄 **OpenAI 兼容 API**：完全兼容 OpenAI API 规范，可直接使用 OpenAI SDK\n- 🌊 **流式响应**：支持 Server-Sent Events (SSE) 流式输出，实现打字机效果\n- 💬 **对话管理**：支持新对话和继续对话，自动管理对话上下文\n- 🧠 **深度思考模式**：支持 DeepSeek 的深度思考模式，可区分思考过程和最终回复\n- 📝 **对话历史**：前端自动保存对话历史到浏览器本地存储\n- 🔗 **URL 管理**：自动保存和恢复对话 URL，切换对话时自动导航到对应页面\n- 🎯 **多模型支持**：基于 Provider 架构，易于扩展支持更多 LLM 提供商\n- 🎨 **Web 测试界面**：内置美观的 Web 测试界面，支持对话列表管理\n\n## 🛠️ 技术栈\n\n- **后端**：\n  - Spring Boot 4.0.0\n  - Java 21\n  - Playwright（浏览器自动化）\n  - Server-Sent Events (SSE)\n\n- **前端**：\n  - OpenAI JavaScript SDK 6.10.0\n  - 原生 JavaScript (ES6 Modules)\n  - LocalStorage（本地存储）\n\n## 📦 安装和运行\n\n### 前置要求\n\n- Java 21 或更高版本\n- Maven 3.6+\n- 已登录 DeepSeek 账号（浏览器中）\n\n### 快速开始\n\n1. **克隆项目**\n```bash\ngit clone \u003crepository-url\u003e\ncd newbie-web-llm-api\n```\n\n2. **编译项目**\n```bash\nmvn clean package\n```\n\n3. **运行项目**\n```bash\nmvn spring-boot:run\n```\n\n或者运行编译后的 JAR：\n```bash\njava -jar target/newbie-web-llm-api-0.0.1-SNAPSHOT.jar\n```\n\n4. **访问测试界面**\n```\nhttp://localhost:24753/test.html\n```\n\n### Docker 部署\n\n#### 前置要求\n\n- Docker 20.10+ 和 Docker Compose 2.0+\n- 或仅 Docker（不使用 docker-compose）\n\n#### 使用 Docker Compose（推荐）\n\n1. **构建并启动容器**\n```bash\ndocker-compose up -d\n```\n\n2. **查看日志**\n```bash\ndocker-compose logs -f\n```\n\n3. **停止容器**\n```bash\ndocker-compose down\n```\n\n4. **重新构建镜像**\n```bash\ndocker-compose build --no-cache\ndocker-compose up -d\n```\n\n#### 使用基础镜像加速构建（推荐）\n\n为了加速构建，项目支持使用预构建的基础镜像（包含 Node.js 和 Chromium）。基础镜像只需要构建一次，之后每次构建应用时都可以复用。\n\n**首次构建基础镜像**（只需要执行一次）：\n```bash\n# 构建基础镜像（包含 Node.js 和 Chromium）\ndocker build --target base -t newbie-web-llm-api-base:latest .\n\n# 或者使用 docker-compose\ndocker-compose -f docker-compose.build.yml build base-image\n```\n\n**之后构建应用时，Docker 会自动复用基础镜像**，大大加快构建速度：\n```bash\n# 正常构建，会自动使用已存在的基础镜像\ndocker-compose build\ndocker-compose up -d\n```\n\n**推送到镜像仓库（可选）**：\n如果使用 Docker Hub 或其他镜像仓库，可以推送基础镜像供团队共享：\n```bash\n# 标记镜像\ndocker tag newbie-web-llm-api-base:latest your-registry/newbie-web-llm-api-base:latest\n\n# 推送镜像\ndocker push your-registry/newbie-web-llm-api-base:latest\n\n# 然后在 Dockerfile 中修改 FROM 语句使用远程镜像\n# FROM your-registry/newbie-web-llm-api-base:latest\n```\n\n#### 使用 Docker 命令\n\n1. **构建镜像**\n```bash\ndocker build -t newbie-web-llm-api:latest .\n```\n\n2. **运行容器**\n```bash\ndocker run -d \\\n  --name newbie-web-llm-api \\\n  -p 24753:24753 \\\n  -v $(pwd)/user-data:/app/user-data \\\n  -v $(pwd)/logs:/app/logs \\\n  newbie-web-llm-api:latest\n```\n\n3. **查看日志**\n```bash\ndocker logs -f newbie-web-llm-api\n```\n\n4. **停止容器**\n```bash\ndocker stop newbie-web-llm-api\ndocker rm newbie-web-llm-api\n```\n\n#### Docker 部署注意事项\n\n- **数据持久化**：`user-data` 目录会被挂载到容器中，用于保存浏览器数据和登录会话\n- **首次登录**：首次运行需要在浏览器中登录 DeepSeek 账号，登录状态会保存在 `user-data` 目录\n- **端口映射**：默认端口为 24753，可通过修改 `docker-compose.yml` 或 Docker 命令中的端口映射来更改\n- **资源限制**：建议为容器分配至少 512MB 内存，Playwright 浏览器需要一定资源\n\n## 🚀 使用方法\n\n### Web 界面使用\n\n1. 打开 `http://localhost:24753/test.html`\n2. 选择提供者和模型\n3. 可选择启用\"深度思考\"模式\n4. 输入消息并发送\n5. 在侧边栏管理对话列表：\n   - 点击\"新对话\"创建新对话\n   - 点击对话项切换对话\n   - 点击标题可编辑对话标题\n   - 点击\"删除\"删除对话\n\n### API 使用\n\n#### 1. 获取模型列表\n\n```bash\ncurl http://localhost:24753/v1/models\n```\n\n#### 2. 获取提供者列表\n\n```bash\ncurl http://localhost:24753/v1/providers\n```\n\n#### 3. 发送聊天请求（流式）\n\n```bash\ncurl -X POST http://localhost:24753/v1/chat/completions \\\n  -H \"Content-Type: application/json\" \\\n  -H \"X-New-Conversation: true\" \\\n  -H \"X-Thinking: false\" \\\n  -d '{\n    \"model\": \"deepseek-web\",\n    \"messages\": [\n      {\"role\": \"user\", \"content\": \"你好\"}\n    ],\n    \"stream\": true\n  }'\n```\n\n#### 4. 使用 OpenAI SDK\n\n```javascript\nimport OpenAI from 'openai';\n\nconst openai = new OpenAI({\n  baseURL: 'http://localhost:24753/v1',\n  apiKey: 'not-needed',\n  dangerouslyAllowBrowser: true\n});\n\nconst stream = await openai.chat.completions.create({\n  model: 'deepseek-web',\n  messages: [\n    { role: 'user', content: '你好' }\n  ],\n  stream: true\n});\n\nfor await (const chunk of stream) {\n  console.log(chunk.choices[0]?.delta?.content || '');\n}\n```\n\n## 📡 API 文档\n\n### 基础路径\n\n所有 API 的基础路径为：`/v1`\n\n### 端点\n\n#### 1. 获取模型列表\n\n```\nGET /v1/models\n```\n\n**响应示例**：\n```json\n{\n  \"object\": \"list\",\n  \"data\": [\n    {\n      \"id\": \"deepseek-web\",\n      \"object\": \"model\",\n      \"created\": 1234567890,\n      \"owned_by\": \"deepseek\"\n    }\n  ]\n}\n```\n\n#### 2. 获取提供者列表\n\n```\nGET /v1/providers\n```\n\n**响应示例**：\n```json\n{\n  \"deepseek\": {\n    \"name\": \"deepseek\",\n    \"models\": [\"deepseek-web\"]\n  }\n}\n```\n\n#### 3. 聊天补全\n\n```\nPOST /v1/chat/completions\n```\n\n**请求头**：\n- `X-New-Conversation` (可选): `true` 或 `false`，是否新开对话\n- `X-Thinking` (可选): `true` 或 `false`，是否启用深度思考模式\n- `X-Conversation-URL` (可选): 对话 URL，用于继续特定对话\n\n**请求体**：\n```json\n{\n  \"model\": \"deepseek-web\",\n  \"messages\": [\n    {\"role\": \"user\", \"content\": \"你好\"}\n  ],\n  \"stream\": true\n}\n```\n\n**响应**：Server-Sent Events (SSE) 流\n\n**响应格式**（兼容 OpenAI）：\n```\ndata: {\"id\":\"...\",\"object\":\"chat.completion.chunk\",\"created\":1234567890,\"model\":\"deepseek-web\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"你好\"},\"finish_reason\":null}]}\n\ndata: {\"id\":\"...\",\"object\":\"chat.completion.chunk\",\"created\":1234567890,\"model\":\"deepseek-web\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"！\"},\"finish_reason\":null}]}\n\ndata: [DONE]\n```\n\n**特殊标记**：\n- `__THINKING__`：思考内容标记（深度思考模式）\n- `__REPLACE__`：整体替换标记（用于内容修正）\n- `__URL__`：对话 URL 标记（用于保存对话 URL）\n\n## ⚙️ 配置\n\n### 应用配置\n\n编辑 `src/main/resources/application.properties`：\n\n```properties\n# 服务器端口\nserver.port=24753\n\n# Playwright 浏览器配置\n# 浏览器数据目录（可选，用于保持登录状态）\nplaywright.browser-data-dir=./my-browser-data\n```\n\n### 浏览器数据目录\n\n项目支持使用浏览器数据目录来保持登录状态。首次运行时，Playwright 会自动创建浏览器实例。如果需要保持登录状态：\n\n1. 将已登录的浏览器数据目录复制到项目根目录\n2. 在配置中指定路径（如 `./my-browser-data`）\n\n## 🏗️ 架构设计\n\n### Provider 架构\n\n项目采用 Provider 模式，易于扩展支持更多 LLM 提供商：\n\n```\nLLMProvider (接口)\n    ├── BaseProvider (抽象基类)\n    │   ├── sendSseChunk() - 发送 SSE 数据块\n    │   ├── sendSseReplace() - 发送整体替换消息\n    │   ├── sendThinkingContent() - 发送思考内容\n    │   └── sendConversationId() - 发送对话 ID\n    │\n    └── DeepSeekProvider (DeepSeek 实现)\n        ├── streamChat() - 流式聊天\n        ├── monitorResponseHybrid() - 混合监听响应\n        └── setupSseInterceptor() - SSE 拦截器\n```\n\n### 添加新的 Provider\n\n1. 实现 `LLMProvider` 接口\n2. 继承 `BaseProvider` 基类\n3. 在 `ProviderRegistry` 中注册\n\n示例：\n```java\n@Component\npublic class MyProvider extends BaseProvider implements LLMProvider {\n    // 实现接口方法\n}\n```\n\n## 🔍 工作原理\n\n1. **页面管理**：使用 Playwright 自动化浏览器，管理 DeepSeek 对话页面\n2. **内容提取**：采用混合方式提取 AI 回复：\n   - DOM 解析：实时流式提取内容\n   - SSE 拦截：通过 JavaScript 注入拦截 SSE 数据，用于最终修正\n3. **流式传输**：将提取的内容转换为 OpenAI 兼容的 SSE 格式\n4. **URL 管理**：自动保存和恢复对话 URL，确保切换对话时导航到正确页面\n\n## 📝 注意事项\n\n1. **登录状态**：首次使用需要手动登录 DeepSeek（在浏览器中）\n2. **浏览器资源**：Playwright 会启动浏览器实例，占用一定系统资源\n3. **网络要求**：需要能够访问 `chat.deepseek.com`\n4. **对话 URL**：切换对话时会自动导航到保存的 URL，确保对话上下文正确\n\n## 🐛 故障排除\n\n### 问题：前端无法连接后端\n\n- 检查后端是否正常运行\n- 确认端口号是否正确（默认 24753）\n- 检查浏览器控制台的错误信息\n\n### 问题：无法获取 AI 回复\n\n- 检查是否已登录 DeepSeek\n- 查看后端日志，确认 Playwright 是否正常工作\n- 检查网络连接\n\n### 问题：对话 URL 未保存\n\n- 检查浏览器控制台是否有错误\n- 确认 LocalStorage 是否可用\n- 查看后端日志，确认 URL 是否成功发送\n\n## 📄 许可证\n\n查看 [LICENSE](LICENSE) 文件了解详情。\n\n## 🤝 贡献\n\n欢迎提交 Issue 和 Pull Request！\n\n## 📧 联系方式\n\n如有问题或建议，请通过 Issue 联系。\n\n---\n\n**注意**：本项目仅供学习和研究使用，请遵守相关服务的使用条款。\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnull-object-0000%2Fnewbie-web-llm-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnull-object-0000%2Fnewbie-web-llm-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnull-object-0000%2Fnewbie-web-llm-api/lists"}