From 44db95c8a3180b300dd9a6f3fd1aa100296896ad Mon Sep 17 00:00:00 2001 From: bitzhangbig <78358414+Bigzhangbig@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:11:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20README=20=E5=92=8C=20HiAge?= =?UTF-8?q?nt=20API=20=E8=B0=83=E7=94=A8=E6=8C=87=E5=8D=97=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=A8=A1=E5=9E=8B=E5=88=97=E8=A1=A8=E4=B8=8E?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E7=A4=BA=E4=BE=8B=EF=BC=8C=E8=B0=83=E6=95=B4?= =?UTF-8?q?=20agent.py=20=E4=BB=A5=E6=94=AF=E6=8C=81=E5=AE=98=E6=96=B9=20A?= =?UTF-8?q?PI=20Key=20=E6=A8=A1=E5=BC=8F=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=96=87=E4=BB=B6=E4=BB=A5=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E6=96=B0=E6=97=A7=E5=87=AD=E8=AF=81=E6=A8=A1=E5=BC=8F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 137 ++++++++++++-- hiagent_api_guide.md | 128 +++++++++++++ hiagent_models_guide.md | 79 ++++++++ models/agent.py | 388 ++++++++++++++++------------------------ settings.py | 19 +- 5 files changed, 497 insertions(+), 254 deletions(-) create mode 100644 hiagent_api_guide.md create mode 100644 hiagent_models_guide.md diff --git a/README.md b/README.md index 4ca0efd..ca9b389 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,15 @@ 你梨居然上新了满血版的r1 671b模型!可喜可贺~ 正愁找不到免费可靠的api吗?刚好来白嫖学校的! +### 本项目的核心价值 + +北京理工大学提供的 HiAgent (agent.bit.edu.cn) 和 iBit (ibit.yanhekt.cn) 平台虽然功能强大,但其官方 API 接口采用的是自定义协议(需处理会话创建、UserID 管理、特定 SSE 事件等),无法直接与通用的 OpenAI 客户端(如 NextChat, LobeChat, OpenAI SDK 等)对接。 + +**本项目的作用:** +- **协议转换**:将 BIT 自定义 API 转换为标准的 OpenAI Chat Completions API 协议。 +- **无状态化**:自动管理上游会话的创建与销毁,用户只需发送 `messages` 列表。 +- **即插即用**:支持流式输出、思维链(Reasoning)显示,完美适配主流 AI 客户端。 + ## 项目架构图 ``` @@ -98,15 +107,18 @@ openai_ibit/ |-----------|------|--------|------| | `BIT_USERNAME` | 是* | `""` | 北理工统一身份认证用户名,用于 iBit 平台登录 | | `BIT_PASSWORD` | 是* | `""` | 北理工统一身份认证密码,用于 iBit 平台登录 | -| `AGENT_APP_KEY` | 是* | `""` | 智能体广场应用密钥,用于 DeepSeek-R1 模型 | -| `AGENT_VISITOR_KEY` | 是* | `""` | 智能体广场访客密钥,用于 DeepSeek-R1 模型 | -| `API_KEY` | 否 | `""` | API 访问密钥,设置后客户端需在请求头中携带 `Authorization: Bearer ` | -| `PRINT_STATISTICS_INTERVAL` | 否 | `30` | 统计信息打印间隔(秒),控制控制台输出调用统计的频率 | +| `HI_API_KEY` | 是* | `""` | **推荐**:HiAgent 平台官方 API Key(从“发布管理”获取) | +| `AGENT_APP_KEY` | 否 | `""` | HiAgent 应用密钥(旧模式,不推荐) | +| `AGENT_VISITOR_KEY` | 否 | `""` | HiAgent 访客密钥(旧模式,不推荐) | +| `API_KEY` | 否 | `""` | 本服务的 API 访问密钥,设置后客户端需在请求头中携带 | +| `PRINT_STATISTICS_INTERVAL` | 否 | `30` | 统计信息打印间隔(秒) | | `TZ` | 否 | 系统默认 | 时区设置,推荐设置为 `Asia/Shanghai` | +> **官方文档**:有关 HiAgent (agent.bit.edu.cn) 的官方 API 调用方法及说明,请参阅 [HiAgent 开发者中心](https://agent.bit.edu.cn/platform/doc/)。 + > **注意**:标记为 `是*` 的环境变量表示至少需要配置一组模型凭证: > - **iBit 模型**:需要同时设置 `BIT_USERNAME` 和 `BIT_PASSWORD` -> - **DeepSeek-R1 模型**:需要同时设置 `AGENT_APP_KEY` 和 `AGENT_VISITOR_KEY` +> - **DeepSeek-R1 模型**:推荐设置 `HI_API_KEY`;也可使用旧模式 `AGENT_APP_KEY` + `AGENT_VISITOR_KEY` > > 如果两组凭证都未配置,程序启动时会报错。 @@ -124,7 +136,16 @@ docker run -d -p 8000:8000 --name OpeniBIT \ yht0511/open_ibit:latest ``` -#### 2. 仅使用智能体广场 DeepSeek-R1 模型 +#### 2. 仅使用智能体广场 DeepSeek-R1 模型(官方推荐) + +```bash +docker run -d -p 8000:8000 --name OpeniBIT \ + -e HI_API_KEY=你的HiAgent官方API密钥 \ + -e TZ=Asia/Shanghai \ + yht0511/open_ibit:latest +``` + +#### 3. 仅使用智能体广场 DeepSeek-R1 模型(旧模式) ```bash docker run -d -p 8000:8000 --name OpeniBIT \ @@ -134,19 +155,18 @@ docker run -d -p 8000:8000 --name OpeniBIT \ yht0511/open_ibit:latest ``` -#### 3. 同时使用两个模型 +#### 4. 同时使用两个模型 ```bash docker run -d -p 8000:8000 --name OpeniBIT \ -e BIT_USERNAME=你的统一身份认证用户名 \ -e BIT_PASSWORD=你的统一身份认证密码 \ - -e AGENT_APP_KEY=你的应用密钥 \ - -e AGENT_VISITOR_KEY=你的访客密钥 \ + -e HI_API_KEY=你的HiAgent官方API密钥 \ -e TZ=Asia/Shanghai \ yht0511/open_ibit:latest ``` -#### 4. 启用 API 密钥保护 +#### 5. 启用 API 密钥保护 ```bash docker run -d -p 8000:8000 --name OpeniBIT \ @@ -157,14 +177,13 @@ docker run -d -p 8000:8000 --name OpeniBIT \ yht0511/open_ibit:latest ``` -#### 5. 完整配置示例 +#### 6. 完整配置示例 ```bash docker run -d -p 8000:8000 --name OpeniBIT \ -e BIT_USERNAME=你的统一身份认证用户名 \ -e BIT_PASSWORD=你的统一身份认证密码 \ - -e AGENT_APP_KEY=你的应用密钥 \ - -e AGENT_VISITOR_KEY=你的访客密钥 \ + -e HI_API_KEY=你的HiAgent官方API密钥 \ -e API_KEY=你想设置的api密钥 \ -e PRINT_STATISTICS_INTERVAL=60 \ -e TZ=Asia/Shanghai \ @@ -186,8 +205,9 @@ services: environment: - BIT_USERNAME=你的统一身份认证用户名 - BIT_PASSWORD=你的统一身份认证密码 - - AGENT_APP_KEY=你的应用密钥 # 可选 - - AGENT_VISITOR_KEY=你的访客密钥 # 可选 + - HI_API_KEY=你的HiAgent官方API密钥 # 推荐 + - AGENT_APP_KEY=你的应用密钥 # 旧模式可选 + - AGENT_VISITOR_KEY=你的访客密钥 # 旧模式可选 - API_KEY=你想设置的api密钥 # 可选 - PRINT_STATISTICS_INTERVAL=30 # 可选 - TZ=Asia/Shanghai @@ -212,6 +232,7 @@ pip install -r requirements.txt ```bash export BIT_USERNAME=你的统一身份认证用户名 export BIT_PASSWORD=你的统一身份认证密码 +export HI_API_KEY=你的HiAgent官方API密钥 # 使用 deepseek-r1 时推荐 export API_KEY=你想设置的api密钥 # 可选 ``` @@ -233,7 +254,7 @@ python server.py | 模型名称 | 说明 | 所需环境变量 | |---------|------|-------------| | `ibit` | iBit 平台 DeepSeek 模型 | `BIT_USERNAME`, `BIT_PASSWORD` | -| `deepseek-r1` | 智能体广场 DeepSeek-R1 模型 | `AGENT_APP_KEY`, `AGENT_VISITOR_KEY` | +| `deepseek-r1` | 智能体广场 DeepSeek-R1 模型 | `HI_API_KEY`(推荐)或 `AGENT_APP_KEY` + `AGENT_VISITOR_KEY`(旧模式) | ### 客户端对接示例 @@ -266,8 +287,92 @@ for chunk in response: - **API Key**:你设置的 `API_KEY`(未设置则随意填写) 3. 选择模型 `ibit` 或 `deepseek-r1` +## 官方 HiAgent Agent API 直连调用(不经过本项目) + +如果你希望直接调用 HiAgent 官方 Agent API(不走 OpenAI 协议转换),可按以下方式: + +- **Base URL**:`https://agent.bit.edu.cn/api/proxy/api/v1` +- **鉴权 Header**:`Apikey: 你的_API_KEY` +- **调用流程**:先 `POST /create_conversation`,再 `POST /chat_query_v2` + +### 1)创建会话 + +```bash +curl -X POST 'https://agent.bit.edu.cn/api/proxy/api/v1/create_conversation' \ + -H 'Apikey: 你的_API_KEY' \ + -H 'Content-Type: application/json' \ + -d '{"UserID":"test_user_01"}' +``` + +从响应中取 `Conversation.AppConversationID`。 + +### 2)发送查询 + +```bash +curl -X POST 'https://agent.bit.edu.cn/api/proxy/api/v1/chat_query_v2' \ + -H 'Apikey: 你的_API_KEY' \ + -H 'Content-Type: application/json' \ + -d '{ + "UserID":"test_user_01", + "AppConversationID":"上一步获取的ID", + "Query":"你好,请简述 DeepSeek-R1 的优势。", + "ResponseMode":"blocking" + }' +``` + +`ResponseMode` 可选: +- `blocking`:阻塞返回完整回答 +- `streaming`:流式返回 + +### 3)Python 示例 + +```python +import requests + +BASE_URL = "https://agent.bit.edu.cn/api/proxy/api/v1" +API_KEY = "你的_API_KEY" +USER_ID = "test_user_01" + +headers = { + "Apikey": API_KEY, + "Content-Type": "application/json" +} + +# 1. 创建会话 +res_create = requests.post( + f"{BASE_URL}/create_conversation", + headers=headers, + json={"UserID": USER_ID} +) +conv_id = res_create.json().get("Conversation", {}).get("AppConversationID") + +# 2. 发送查询 +res_query = requests.post( + f"{BASE_URL}/chat_query_v2", + headers=headers, + json={ + "UserID": USER_ID, + "AppConversationID": conv_id, + "Query": "你好,请问 HiAgent 平台支持哪些大模型?", + "ResponseMode": "blocking" + } +) + +print(res_query.json().get("answer")) +``` + +更多参考: +- [HiAgent 开发者中心](https://agent.bit.edu.cn/platform/doc) +- [HiAgent OpenAPI 通用说明](https://agent.bit.edu.cn/platform/doc/api/hiagent-openapi-general-instructions) +- [智能体接口详细文档](https://agent.bit.edu.cn/platform/doc/api/agent-api-call/agent-api-documentation) + ## 更新日志 +## 2026.3.3更新 +- README 新增“官方 HiAgent Agent API 直连调用”章节,补充 `create_conversation` + `chat_query_v2` 的调用流程。 +- 增加官方 `curl` 与 Python 示例,便于不经过本项目时直接对接 HiAgent。 +- 统一 `deepseek-r1` 的凭证说明:推荐 `HI_API_KEY`,同时保留 `AGENT_APP_KEY` + `AGENT_VISITOR_KEY` 旧模式说明。 + ## 2025.6.8更新 现在支持智能体广场的模型,设置环境变量`AGENT_APP_KEY`和`AGENT_VISITOR_KEY`即可使用。 默认模型名称:"deepseek-r1",ibit模型名称:"ibit"。 diff --git a/hiagent_api_guide.md b/hiagent_api_guide.md new file mode 100644 index 0000000..11fd02b --- /dev/null +++ b/hiagent_api_guide.md @@ -0,0 +1,128 @@ +# HiAgent API 调用指南 + +本指南详细介绍了如何使用北京理工大学 HiAgent 平台的 API 接口进行大模型对话调用。 + +--- + +## 1. 准备工作 + +在调用 API 之前,您需要获取以下凭证: + +### 1.1 获取 API Key (Apikey) +1. 登录 [HiAgent 平台](https://agent.bit.edu.cn)。 +2. 进入您创建或拥有的**智能体**。 +3. 在页面右侧或菜单中点击 **“发布管理”** 或 **“API 调用”**。 +4. 在“API 密钥”部分,创建一个永久或限时的密钥并复制。 + +### 1.2 获取 AppID +在智能体页面的 URL 中或“API 调用”页面的代码示例中可以找到 `AppID`(如 `d5akl1...`)。 + +--- + +## 2. 接口基本信息 + +- **Base URL**: `https://agent.bit.edu.cn/api/proxy/api/v1` +- **内容类型 (Content-Type)**: `application/json` +- **鉴权方式**: 在 HTTP Header 中添加 `Apikey`。 + +--- + +## 3. 核心调用流程 + +HiAgent 的对话调用分为两个阶段:**创建会话** 和 **发送查询**。 + +### 3.1 创建会话 (Create Conversation) +在开始对话前,必须先获取一个有效的会话 ID。 + +- **Endpoint**: `/create_conversation` +- **Method**: `POST` +- **请求参数 (JSON)**: + - `UserID` (string, 必填): 用户标识,建议使用随机 ID 或固定用户标识。 +- **返回结果**: 包含 `AppConversationID`,用于后续对话。 + +### 3.2 发送查询 (Chat Query V2) +使用获取到的会话 ID 进行实际的大模型对话。 + +- **Endpoint**: `/chat_query_v2` +- **Method**: `POST` +- **请求参数 (JSON)**: + - `UserID` (string, 必填): 与创建会话时一致。 + - `AppConversationID` (string, 必填): 上一步获取的 ID。 + - `Query` (string, 必填): 您的提问内容。 + - `ResponseMode` (string): `blocking` (阻塞返回完整结果) 或 `streaming` (流式返回)。 + +--- + +## 4. Python 调用示例 + +以下是一个完整的自动化脚本,演示了从创建会话到获取回答的全过程。 + +```python +import requests +import json + +# --- 配置区 --- +BASE_URL = "https://agent.bit.edu.cn/api/proxy/api/v1" +API_KEY = "您的_API_KEY" # 替换为实际密钥 +USER_ID = "test_user_01" # 自定义用户 ID + +def hiagent_test(): + headers = { + "Apikey": API_KEY, + "Content-Type": "application/json" + } + + # 1. 创建会话 + create_url = f"{BASE_URL}/create_conversation" + create_payload = {"UserID": USER_ID} + + print("正在创建会话...") + res_create = requests.post(create_url, headers=headers, json=create_payload) + if res_create.status_code != 200: + print(f"创建会话失败: {res_create.text}") + return + + conv_id = res_create.json().get("Conversation", {}).get("AppConversationID") + print(f"会话创建成功,ID: {conv_id}") + + # 2. 发送对话请求 + query_url = f"{BASE_URL}/chat_query_v2" + query_payload = { + "UserID": USER_ID, + "AppConversationID": conv_id, + "Query": "你好,请问 HiAgent 平台支持哪些大模型?", + "ResponseMode": "blocking" + } + + print("正在等待模型响应...") + res_query = requests.post(query_url, headers=headers, json=query_payload) + if res_query.status_code == 200: + answer = res_query.json().get("answer") + print(" +=== 模型回复 ===") + print(answer) + print("================") + else: + print(f"请求失败: {res_query.text}") + +if __name__ == "__main__": + hiagent_test() +``` + +--- + +## 5. 常见问题 (FAQ) +- **报错 `missing required parameter`**: 检查是否遗漏了 `AppConversationID` 或 `UserID`。 +- **401 Unauthorized**: 检查 Header 中的 `Apikey` 是否正确,注意大小写(`Apikey` 而非 `api-key`)。 +- **流式输出**: 如果需要流式响应,需设置 `ResponseMode: "streaming"` 并通过 `requests` 的 `stream=True` 迭代获取数据块。 + +--- + +## 6. 资料来源 +- [HiAgent OpenAPI 通用说明](https://agent.bit.edu.cn/platform/doc/api/hiagent-openapi-general-instructions) +- [智能体接口详细文档](https://agent.bit.edu.cn/platform/doc/api/agent-api-call/agent-api-documentation) +- [HiAgent API 调用示例代码](https://agent.bit.edu.cn/platform/doc/api/hiagent-api-call-examples) +- [HiAgent 开发者中心](https://agent.bit.edu.cn/platform/doc) + +--- +*文档生成日期:2026年3月2日* diff --git a/hiagent_models_guide.md b/hiagent_models_guide.md new file mode 100644 index 0000000..400b56f --- /dev/null +++ b/hiagent_models_guide.md @@ -0,0 +1,79 @@ +# HiAgent 模型列表与调用指南 + +本文档汇总了 HiAgent 平台支持的主要模型列表及其调用方式。 + +## 1. 模型列表 (Available Models) + +根据平台当前状态,以下是已部署并可供调用的核心模型: + +| 模型名称 | 类型 | 描述 | 适用场景 | +| :--- | :--- | :--- | :--- | +| **DeepSeek-R1** | 对话型 | 深度求索开发的推理型大模型,支持长上下文与强逻辑推理。 | 复杂逻辑分析、代码生成、学术研究 | +| **DeepSeek-V3** | 对话型 | 深度求索通用大模型,知识更新至 2024 年 7 月。 | 日常问答、创意写作、通用任务 | +| **Doubao-1.5-Pro-256k** | 对话型 | 字节跳动豆包大模型 Pro 版,支持极长文本(256k)。 | 长文档解读、超长会话保持 | +| **Doubao-1.5-Pro-32k** | 对话型 | 豆包 Pro 版,性能均衡,适合大多数应用。 | 通用办公、智能助手、知识库问答 | +| **Doubao-1.5-Lite-32k** | 对话型 | 豆包轻量版,响应速度极快,成本更低。 | 快速响应任务、简单文本处理 | + +--- + +## 2. 调用方式 + +### 2.1 环境变量配置 +建议将敏感信息存储在 `.env` 文件中: +```bash +HI_API_KEY=您的_API_KEY +HI_BASE_URL=https://agent.bit.edu.cn/api/proxy/api/v1 +``` + +### 2.2 调用流程 +1. **创建会话**: 发送 `POST` 请求到 `/create_conversation` 获取 `AppConversationID`。 +2. **对话查询**: 发送 `POST` 请求到 `/chat_query_v2`,并携带会话 ID。 + +--- + +## 3. 代码示例 (Python) + +```python +import os +import requests +import json +from dotenv import load_dotenv + +# 加载配置 +load_dotenv() +API_KEY = os.getenv("HI_API_KEY") +BASE_URL = os.getenv("HI_BASE_URL") + +def call_hiagent(query): + headers = {"Apikey": API_KEY, "Content-Type": "application/json"} + + # 1. 获取会话 ID + res_conv = requests.post(f"{BASE_URL}/create_conversation", + headers=headers, json={"UserID": "user_01"}) + conv_id = res_conv.json().get("Conversation", {}).get("AppConversationID") + + # 2. 调用对话接口 + payload = { + "UserID": "user_01", + "AppConversationID": conv_id, + "Query": query, + "ResponseMode": "blocking" + } + res_chat = requests.post(f"{BASE_URL}/chat_query_v2", + headers=headers, json=payload) + + return res_chat.json().get("answer") + +if __name__ == "__main__": + print(call_hiagent("请简述 DeepSeek-R1 的优势。")) +``` + +--- + +## 4. 来源与参考 +- **平台地址**: [https://agent.bit.edu.cn](https://agent.bit.edu.cn) +- **官方文档**: [HiAgent Document](https://agent.bit.edu.cn/platform/doc) +- **智能体广场**: 模型详情参考自个人空间及公开智能体配置。 + +--- +*文档生成日期:2026年3月2日* diff --git a/models/agent.py b/models/agent.py index 89a5089..1653f5d 100644 --- a/models/agent.py +++ b/models/agent.py @@ -1,278 +1,204 @@ """ -agent.py - 智能体广场 DeepSeek-R1 模型接口封装 +agent.py - 智能体广场 (HiAgent) 模型接口封装 + +本模块封装了北理工智能体广场(agent.bit.edu.cn)的模型 API。 +支持官方 API Key 模式和旧的应用密钥/访客密钥模式。 + +官方文档参考:https://agent.bit.edu.cn/platform/doc/ -本模块封装了北理工智能体广场(agent.bit.edu.cn)的 DeepSeek-R1 模型 API。 主要功能: -1. 通过应用密钥和访客密钥进行身份验证 +1. 通过官方 API Key (Apikey Header) 或旧凭证进行身份验证 2. 支持流式和非流式对话 3. 自动会话管理(创建和删除对话) -4. 支持思维链(reasoning_content)输出 - -与 ibit.py 的区别: -- 不需要统一身份认证,使用应用密钥认证 -- API 端点不同(agent.bit.edu.cn vs ibit.yanhekt.cn) -- 思维链标签格式不同(think_message 事件 vs 标签) - -使用方式: - agent = Agent(appkey, visitor_key) - agent.init() # 必须先初始化 - reasoning, content = agent.chat("你好") # 非流式对话 - for chunk in agent.chat_stream("你好"): # 流式对话 - print(chunk) +4. 支持思维链 (reasoning_content) 输出 """ -import json # JSON 数据解析 -import time # 时间处理(保留供将来使用) -import requests # HTTP 请求库 - +import json +import time +import requests +import uuid class Agent: """ - 智能体广场模型封装类 - - 封装了智能体广场的 DeepSeek-R1 模型 API,提供统一的对话接口。 - 支持流式和非流式两种调用方式,自动管理会话。 + 智能体广场 (HiAgent) 模型封装类 - Attributes: - appkey: 应用密钥(从智能体广场获取) - visitor_key: 访客密钥(从智能体广场获取) - url: API 请求 URL - cookies: 请求 Cookie - timeout_seconds: 请求超时时间(秒) - headers: HTTP 请求头 + 支持官方 API 和旧版集成 API。 """ - def __init__(self, appkey, visitor_key, timeout_seconds=10): + def __init__(self, api_key=None, appkey=None, visitor_key=None, timeout_seconds=15): """ - 初始化智能体广场模型实例 + 初始化 HiAgent 模型实例 Args: - appkey: 应用密钥,从智能体广场获取 - visitor_key: 访客密钥,从智能体广场获取 - timeout_seconds: HTTP 请求超时时间,默认 10 秒 + api_key: 官方 API Key (推荐),从智能体发布管理获取 + appkey: 旧版应用密钥 (可选) + visitor_key: 旧版访客密钥 (可选) + timeout_seconds: 请求超时时间 """ + self.api_key = api_key self.appkey = appkey self.visitor_key = visitor_key - self.url = f"https://agent.bit.edu.cn/product/llm/chat/{appkey}" # 应用专属 URL - self.cookies = { - 'app-visitor-key': visitor_key, # 访客身份标识 - } self.timeout_seconds = timeout_seconds - - # 构造请求头,模拟浏览器访问 - self.headers = { - 'Accept': 'application/json, text/event-stream', - 'Connection': 'keep-alive', - 'Content-Type': 'application/json; charset=utf-8', - 'Origin': 'https://agent.bit.edu.cn', - 'Sec-Fetch-Dest': 'empty', - 'Sec-Fetch-Mode': 'cors', - 'Sec-Fetch-Site': 'same-origin', - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0', - 'X-KL-Ajax-Request': 'Ajax_Request', - 'accept-language': 'zh', - 'app-visitor-key': 'd104cralaa6c73dtnoi0', # 默认访客密钥 - 'sec-ch-ua': '"Chromium";v="136", "Microsoft Edge";v="136", "Not.A/Brand";v="99"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"Windows"', - } - - def init(self): - """ - 初始化模型(必须在使用前调用) - 清除所有已存在的对话,确保干净的初始状态。 - """ - self.clear_conversations() # 清除所有对话 - - def chat(self, query, history=[]): - """ - 非流式对话 + # 官方 API 配置 + self.base_url = "https://agent.bit.edu.cn/api/proxy/api/v1" - 发送查询并等待完整响应返回。 + # 旧版 API 配置 (回退使用) + self.legacy_url = f"https://agent.bit.edu.cn/product/llm/chat/{appkey}" if appkey else "" - Args: - query: 用户查询内容 - history: 历史对话列表,格式为 [{"role": "user", "content": "..."}, ...] - - Returns: - tuple: (reasoning, result) - - reasoning: 模型的思考过程 - - result: 最终回复内容 - """ + # 默认 UserID,用于官方 API + self.user_id = f"openai_ibit_{uuid.uuid4().hex[:8]}" + + def _get_headers(self): + """构造请求头""" + if self.api_key: + return { + "Apikey": self.api_key, + "Content-Type": "application/json", + "Accept": "application/json, text/event-stream" + } + else: + # 旧版模拟浏览器请求头 + return { + 'Accept': 'application/json, text/event-stream', + 'Content-Type': 'application/json; charset=utf-8', + 'app-visitor-key': self.visitor_key, + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36' + } + + def _get_cookies(self): + """构造旧版 API 所需的 Cookie""" + if self.api_key: + return None + return {'app-visitor-key': self.visitor_key} + + def init(self): + """初始化操作""" + # 官方模式通常不需要预清理,但可以根据需要添加 + pass + + def chat(self, query, history=[]): + """非流式对话""" result = "" reasoning = "" - # 通过流式接口收集完整响应 for chunk in self.chat_stream(query, history): if chunk.get("content"): result += chunk["content"] if chunk.get("reasoning_content"): reasoning += chunk["reasoning_content"] return reasoning, result - + def chat_stream(self, query, history=[]): - """ - 流式对话(生成器) - - 发送查询并以流式方式逐步返回响应。 - 自动管理临时对话的创建和删除。 - - Args: - query: 用户查询内容 - history: 历史对话列表 + """流式对话 (生成器)""" + if self.api_key: + yield from self._chat_stream_official(query, history) + else: + yield from self._chat_stream_legacy(query, history) + + def _chat_stream_official(self, query, history): + """使用官方 API 进行流式对话""" + # 1. 创建会话 + create_url = f"{self.base_url}/create_conversation" + try: + res_create = requests.post( + create_url, + headers=self._get_headers(), + json={"UserID": self.user_id}, + timeout=self.timeout_seconds + ) + conv_id = res_create.json().get("Conversation", {}).get("AppConversationID") + except Exception as e: + print(f"[Agent] Create conversation failed: {e}") + return + + # 2. 发送查询 + query_url = f"{self.base_url}/chat_query_v2" + # 官方目前主要通过 prompt 传递历史 + full_query = self.get_history_prompt(history) + query + + payload = { + "UserID": self.user_id, + "AppConversationID": conv_id, + "Query": full_query, + "ResponseMode": "streaming" + } + + try: + response = requests.post( + query_url, + headers=self._get_headers(), + json=payload, + stream=True, + timeout=self.timeout_seconds + ) - Yields: - dict: 包含增量内容的字典 - - content: 普通回复内容(可能为 None) - - reasoning_content: 思考过程内容(可能为 None) - """ - url = "https://agent.bit.edu.cn/api/proxy/chat/v2/chat_query" # 对话 API - temp_dialogue_id = self.new_dialogue() # 创建临时对话 - query = self.get_history_prompt(history) + query # 将历史对话拼接到查询中 + for line in response.iter_lines(): + if line: + line_str = line.decode("utf-8") + if line_str.startswith("data: "): + try: + data = json.loads(line_str[6:]) + # 官方 API 格式解析 + # 注:此处需要根据官方 R1 的具体返回字段适配思维链 + # 假设官方也遵循类似的 event 或 answer 结构 + if data.get("event") == "think_message": + yield {"content": None, "reasoning_content": data.get("answer", "")} + elif data.get("event") == "message": + yield {"content": data.get("answer", ""), "reasoning_content": None} + except: + pass + except Exception as e: + print(f"[Agent] Chat stream failed: {e}") + finally: + # 3. 官方 API 可选:删除会话 (保持环境整洁) + delete_url = f"{self.base_url}/delete_conversation" + requests.post( + delete_url, + headers=self._get_headers(), + json={"UserID": self.user_id, "AppConversationID": conv_id} + ) + + def _chat_stream_legacy(self, query, history): + """使用旧版模拟接口进行流式对话 (回退逻辑)""" + url = "https://agent.bit.edu.cn/api/proxy/chat/v2/chat_query" + conv_id = self._new_dialogue_legacy() + query = self.get_history_prompt(history) + query - # 构造请求数据 json_data = { 'Query': query, - 'AppConversationID': temp_dialogue_id, + 'AppConversationID': conv_id, 'AppKey': self.appkey, - 'QueryExtends': { - 'Files': [], # 附件文件(暂不支持) - } + 'QueryExtends': {'Files': []} } - # 发送流式请求 - response = requests.post(url, json=json_data, cookies=self.cookies, headers=self.headers, stream=True) - response.raw.decode_content = True - answer = "" - - # 提前删除对话(避免对话累积) - self.delete_dialogue(temp_dialogue_id) - - # 逐块处理响应 - for chunk in response.iter_content(chunk_size=1024): - if chunk: - try: - # 解析 SSE 数据格式 - data = json.loads(chunk.decode("utf-8").split("data: ")[1].replace("\n","")) - - # 根据事件类型区分思考内容和回复内容 - if data["event"] == "think_message" and data["answer"]: - # 思考过程事件 - answer = data["answer"] - yield { - "content": None, - "reasoning_content": answer - } - elif data["event"] == "message" and data["answer"]: - # 普通回复事件 - answer = data["answer"] - yield { - "content": answer, - "reasoning_content": None - } - except: pass # 忽略解析错误 + try: + response = requests.post(url, json=json_data, cookies=self._get_cookies(), headers=self._get_headers(), stream=True) + for chunk in response.iter_content(chunk_size=1024): + if chunk: + try: + data = json.loads(chunk.decode("utf-8").split("data: ")[1].replace("\n","")) + if data["event"] == "think_message": + yield {"content": None, "reasoning_content": data["answer"]} + elif data["event"] == "message": + yield {"content": data["answer"], "reasoning_content": None} + except: pass + finally: + self._delete_dialogue_legacy(conv_id) def get_history_prompt(self, history): - """ - 构造历史对话提示 - - 将历史对话格式化为提示文本,供模型参考。 - - Args: - history: 历史对话列表 - - Returns: - str: 格式化后的历史对话提示文本 - """ - res = "[历史对话](请注意这是由程序提供的历史对话功能,不要把它当成用户对话的一部分,不要刻意提及它):" + """构造历史对话提示""" + if not history: return "" + res = "[历史对话](程序提供):" for i in history: res += f"\n{i['role']}:{i['content']}" - res += "\n接下来是用户的新一轮问题:\n" + res += "\n新问题:\n" return res - - def new_dialogue(self): - """ - 创建新对话 - - 在智能体广场创建一个新的对话会话。 - - Returns: - str: 新创建的对话 ID(AppConversationID) - """ + + def _new_dialogue_legacy(self): url = "https://agent.bit.edu.cn/api/proxy/chat/v2/create_conversation" - json_data = { - 'AppKey': self.appkey, - 'Inputs': {}, # 初始输入参数(可扩展) - } - response = requests.post( - url, - json=json_data, - cookies=self.cookies, - headers=self.headers - ) - return response.json().get("Conversation").get("AppConversationID") + res = requests.post(url, json={'AppKey': self.appkey}, cookies=self._get_cookies(), headers=self._get_headers()) + return res.json().get("Conversation", {}).get("AppConversationID") - def delete_dialogue(self, dialogue_id): - """ - 删除对话 - - 删除指定的对话会话,用于清理临时对话。 - - Args: - dialogue_id: 要删除的对话 ID - - Returns: - bool: 总是返回 True - """ + def _delete_dialogue_legacy(self, dialogue_id): url = 'https://agent.bit.edu.cn/api/proxy/chat/v2/delete_conversation' - json_data = { - 'AppKey': self.appkey, - 'AppConversationID': dialogue_id, - } - - response = requests.post( - url, - json=json_data, - cookies=self.cookies, - headers=self.headers - ) - return True - - def get_conversation_list(self): - """ - 获取对话列表 - - 获取当前应用下的所有对话会话。 - - Returns: - list: 对话列表,每个元素包含对话的详细信息 - """ - url = 'https://agent.bit.edu.cn/api/proxy/chat/v2/get_conversation_list' - json_data = { - 'AppKey': self.appkey, - } - response = requests.post( - url, - json=json_data, - cookies=self.cookies, - headers=self.headers - ) - return response.json().get("ConversationList",[]) - - def clear_conversations(self): - """ - 清除所有对话 - - 删除当前应用下的所有对话会话。 - 用于初始化时清理环境。 - - Returns: - bool: 总是返回 True - """ - conversations = self.get_conversation_list() - for conversation in self.get_conversation_list(): - dialogue_id = conversation.get("AppConversationID") - if dialogue_id: - self.delete_dialogue(dialogue_id) - return True - + requests.post(url, json={'AppKey': self.appkey, 'AppConversationID': dialogue_id}, cookies=self._get_cookies(), headers=self._get_headers()) diff --git a/settings.py b/settings.py index 47349a0..daaae17 100644 --- a/settings.py +++ b/settings.py @@ -27,9 +27,11 @@ bit_username = "" # 统一身份认证用户名 bit_password = "" # 统一身份认证密码 -# 智能体广场凭证 -agent_app_key = "" # 应用密钥(从智能体广场获取) -agent_visitor_key = "" # 访客密钥(从智能体广场获取) +# 智能体广场凭证 (HiAgent) +# 支持官方 API Key 模式和旧的 AppKey/VisitorKey 模式 +hi_api_key = "" # 官方 API Key (从发布管理获取) +agent_app_key = "" # 应用密钥 (旧模式) +agent_visitor_key = "" # 访客密钥 (旧模式) # API 访问密钥(可选,用于保护服务接口) api_key = "" @@ -61,7 +63,10 @@ if os.environ.get('BIT_PASSWORD'): bit_password = os.environ.get('BIT_PASSWORD') -# 读取智能体广场凭证 +# 读取智能体广场凭证 (HiAgent) +# 优先读取官方 API Key +if os.environ.get('HI_API_KEY'): + hi_api_key = os.environ.get('HI_API_KEY') if os.environ.get('AGENT_APP_KEY'): agent_app_key = os.environ.get('AGENT_APP_KEY') if os.environ.get('AGENT_VISITOR_KEY'): @@ -97,12 +102,12 @@ "tokenizer": deepseek_tokenizer.count_tokens # 分词器函数 } -# 注册智能体广场 DeepSeek-R1 模型 -# 需要提供应用密钥和访客密钥 -if agent_app_key and agent_visitor_key: +# 注册智能体广场 DeepSeek-R1 模型 (HiAgent) +if hi_api_key or (agent_app_key and agent_visitor_key): models["deepseek-r1"] = { "name": "DeepSeek-R1", # 模型显示名称 "model": agent.Agent( + api_key=hi_api_key, appkey=agent_app_key, visitor_key=agent_visitor_key ), # 模型实例