Files
opro_demo/API.md

361 lines
7.9 KiB
Markdown
Raw Normal View History

2025-12-05 07:11:25 +00:00
# 项目 API 文档
本项目提供用于 OPRO 风格提示优化与会话交互的 REST API。所有接口均使用 `application/json`,无鉴权。示例以默认本地启动地址为例:`http://127.0.0.1:8010`
- 基础路径:`/`
- 前端页面:`/ui/`(三栏界面),`/ui/react`React 示例页面),`/ui/offline`(离线备份页面)
- 内容类型:`Content-Type: application/json`
### 统一响应格式
所有 JSON 接口统一返回以下包装结构:
```json
{
"code": 0,
"msg": "ok",
"data": {}
}
```
- 成功:`code` 固定为 `0``msg` 为简要说明(默认 `ok`),业务数据在 `data` 字段中。
- 失败HTTP 状态码保持原值(如 400/404/500`code` 同步为该状态码,`msg` 为错误信息,`data``null`
错误处理位于 `_qwen_xinference_demo/api.py:23-31`(异常处理器),成功响应包装器为 `_qwen_xinference_demo/api.py:21-22``ok()`
---
## 健康检查
- 方法与路径:`GET /health`
- 作用:服务可用性检查
- 响应示例:
```json
{
"code": 0,
"msg": "ok",
"data": { "status": "ok" }
}
```
---
## 模型管理
### 获取可用模型
- 方法与路径:`GET /models`
- 作用:列出可用于推理的 Ollama 模型(过滤掉 embedding/reranker
- 响应示例:
```json
{
"code": 0,
"msg": "ok",
"data": {
"models": ["qwen3:8b", "qwen3:14b", "qwen3:32b"]
}
}
```
### 设置当前会话模型
- 方法与路径:`POST /set_model`
- 请求体:
```json
{
"session_id": "<SID>",
"model_name": "qwen3:8b"
}
```
- 成功响应:
```json
{
"code": 0,
"msg": "ok",
"data": {
"session_id": "<SID>",
"model_name": "qwen3:8b"
}
}
```
- 说明:`model_name` 必须在 `/models` 返回列表中;否则返回 400 错误。
---
## 会话与候选生成(提示优化)
提示优化由以下流程实现:根据用户问题或最近消息构造“改写/变异”指令 → 调用 Qwen 批量生成候选 → 通过 Xinference失败回退到 Ollama embedding做语义向量 → 聚类去重并选取 TopK默认 5
### 首次生成候选(创建会话)
- 方法与路径:`POST /query`
- 请求体(新会话):
```json
{ "query": "我想买苹果" }
```
- 成功响应:
```json
{
"code": 0,
"msg": "ok",
"data": {
"session_id": "<SID>",
"round": 0,
"candidates": ["...", "..."]
}
}
```
- 说明:
- 新建会话并记录用户原始问题与首轮候选;`round` 会在候选入库后加 1。
### 继续优化(基于最近消息再生候选)
- 方法与路径:`POST /query_from_message`
- 请求体:
```json
{ "session_id": "<SID>" }
```
- 成功响应:
```json
{
"code": 0,
"msg": "ok",
"data": {
"session_id": "<SID>",
"round": 1,
"candidates": ["...", "..."]
}
}
```
- 说明:
- 从会话的最近一条“用户消息”或原始问题作为基线生成新候选。
### 选择候选并回答
- 方法与路径:`POST /select`
- 请求体:
```json
{
"session_id": "<SID>",
"choice": "选中的提示词"
}
```
- 成功响应:
```json
{
"code": 0,
"msg": "ok",
"data": {
"prompt": "选中的提示词",
"answer": "模型回答内容"
}
}
```
- 说明:
-`choice` 记录为当前会话的 `selected_prompt`,并用该提示词生成回答。
- 会把用户选择与回答追加到 `outputs/user_feedback.jsonl`
### 拒绝候选并再生成
- 方法与路径:`POST /reject`
- 请求体:
```json
{
"session_id": "<SID>",
"candidate": "不合适的候选",
"reason": "可选的拒绝理由"
}
```
- 成功响应:
```json
{
"code": 0,
"msg": "ok",
"data": {
"session_id": "<SID>",
"round": 2,
"candidates": ["...", "..."]
}
}
```
- 说明:
- 将被拒绝的候选加入会话历史,生成新一轮候选以“避撞并多样化”。
### 直接回答 + 候选(可选流程)
- 方法与路径:`POST /answer`
- 请求体:
```json
{ "query": "我想买苹果" }
```
- 成功响应:
```json
{
"code": 0,
"msg": "ok",
"data": {
"session_id": "<SID>",
"answer": "直接回答内容",
"candidates": ["...", "..."]
}
}
```
- 说明:
- 先对用户问题直接回答,再生成提示优化候选。该路由默认使用后端配置的模型。
### 再次生成(旧接口,含 MAX_ROUNDS
- 方法与路径:`POST /next`
- 请求体:
```json
{ "session_id": "<SID>" }
```
- 成功响应(达到最大轮次时):
```json
{
"code": 0,
"msg": "ok",
"data": { "final": true, "answer": "最终回答" }
}
```
- 成功响应(未达到最大轮次时):
```json
{
"code": 0,
"msg": "ok",
"data": { "session_id": "<SID>", "round": 1, "candidates": ["...", "..."] }
}
```
- 说明:
- `MAX_ROUNDS` 当前为 3仅对该路由有效前端默认不使用此路由。
---
## 会话聊天
### 发送消息并获取回答
- 方法与路径:`POST /message`
- 请求体:
```json
{
"session_id": "<SID>",
"message": "继续提问或补充说明"
}
```
- 成功响应:
```json
{
"code": 0,
"msg": "ok",
"data": {
"session_id": "<SID>",
"answer": "模型回答",
"history": [
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."}
]
}
}
```
- 说明:
- 回答会在已选提示词(如无则原始问题)基础上拼接本次消息生成。
---
## 会话管理
### 列出会话
- 方法与路径:`GET /sessions`
- 成功响应:
```json
{
"code": 0,
"msg": "ok",
"data": {
"sessions": [
{
"session_id": "<SID>",
"round": 2,
"selected_prompt": "...",
"original_query": "我想买苹果"
}
]
}
}
```
### 会话详情
- 方法与路径:`GET /session/{sid}`
- 成功响应:
```json
{
"code": 0,
"msg": "ok",
"data": {
"session_id": "<SID>",
"round": 2,
"original_query": "我想买苹果",
"selected_prompt": "...",
"candidates": ["...", "..."],
"user_feedback": [{"round": 1, "choice": "..."}],
"rejected": ["...", "..."],
"history": [
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."}
]
}
}
```
---
## 静态页面与重定向
- `GET /` → 重定向到 `/ui/`
- `GET /ui/` → 前端三栏页面(由后端挂载静态目录 `frontend`
- `GET /ui/react` → React 版本示例页面
- `GET /ui/offline` → 离线页面(无 CDN 依赖)
- `GET /react` → 与 `/ui/react` 等价的页面入口
---
## 错误码与通用返回
- 错误包装:
- HTTP 404`{"code": 404, "msg": "session not found", "data": null}`
- HTTP 400`{"code": 400, "msg": "model not available: <name>"|"ollama error: <message>", "data": null}`
- HTTP 500`{"code": 500, "msg": "internal error", "data": null}`
---
## 调用示例curl
```bash
# 创建会话并生成首轮候选
curl -X POST http://127.0.0.1:8010/query \
-H 'Content-Type: application/json' \
-d '{"query": "我想买苹果"}'
# 选择某个候选并回答
curl -X POST http://127.0.0.1:8010/select \
-H 'Content-Type: application/json' \
-d '{"session_id": "<SID>", "choice": "选中的提示词"}'
# 拒绝某个候选并再生成
curl -X POST http://127.0.0.1:8010/reject \
-H 'Content-Type: application/json' \
-d '{"session_id": "<SID>", "candidate": "不合适的候选", "reason": "太笼统"}'
# 基于最近消息继续优化
curl -X POST http://127.0.0.1:8010/query_from_message \
-H 'Content-Type: application/json' \
-d '{"session_id": "<SID>"}'
# 普通聊天
curl -X POST http://127.0.0.1:8010/message \
-H 'Content-Type: application/json' \
-d '{"session_id": "<SID>", "message": "有无更甜的品种?"}'
# 获取会话详情
curl http://127.0.0.1:8010/session/<SID>
```
---
## 备注
- 候选 TopK 默认 5聚类阈值默认 `0.15`
- 向量优先使用 Xinference`http://127.0.0.1:9997/...`),失败自动回退到 Ollama embedding`qwen3-embedding:4b`)。
- 回答默认使用 Ollama 中的 `qwen3:8b`,或通过 `/set_model` 设置当前会话模型。