# 项目 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": "", "model_name": "qwen3:8b" } ``` - 成功响应: ```json { "code": 0, "msg": "ok", "data": { "session_id": "", "model_name": "qwen3:8b" } } ``` - 说明:`model_name` 必须在 `/models` 返回列表中;否则返回 400 错误。 --- ## 会话与候选生成(提示优化) 提示优化由以下流程实现:根据用户问题或最近消息构造“改写/变异”指令 → 调用 Qwen 批量生成候选 → 通过 Xinference(失败回退到 Ollama embedding)做语义向量 → 聚类去重并选取 Top‑K(默认 5)。 ### 首次生成候选(创建会话) - 方法与路径:`POST /query` - 请求体(新会话): ```json { "query": "我想买苹果" } ``` - 成功响应: ```json { "code": 0, "msg": "ok", "data": { "session_id": "", "round": 0, "candidates": ["...", "..."] } } ``` - 说明: - 新建会话并记录用户原始问题与首轮候选;`round` 会在候选入库后加 1。 ### 继续优化(基于最近消息再生候选) - 方法与路径:`POST /query_from_message` - 请求体: ```json { "session_id": "" } ``` - 成功响应: ```json { "code": 0, "msg": "ok", "data": { "session_id": "", "round": 1, "candidates": ["...", "..."] } } ``` - 说明: - 从会话的最近一条“用户消息”或原始问题作为基线生成新候选。 ### 选择候选并回答 - 方法与路径:`POST /select` - 请求体: ```json { "session_id": "", "choice": "选中的提示词" } ``` - 成功响应: ```json { "code": 0, "msg": "ok", "data": { "prompt": "选中的提示词", "answer": "模型回答内容" } } ``` - 说明: - 将 `choice` 记录为当前会话的 `selected_prompt`,并用该提示词生成回答。 - 会把用户选择与回答追加到 `outputs/user_feedback.jsonl`。 ### 拒绝候选并再生成 - 方法与路径:`POST /reject` - 请求体: ```json { "session_id": "", "candidate": "不合适的候选", "reason": "可选的拒绝理由" } ``` - 成功响应: ```json { "code": 0, "msg": "ok", "data": { "session_id": "", "round": 2, "candidates": ["...", "..."] } } ``` - 说明: - 将被拒绝的候选加入会话历史,生成新一轮候选以“避撞并多样化”。 ### 直接回答 + 候选(可选流程) - 方法与路径:`POST /answer` - 请求体: ```json { "query": "我想买苹果" } ``` - 成功响应: ```json { "code": 0, "msg": "ok", "data": { "session_id": "", "answer": "直接回答内容", "candidates": ["...", "..."] } } ``` - 说明: - 先对用户问题直接回答,再生成提示优化候选。该路由默认使用后端配置的模型。 ### 再次生成(旧接口,含 MAX_ROUNDS) - 方法与路径:`POST /next` - 请求体: ```json { "session_id": "" } ``` - 成功响应(达到最大轮次时): ```json { "code": 0, "msg": "ok", "data": { "final": true, "answer": "最终回答" } } ``` - 成功响应(未达到最大轮次时): ```json { "code": 0, "msg": "ok", "data": { "session_id": "", "round": 1, "candidates": ["...", "..."] } } ``` - 说明: - `MAX_ROUNDS` 当前为 3,仅对该路由有效;前端默认不使用此路由。 --- ## 会话聊天 ### 发送消息并获取回答 - 方法与路径:`POST /message` - 请求体: ```json { "session_id": "", "message": "继续提问或补充说明" } ``` - 成功响应: ```json { "code": 0, "msg": "ok", "data": { "session_id": "", "answer": "模型回答", "history": [ {"role": "user", "content": "..."}, {"role": "assistant", "content": "..."} ] } } ``` - 说明: - 回答会在已选提示词(如无则原始问题)基础上拼接本次消息生成。 --- ## 会话管理 ### 列出会话 - 方法与路径:`GET /sessions` - 成功响应: ```json { "code": 0, "msg": "ok", "data": { "sessions": [ { "session_id": "", "round": 2, "selected_prompt": "...", "original_query": "我想买苹果" } ] } } ``` ### 会话详情 - 方法与路径:`GET /session/{sid}` - 成功响应: ```json { "code": 0, "msg": "ok", "data": { "session_id": "", "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: "|"ollama error: ", "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": "", "choice": "选中的提示词"}' # 拒绝某个候选并再生成 curl -X POST http://127.0.0.1:8010/reject \ -H 'Content-Type: application/json' \ -d '{"session_id": "", "candidate": "不合适的候选", "reason": "太笼统"}' # 基于最近消息继续优化 curl -X POST http://127.0.0.1:8010/query_from_message \ -H 'Content-Type: application/json' \ -d '{"session_id": ""}' # 普通聊天 curl -X POST http://127.0.0.1:8010/message \ -H 'Content-Type: application/json' \ -d '{"session_id": "", "message": "有无更甜的品种?"}' # 获取会话详情 curl http://127.0.0.1:8010/session/ ``` --- ## 备注 - 候选 Top‑K 默认 5,聚类阈值默认 `0.15`。 - 向量优先使用 Xinference(`http://127.0.0.1:9997/...`),失败自动回退到 Ollama embedding(`qwen3-embedding:4b`)。 - 回答默认使用 Ollama 中的 `qwen3:8b`,或通过 `/set_model` 设置当前会话模型。