Commit 0e66a315079907ef596d2e17f7b06b9238287b6b

Authored by tangwang
1 parent 2e3670ab

docs

docs/ARCHITECTURE_EVALUATION.md deleted
@@ -1,202 +0,0 @@ @@ -1,202 +0,0 @@
1 -# 能力提供者架构评估与统一改造方案  
2 -  
3 -> **已落地**。实现见 `providers/`、`config/services_config.py`。使用与扩展见 `docs/PROVIDER_ARCHITECTURE.md`。  
4 -  
5 ----  
6 -  
7 -## 一、当前状态梳理  
8 -  
9 -### 1.1 两种“可插拔”的辨析  
10 -  
11 -| 模式 | 含义 | 当前是否存在 |  
12 -|------|------|--------------|  
13 -| **提供者内部可选择** | 某个 provider(如翻译)内部封装多种实现(如 qwen/deepl),内部切换 | 部分存在:`direct` 的 Translator 内部可选 qwen/deepl |  
14 -| **平台级多 provider** | 平台定义能力抽象,多个独立 provider 注册,通过配置切换 | 存在:translation 的 direct/http,rerank 的 http/vllm |  
15 -  
16 -**结论**:当前是 **平台级可插拔** 为主,但实现不统一、配置分散,造成混乱。  
17 -  
18 -### 1.2 三种能力的实现对比  
19 -  
20 -| 能力 | 抽象层 | Provider 实现 | 配置来源 | 问题 |  
21 -|------|--------|---------------|----------|------|  
22 -| **翻译** | `create_translation_client()` | direct, http | `query_config` + `services.translation` | 双重配置源,优先级链复杂 |  
23 -| **重排** | `create_rerank_client()` | http, vllm(reserved) | `rerank` 块 + `services.rerank` | 同上 |  
24 -| **向量化** | 无 | 仅 HTTP 直连 | `service_endpoints` 读 `services.embedding` | 无 provider 抽象,只有 endpoint 解析 |  
25 -  
26 -### 1.3 配置分散问题  
27 -  
28 -```  
29 -config.yaml 中:  
30 -├── query_config.translation_provider  
31 -├── query_config.translation_providers  
32 -├── query_config.translation_service_url  
33 -├── rerank.rerank_provider  
34 -├── rerank.rerank_providers  
35 -├── rerank.service_url  
36 -└── services.{translation,embedding,rerank} # 又一整套  
37 -```  
38 -  
39 -config_loader 用冗长的优先级链合并(env > query_config > services > defaults),维护成本高。  
40 -  
41 ----  
42 -  
43 -## 二、统一架构原则  
44 -  
45 -### 2.1 设计目标  
46 -  
47 -1. **单一配置源**:每种能力只在一个地方配置  
48 -2. **统一抽象模式**:translation / embedding / rerank 采用相同结构  
49 -3. **平台级可插拔**:能力 = 接口 + 多 provider 实现,通过配置切换  
50 -4. **丢弃历史包袱**:移除冗余配置、合并重复逻辑  
51 -  
52 -### 2.2 推荐方案:平台级 Provider Registry  
53 -  
54 -**核心思想**:平台定义“能力”,每种能力有统一接口;多个 provider 实现该接口;配置只在一个地方。  
55 -  
56 -```  
57 -┌─────────────────────────────────────────────────────────────┐  
58 -│ Platform (Search Engine) │  
59 -├─────────────────────────────────────────────────────────────┤  
60 -│ Capability: Translation Embedding Rerank │  
61 -│ │ │ │ │ │  
62 -│ ▼ ▼ ▼ ▼ │  
63 -│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │  
64 -│ │ direct │ │ http │ │ http │ ← Provider 实现 │  
65 -│ │ http │ │ vllm │ │ vllm │ (可扩展) │  
66 -│ │ google │ │ │ │ │ │  
67 -│ └─────────┘ └─────────┘ └─────────┘ │  
68 -│ ▲ ▲ ▲ │  
69 -│ └────────────┴────────────┴── 统一从 services.* 读取 │  
70 -└─────────────────────────────────────────────────────────────┘  
71 -```  
72 -  
73 ----  
74 -  
75 -## 三、统一改造方案  
76 -  
77 -### 3.1 配置结构(单一源)  
78 -  
79 -**只保留 `services` 块**,移除 query_config / rerank 中的 provider 相关字段:  
80 -  
81 -```yaml  
82 -services:  
83 - translation:  
84 - provider: "direct" # 当前使用的 provider  
85 - providers:  
86 - direct:  
87 - model: "qwen"  
88 - http:  
89 - base_url: "http://127.0.0.1:6006"  
90 - model: "qwen"  
91 - timeout_sec: 10.0  
92 - google:  
93 - enabled: false  
94 - # ...  
95 -  
96 - embedding:  
97 - provider: "http"  
98 - providers:  
99 - http:  
100 - base_url: "http://127.0.0.1:6005"  
101 - vllm:  
102 - enabled: false  
103 - # ...  
104 -  
105 - rerank:  
106 - provider: "http"  
107 - providers:  
108 - http:  
109 - base_url: "http://127.0.0.1:6007"  
110 - service_path: "/rerank"  
111 - vllm:  
112 - enabled: false  
113 - # ...  
114 -```  
115 -  
116 -**环境变量**(部署态覆盖)保持简洁:  
117 -- `TRANSLATION_PROVIDER`, `TRANSLATION_SERVICE_URL`  
118 -- `EMBEDDING_PROVIDER`, `EMBEDDING_SERVICE_URL`  
119 -- `RERANK_PROVIDER`, `RERANKER_SERVICE_URL`  
120 -  
121 -### 3.2 统一 Provider 创建入口  
122 -  
123 -新建 `providers/` 模块,统一工厂:  
124 -  
125 -```python  
126 -# providers/__init__.py  
127 -def create_translation_provider(config: ServicesConfig) -> TranslationProvider  
128 -def create_embedding_provider(config: ServicesConfig) -> EmbeddingProvider  
129 -def create_rerank_provider(config: ServicesConfig) -> RerankProvider  
130 -```  
131 -  
132 -每个 factory 从 `config.services["translation"]` 等读取,不再从 query_config / rerank 块读取。  
133 -  
134 -### 3.3 能力接口(Protocol)  
135 -  
136 -```python  
137 -# providers/base.py  
138 -class TranslationProvider(Protocol):  
139 - def translate(self, text, target_lang, ...) -> Optional[str]: ...  
140 - def translate_for_indexing(self, ...) -> Dict[str, Optional[str]]: ...  
141 -  
142 -class EmbeddingProvider(Protocol):  
143 - def encode_text(self, texts: List[str]) -> np.ndarray: ...  
144 - def encode_image(self, url: str) -> Optional[np.ndarray]: ...  
145 -  
146 -class RerankProvider(Protocol):  
147 - def rerank(self, query: str, docs: List[str], timeout: float) -> Tuple[Optional[List[float]], ...]: ...  
148 -```  
149 -  
150 -### 3.4 迁移步骤  
151 -  
152 -| 步骤 | 内容 |  
153 -|------|------|  
154 -| 1 | 新建 `config/services_config.py`,定义 `ServicesConfig`,只从 `services` 块加载 |  
155 -| 2 | 新建 `providers/` 目录,实现 `create_*_provider()`,迁移 translation/rerank 逻辑 |  
156 -| 3 | 为 embedding 增加 provider 抽象(HttpEmbeddingProvider),封装 BgeEncoder/CLIPImageEncoder 的 HTTP 调用 |  
157 -| 4 | 从 `query_config` 移除 translation_provider/providers/service_url 等 |  
158 -| 5 | 从 `rerank` 块移除 rerank_provider/providers/service_url 等 |  
159 -| 6 | 精简 `config_loader.py`,删除冗长的 provider 合并逻辑 |  
160 -| 7 | 更新 `config.yaml`,删除重复配置 |  
161 -| 8 | 调用方改为使用 `create_*_provider(services_config)` |  
162 -  
163 ----  
164 -  
165 -## 四、回答核心问题  
166 -  
167 -### Q1: 可插拔是提供者内部可选择,还是平台多 provider?  
168 -  
169 -**答**:采用 **平台级多 provider**。每种能力(translation/embedding/rerank)在平台层定义接口,多个独立 provider 实现该接口,通过配置切换。提供者内部(如 direct 的 qwen/deepl)可作为该 provider 的子选项,但不作为平台级扩展点。  
170 -  
171 -### Q2: 现在是两者都有吗?  
172 -  
173 -**答**:之前是混合状态——配置分散、三种能力实现不一致。改造后 **只保留平台级可插拔**,结构统一。  
174 -  
175 -### Q3: 如何减少混乱、架构清晰?  
176 -  
177 -**答**:  
178 -1. **单一配置源**:`services.{translation,embedding,rerank}`  
179 -2. **统一模式**:每种能力 = Protocol + factory + 多 provider 实现  
180 -3. **丢弃冗余**:删除 query_config/rerank 中的 provider 配置,删除 service_endpoints 中的重复解析逻辑  
181 -  
182 ----  
183 -  
184 -## 五、改造后的目录结构  
185 -  
186 -```  
187 -providers/  
188 -├── __init__.py # create_*_provider 导出  
189 -├── base.py # Protocol 定义  
190 -├── translation/  
191 -│ ├── direct.py # 进程内 Translator  
192 -│ ├── http.py # HttpTranslationClient  
193 -│ └── ...  
194 -├── embedding/  
195 -│ ├── http.py # HttpEmbeddingProvider (封装 BgeEncoder/CLIP 的 HTTP)  
196 -│ └── vllm.py # reserved  
197 -└── rerank/  
198 - ├── http.py # HttpRerankClient  
199 - └── vllm.py # reserved  
200 -```  
201 -  
202 -调用方(query_parser, searcher, indexer)只依赖 `providers.create_*_provider(services_config)`,不关心具体实现。  
docs/DEVELOPER_GUIDE.md
@@ -42,13 +42,10 @@ @@ -42,13 +42,10 @@
42 42
43 以下文档由本指南引用,按需深入: 43 以下文档由本指南引用,按需深入:
44 44
45 -- [QUICKSTART.md](./QUICKSTART.md) — 环境、服务、模块、请求示例  
46 -- [PROVIDER_ARCHITECTURE.md](./PROVIDER_ARCHITECTURE.md) — 翻译/向量/重排 Provider 架构与新增 Provider  
47 -- [MODULE_EXTENSION_SPEC.md](./MODULE_EXTENSION_SPEC.md) — 向量化/重排后端可插拔设计、协议与配置 45 +- [QUICKSTART.md](./QUICKSTART.md) — 环境、服务、模块、请求示例;§2–§4 含基础配置与 Provider/模块扩展
48 - [系统设计文档.md](./系统设计文档.md) — 索引结构、数据流、通用化设计 46 - [系统设计文档.md](./系统设计文档.md) — 索引结构、数据流、通用化设计
49 -- [基础配置指南.md](./基础配置指南.md) — 索引与查询配置说明  
50 - [搜索API对接指南.md](./搜索API对接指南.md) — 搜索/索引/管理接口完整说明 47 - [搜索API对接指南.md](./搜索API对接指南.md) — 搜索/索引/管理接口完整说明
51 -- [QUICKSTART.md](./QUICKSTART.md) §1.4–1.8 — 系统要求、Python 环境、外部服务与生产凭证、店匠数据源(原环境配置说明已并入) 48 +- [QUICKSTART.md](./QUICKSTART.md) §1.4–1.8 — 系统要求、Python 环境、外部服务与生产凭证、店匠数据源
52 - [Usage-Guide.md](./Usage-Guide.md) — 运维、日志、多环境、故障排查 49 - [Usage-Guide.md](./Usage-Guide.md) — 运维、日志、多环境、故障排查
53 50
54 --- 51 ---
@@ -159,19 +156,19 @@ docs/ # 文档(含本指南) @@ -159,19 +156,19 @@ docs/ # 文档(含本指南)
159 156
160 - **职责**:提供向量服务(FastAPI):`POST /embed/text`、`POST /embed/image`;服务内按配置加载文本后端(如 BGE)与图像后端(如 clip-as-service 或本地 CN-CLIP),实现协议即可插拔。 157 - **职责**:提供向量服务(FastAPI):`POST /embed/text`、`POST /embed/image`;服务内按配置加载文本后端(如 BGE)与图像后端(如 clip-as-service 或本地 CN-CLIP),实现协议即可插拔。
161 - **原则**:图片后端实现 `embeddings/protocols.ImageEncoderProtocol`;配置优先从 `config` 或 `embeddings/config.py` 读取,与 `services.embedding` 的 URL 分离。 158 - **原则**:图片后端实现 `embeddings/protocols.ImageEncoderProtocol`;配置优先从 `config` 或 `embeddings/config.py` 读取,与 `services.embedding` 的 URL 分离。
162 -- **详见**:`embeddings/README.md`、[MODULE_EXTENSION_SPEC.md](./MODULE_EXTENSION_SPEC.md) 159 +- **详见**:`embeddings/README.md`、本指南 §7.5–§7.6
163 160
164 ### 4.7 reranker 161 ### 4.7 reranker
165 162
166 - **职责**:提供重排服务(FastAPI):`POST /rerank`(query + docs → scores);服务内按配置加载一个重排后端(如 BGE 或 Qwen3-vLLM),实现 `score_with_meta(query, docs, normalize)` 协议。 163 - **职责**:提供重排服务(FastAPI):`POST /rerank`(query + docs → scores);服务内按配置加载一个重排后端(如 BGE 或 Qwen3-vLLM),实现 `score_with_meta(query, docs, normalize)` 协议。
167 - **原则**:对外 HTTP 契约固定;新增后端只在 `reranker/backends` 中实现协议并注册,不修改调用方。 164 - **原则**:对外 HTTP 契约固定;新增后端只在 `reranker/backends` 中实现协议并注册,不修改调用方。
168 -- **详见**:[MODULE_EXTENSION_SPEC.md](./MODULE_EXTENSION_SPEC.md) 165 +- **详见**:本指南 §7.5–§7.6
169 166
170 ### 4.8 providers 167 ### 4.8 providers
171 168
172 - **职责**:统一“能力”的调用方式:翻译、向量、重排均通过工厂函数(如 `create_translation_provider()`、`create_rerank_provider()`、`create_embedding_provider()`)获取实现,配置来自 `config/services_config`(即 `config.yaml` 的 `services` + 环境变量)。 169 - **职责**:统一“能力”的调用方式:翻译、向量、重排均通过工厂函数(如 `create_translation_provider()`、`create_rerank_provider()`、`create_embedding_provider()`)获取实现,配置来自 `config/services_config`(即 `config.yaml` 的 `services` + 环境变量)。
173 - **原则**:业务代码只依赖 Provider 接口,不依赖具体 URL 或后端类型;新增调用方式(如新 Provider 类型)在对应 `providers/<capability>.py` 中实现并在工厂中注册。 170 - **原则**:业务代码只依赖 Provider 接口,不依赖具体 URL 或后端类型;新增调用方式(如新 Provider 类型)在对应 `providers/<capability>.py` 中实现并在工厂中注册。
174 -- **详见**:[PROVIDER_ARCHITECTURE.md](./PROVIDER_ARCHITECTURE.md) 171 +- **详见**:本指南 §7.2;[QUICKSTART.md](./QUICKSTART.md) §3
175 172
176 ### 4.9 suggestion 173 ### 4.9 suggestion
177 174
@@ -207,7 +204,7 @@ docs/ # 文档(含本指南) @@ -207,7 +204,7 @@ docs/ # 文档(含本指南)
207 204
208 - **调用方**:通过 Provider(如 `HttpRerankProvider`)访问能力,不依赖具体 URL 或服务内实现。 205 - **调用方**:通过 Provider(如 `HttpRerankProvider`)访问能力,不依赖具体 URL 或服务内实现。
209 - **服务内**:通过“后端”实现具体推理(如 BGE 与 Qwen3-vLLM);后端实现协议、在配置与工厂中注册即可插拔。 206 - **服务内**:通过“后端”实现具体推理(如 BGE 与 Qwen3-vLLM);后端实现协议、在配置与工厂中注册即可插拔。
210 -- 新增“一种调用方式”在 providers 中扩展;新增“一种推理实现”在对应服务的 backends 中扩展,并遵循 [MODULE_EXTENSION_SPEC.md](./MODULE_EXTENSION_SPEC.md) 207 +- 新增“一种调用方式”在 providers 中扩展;新增“一种推理实现”在对应服务的 backends 中扩展,并遵循本指南 §7
211 208
212 ### 5.5 协议契约 209 ### 5.5 协议契约
213 210
@@ -266,8 +263,8 @@ services: @@ -266,8 +263,8 @@ services:
266 263
267 ### 7.1 何时看扩展规范 264 ### 7.1 何时看扩展规范
268 265
269 -- 新增或替换**翻译/向量/重排**的调用方式(如新的 HTTP 客户端、gRPC):见 [PROVIDER_ARCHITECTURE.md](./PROVIDER_ARCHITECTURE.md)。  
270 -- 新增或替换**向量/重排**的推理实现(如新模型、vLLM):见 [MODULE_EXTENSION_SPEC.md](./MODULE_EXTENSION_SPEC.md)。 266 +- 新增或替换**翻译/向量/重排**的调用方式(如新的 HTTP 客户端、gRPC):见本指南 §7.2、[QUICKSTART.md](./QUICKSTART.md) §3。
  267 +- 新增或替换**向量/重排**的推理实现(如新模型、vLLM):见本指南 §7.3–§7.6。
271 268
272 ### 7.2 新增 Provider(调用方式) 269 ### 7.2 新增 Provider(调用方式)
273 270
@@ -284,7 +281,7 @@ services: @@ -284,7 +281,7 @@ services:
284 4. **服务启动**:服务(如 `reranker/server.py`)启动时读取 backend 配置并调用工厂,不写死后端类型。 281 4. **服务启动**:服务(如 `reranker/server.py`)启动时读取 backend 配置并调用工厂,不写死后端类型。
285 5. **文档与依赖**:在 README 或 docs 中说明新后端的依赖、资源要求;可选依赖放入 `requirements_ml.txt` 或 extra。 282 5. **文档与依赖**:在 README 或 docs 中说明新后端的依赖、资源要求;可选依赖放入 `requirements_ml.txt` 或 extra。
286 283
287 -详见 [MODULE_EXTENSION_SPEC.md](./MODULE_EXTENSION_SPEC.md) 的“新增后端清单” 284 +详见下文 §7.6 新增后端清单
288 285
289 ### 7.4 禁止做法 286 ### 7.4 禁止做法
290 287
@@ -292,6 +289,38 @@ services: @@ -292,6 +289,38 @@ services:
292 - 新增能力时复制一套独立配置体系或新顶层包,而不纳入 `services` 与 providers/backends。 289 - 新增能力时复制一套独立配置体系或新顶层包,而不纳入 `services` 与 providers/backends。
293 - 新增后端时破坏现有协议(如修改返回长度、顺序或 meta 约定)。 290 - 新增后端时破坏现有协议(如修改返回长度、顺序或 meta 约定)。
294 291
  292 +### 7.5 重排与向量化协议与配置速查
  293 +
  294 +**设计原则**:同类型后端实现同一协议;配置来自 `config/config.yaml` 的 `services` 块,环境变量可覆盖;调用方通过 Provider 访问服务,服务内通过 Backend 完成推理;新增后端 = 实现协议 + 在配置与工厂中注册。
  295 +
  296 +**重排后端协议(服务内)**:所有在 reranker 服务内加载的后端须实现 `score_with_meta(query, docs, normalize=True) -> (scores: List[float], meta: dict)`。返回的 `scores[i]` 与 `docs[i]` 一一对应;meta 至少含 `input_docs`、`usable_docs`、`elapsed_ms` 等。对外 HTTP 契约固定:`POST /rerank` 请求体 `{ "query": str, "docs": [str] }`,响应体 `{ "scores": [float], "meta": object }`;`GET /health` 返回 `status`、`model`、`backend` 等。
  297 +
  298 +**向量化后端协议(服务内)**:文本后端需支持 `encode_batch(texts, batch_size, device) -> List[ndarray]`,与 texts 一一对应;图片后端实现 `embeddings/protocols.ImageEncoderProtocol`:`encode_image_urls(urls, batch_size) -> List[Optional[ndarray]]`,与 urls 等长。
  299 +
  300 +**配置速查**:
  301 +
  302 +| 层次 | 配置键 | 重排 | 向量化 |
  303 +|------|--------|------|--------|
  304 +| 调用方 | `services.<capability>.provider` | http | http |
  305 +| 调用方 | `services.<capability>.providers.http.base_url` | 6007 | 6005 |
  306 +| 服务内 | `services.<capability>.backend` | bge / qwen3_vllm 等 | 见 embeddings/config |
  307 +| 服务内 | `services.<capability>.backends.<name>` | 模型名、batch、vLLM 参数 | 模型名、device 等 |
  308 +
  309 +### 7.6 新增后端清单(以 Qwen3-Reranker 为例)
  310 +
  311 +1. **实现协议**:在 `reranker/backends/qwen3_vllm.py` 中实现类,提供 `score_with_meta(query, docs, normalize) -> (scores, meta)`,输出与 docs 等长且顺序一致。
  312 +2. **配置**:在 `config/config.yaml` 的 `services.rerank.backends` 下增加 `qwen3_vllm` 块(model_name、engine、max_model_len、gpu_memory_utilization 等);支持环境变量 `RERANK_BACKEND=qwen3_vllm`。
  313 +3. **注册**:在 `reranker/backends/__init__.py` 的 `get_rerank_backend(name, config)` 中增加 `qwen3_vllm` 分支。
  314 +4. **服务启动**:`reranker/server.py` 启动时根据配置调用 `get_rerank_backend(backend_name, backend_cfg)` 得到实例。
  315 +5. **调用方**:无需修改;仅部署时启动使用新后端的 reranker 服务即可。
  316 +6. **文档与依赖**:在 `reranker/README.md` 或 docs 中说明依赖(如 vllm)、显存建议;可选依赖放入 `requirements_ml.txt` 或 extra。
  317 +
  318 +### 7.7 与现有配置的兼容说明
  319 +
  320 +- **reranker**:当前 `reranker/config.py` 的 BGE 相关默认值可保留为兜底,或将默认值迁移到 `config.yaml` 的 `services.rerank.backends.bge`,由 config 只读环境变量与 YAML。
  321 +- **embeddings**:`embeddings/config.py` 的文本/图片及 clip-as-service 开关与 `services.embedding` 的 URL 分离;后续多种后端可在 `services.embedding.backends` 中增加条目。
  322 +- **环境变量**:所有能力均支持环境变量覆盖(如 `RERANKER_SERVICE_URL`、`RERANK_BACKEND`、`EMBEDDING_SERVICE_URL`),便于多环境部署。
  323 +
295 --- 324 ---
296 325
297 ## 8. 代码规范与质量 326 ## 8. 代码规范与质量
@@ -335,7 +364,7 @@ services: @@ -335,7 +364,7 @@ services:
335 ### 9.2 配置与扩展 364 ### 9.2 配置与扩展
336 365
337 - [ ] 新增配置项放在 `config.yaml` 或 `services.<capability>` 下,并有环境变量覆盖方式(如需要)。 366 - [ ] 新增配置项放在 `config.yaml` 或 `services.<capability>` 下,并有环境变量覆盖方式(如需要)。
338 -- [ ] 新增 Provider 或 Backend 时已阅读 [PROVIDER_ARCHITECTURE.md](./PROVIDER_ARCHITECTURE.md) / [MODULE_EXTENSION_SPEC.md](./MODULE_EXTENSION_SPEC.md),并按要求实现协议、注册与配置。 367 +- [ ] 新增 Provider 或 Backend 时已阅读本指南 §7,并按要求实现协议、注册与配置。
339 - [ ] 新增后端满足现有协议(输入输出、顺序、长度、meta),未破坏调用方。 368 - [ ] 新增后端满足现有协议(输入输出、顺序、长度、meta),未破坏调用方。
340 369
341 ### 9.3 索引与查询 370 ### 9.3 索引与查询
@@ -364,10 +393,8 @@ services: @@ -364,10 +393,8 @@ services:
364 |------|------| 393 |------|------|
365 | 新人上手、环境与请求示例 | [QUICKSTART.md](./QUICKSTART.md) | 394 | 新人上手、环境与请求示例 | [QUICKSTART.md](./QUICKSTART.md) |
366 | 框架全貌与规范(本文) | 本指南 | 395 | 框架全貌与规范(本文) | 本指南 |
367 -| 翻译/向量/重排 Provider 扩展 | [PROVIDER_ARCHITECTURE.md](./PROVIDER_ARCHITECTURE.md) |  
368 -| 向量/重排后端可插拔与协议 | [MODULE_EXTENSION_SPEC.md](./MODULE_EXTENSION_SPEC.md) | 396 +| Provider 与基础配置、模块扩展(协议与后端) | [QUICKSTART.md](./QUICKSTART.md) §2–§4、本指南 §7 |
369 | 索引结构、数据流、通用化设计 | [系统设计文档.md](./系统设计文档.md) | 397 | 索引结构、数据流、通用化设计 | [系统设计文档.md](./系统设计文档.md) |
370 -| 索引与查询配置说明 | [基础配置指南.md](./基础配置指南.md) |  
371 | 搜索/索引 API 完整说明 | [搜索API对接指南.md](./搜索API对接指南.md) | 398 | 搜索/索引 API 完整说明 | [搜索API对接指南.md](./搜索API对接指南.md) |
372 | 搜索 API 参数速查 | [搜索API速查表.md](./搜索API速查表.md) | 399 | 搜索 API 参数速查 | [搜索API速查表.md](./搜索API速查表.md) |
373 | 首次部署、新机器环境、生产凭证 | [QUICKSTART.md](./QUICKSTART.md) §1.4–1.8 | 400 | 首次部署、新机器环境、生产凭证 | [QUICKSTART.md](./QUICKSTART.md) §1.4–1.8 |
docs/MODULE_EXTENSION_SPEC.md deleted
@@ -1,223 +0,0 @@ @@ -1,223 +0,0 @@
1 -# 模块扩展规范(向量化 / 重排 可插拔设计)  
2 -  
3 -本文档定义**向量化(embedding)**与**重排(rerank)**模块的扩展规范,保证新增模型/推理引擎时框架统一、配置统一、可插拔。新增 Qwen3-Reranker-0.6B(vLLM)等模块时需遵循本规范。  
4 -  
5 -**相关文档**:  
6 -- 调用方(Provider 选择、HTTP 客户端):[PROVIDER_ARCHITECTURE.md](./PROVIDER_ARCHITECTURE.md)  
7 -- 向量化使用说明:[embeddings/README.md](../embeddings/README.md)、[向量化模块和API说明文档.md](./向量化模块和API说明文档.md)  
8 -  
9 ----  
10 -  
11 -## 1. 设计原则  
12 -  
13 -| 原则 | 说明 |  
14 -|------|------|  
15 -| **接口契约** | 所有同类型后端实现同一协议(Protocol),调用方只依赖协议不依赖具体实现。 |  
16 -| **单一配置源** | 能力类型、后端类型、后端参数均来自 `config/config.yaml` 的 `services` 块,环境变量可覆盖。 |  
17 -| **服务与后端分离** | **调用方**通过 Provider(如 `HttpRerankProvider`)访问**服务**;**服务内部**通过后端实现(如 BGE、Qwen3-vLLM)完成推理。新增“提供者”时区分:是新增一种**调用方式**(新 Provider)还是新增一种**推理实现**(新 Backend)。 |  
18 -| **可插拔后端** | 重排/向量化服务在启动时根据配置加载一个后端;新增后端 = 实现协议 + 在配置与工厂中注册,不改服务入口代码。 |  
19 -  
20 ----  
21 -  
22 -## 2. 配置体系(统一结构)  
23 -  
24 -### 2.1 配置来源与优先级  
25 -  
26 -- **主配置**:`config/config.yaml` 下的 `services.<capability>`  
27 -- **覆盖**:环境变量(如 `RERANKER_SERVICE_URL`、`RERANK_BACKEND`)> config 文件  
28 -- **解析**:`config/services_config.py` 提供 `get_*_config()`,各模块从该处读取,避免散落多处。  
29 -  
30 -### 2.2 能力块通用结构  
31 -  
32 -每种能力(translation / embedding / rerank)在 `services` 下结构一致:  
33 -  
34 -```yaml  
35 -services:  
36 - <capability>:  
37 - provider: "http" # 调用方使用的提供者:http | direct | vllm 等  
38 - base_url: "http://..." # 对外服务 URL(provider=http 时)  
39 - providers:  
40 - http: { base_url: "...", ... }  
41 - direct: { ... }  
42 - vllm: { ... }  
43 - # 以下为「服务内部后端」配置(仅当本能力由本仓库启动的服务承载时使用)  
44 - backend: "bge" # 可选:服务内加载的后端类型  
45 - backends:  
46 - bge: { model_name: "...", batch_size: 64, ... }  
47 - qwen3_vllm: { model_name: "Qwen/Qwen3-Reranker-0.6B", ... }  
48 -```  
49 -  
50 -- **provider**:调用方(搜索 API、索引等)如何访问该能力(如 HTTP 调 `base_url`)。  
51 -- **backend / backends**:当该能力由本仓库内的服务进程提供时,该进程内应加载哪个后端及参数(如 reranker 服务内用 BGE 还是 Qwen3-vLLM)。  
52 -  
53 ----  
54 -  
55 -## 3. 重排(Rerank)模块规范  
56 -  
57 -### 3.1 调用链  
58 -  
59 -- **调用方**:`search/rerank_client.py` → `create_rerank_provider()` → `HttpRerankProvider.rerank(query, docs, timeout_sec)`  
60 -- **协议**:HTTP `POST <base>/rerank`,请求体 `{ "query": str, "docs": [str] }`,响应体 `{ "scores": [float], "meta": dict }`,scores 与 docs 一一对应。  
61 -- **服务实现**:`reranker/server.py`(FastAPI)在启动时加载一个**重排后端**,对 `/rerank` 的请求用该后端计算分数。  
62 -  
63 -因此:  
64 -- **新增一种“调用方式”**(如 gRPC):在 `providers/rerank.py` 增加新 Provider 类,并在 `create_rerank_provider()` 中按 `provider` 选择。  
65 -- **新增一种“推理实现”**(如 Qwen3-vLLM):在 reranker 服务内实现**重排后端协议**并注册,服务通过配置选择后端。  
66 -  
67 -### 3.2 重排后端协议(服务内)  
68 -  
69 -所有在 `reranker` 服务内加载的后端必须实现以下接口(与当前 `BGEReranker` 一致):  
70 -  
71 -```python  
72 -# 行为契约(不强制继承,实现以下方法即可)  
73 -class RerankBackendProtocol(Protocol):  
74 - def score_with_meta(  
75 - self,  
76 - query: str,  
77 - docs: List[str],  
78 - normalize: bool = True,  
79 - ) -> Tuple[List[float], Dict[str, Any]]:  
80 - """  
81 - 输入:  
82 - - query: 搜索查询字符串  
83 - - docs: 文档列表,与返回的 scores 一一对应  
84 - - normalize: 是否对分数做归一化(如 sigmoid)  
85 - 输出:  
86 - - scores: 与 docs 等长的分数列表,顺序一致  
87 - - meta: 至少含 input_docs, usable_docs, unique_docs, elapsed_ms 等,供日志与调试  
88 - """  
89 - ...  
90 -```  
91 -  
92 -- **顺序**:返回的 `scores[i]` 必须对应 `docs[i]`。  
93 -- **空/无效**:对无法打分的 doc 可填 0.0,并在 meta 中说明。  
94 -- **去重**:后端可对 docs 去重再推理以省算力,但返回的 scores 必须按原始 docs 顺序与长度还原。  
95 -  
96 -### 3.3 重排服务配置项(建议)  
97 -  
98 -在 `config/config.yaml` 的 `services.rerank` 下建议结构(与现有 `rerank` 顶层配置区分:顶层为搜索侧融合参数,此处为服务/后端配置):  
99 -  
100 -```yaml  
101 -services:  
102 - rerank:  
103 - provider: "http"  
104 - base_url: "http://127.0.0.1:6007"  
105 - providers:  
106 - http:  
107 - base_url: "http://127.0.0.1:6007"  
108 - service_url: "http://127.0.0.1:6007/rerank"  
109 - # 服务内后端(reranker 进程启动时读取)  
110 - backend: "bge" # bge | qwen3_vllm  
111 - backends:  
112 - bge:  
113 - model_name: "BAAI/bge-reranker-v2-m3"  
114 - device: null  
115 - use_fp16: true  
116 - batch_size: 64  
117 - max_length: 512  
118 - cache_dir: "./model_cache"  
119 - enable_warmup: true  
120 - qwen3_vllm:  
121 - model_name: "Qwen/Qwen3-Reranker-0.6B"  
122 - engine: "vllm"  
123 - max_model_len: 8192  
124 - tensor_parallel_size: 1  
125 - gpu_memory_utilization: 0.8  
126 - instruction: "Given a web search query, retrieve relevant passages that answer the query"  
127 -```  
128 -  
129 -- 环境变量示例:`RERANK_BACKEND=qwen3_vllm`、`RERANKER_SERVICE_URL=http://127.0.0.1:6007`。  
130 -  
131 -### 3.4 重排后端目录与注册  
132 -  
133 -- **推荐目录**:`reranker/backends/`  
134 - - `reranker/backends/__init__.py`:导出 `get_rerank_backend(name, config) -> 实现 RerankBackendProtocol 的实例`  
135 - - `reranker/backends/bge.py`:现有 BGE 逻辑迁移或封装为 `BGERerankerBackend`  
136 - - `reranker/backends/qwen3_vllm.py`:新增 Qwen3-Reranker-0.6B + vLLM 实现  
137 -- **服务启动**:`reranker/server.py` 在 `startup` 中读取 `services.rerank.backend` 与 `services.rerank.backends.<name>`,调用 `get_rerank_backend(backend, cfg)` 得到实例,再对外提供同一 `/rerank` API。  
138 -  
139 -### 3.5 重排 HTTP API 契约(不变)  
140 -  
141 -无论后端是 BGE 还是 Qwen3-vLLM,对外接口保持一致,便于调用方与运维统一:  
142 -  
143 -- **POST /rerank**  
144 - - Request: `{ "query": string, "docs": [string], "normalize": optional bool }`  
145 - - Response: `{ "scores": [float], "meta": object }`  
146 -- **GET /health**  
147 - - Response: `{ "status": "ok"|"unavailable", "model_loaded": bool, "model": string, "backend": string }`  
148 -  
149 ----  
150 -  
151 -## 4. 向量化(Embedding)模块规范  
152 -  
153 -### 4.1 调用链  
154 -  
155 -- **调用方**:通过 `providers.create_embedding_provider()` 得到 HTTP 客户端,请求 `POST /embed/text`、`POST /embed/image`。  
156 -- **服务实现**:`embeddings/server.py` 在启动时按配置加载**文本后端**与**图片后端**,二者可独立选择。  
157 -  
158 -### 4.2 向量化后端协议(服务内)  
159 -  
160 -- **文本**:与当前 `BgeTextModel` 一致,需支持 `encode_batch(texts, batch_size, device) -> List[ndarray]`,元素与 `texts` 一一对应,失败可为 None。  
161 -- **图片**:已定义 `embeddings/protocols.ImageEncoderProtocol`:  
162 - - `encode_image_urls(urls: List[str], batch_size: Optional[int]) -> List[Optional[np.ndarray]]`  
163 - - 与 `urls` 等长,失败位置为 None。  
164 -  
165 -新增文本/图片后端时实现对应协议即可;服务通过配置选择后端(如 `USE_CLIP_AS_SERVICE` 选 clip-as-service 或本地 CN-CLIP)。  
166 -  
167 -### 4.3 向量化配置(现有与扩展)  
168 -  
169 -- **Provider/URL**:`config/config.yaml` → `services.embedding`,环境变量 `EMBEDDING_SERVICE_URL`。  
170 -- **服务内**:`embeddings/config.py` 中已有 `TEXT_*`、`IMAGE_*`、`USE_CLIP_AS_SERVICE`、`CLIP_AS_SERVICE_SERVER`;若未来支持多种文本/图像后端,建议在 `services.embedding.backend` / `services.embedding.backends` 中统一,与重排结构对齐。  
171 -  
172 ----  
173 -  
174 -## 5. 新增后端清单(以 Qwen3-Reranker-0.6B + vLLM 为例)  
175 -  
176 -按本规范新增「重排后端」Qwen3-Reranker-0.6B(vLLM 推理)时,建议步骤:  
177 -  
178 -1. **实现协议**  
179 - - 在 `reranker/backends/qwen3_vllm.py` 中实现类(如 `Qwen3VLLMReranker`),提供 `score_with_meta(query, docs, normalize) -> (scores, meta)`。  
180 - - 推理逻辑参考 [Qwen3-Reranker-0.6B](https://huggingface.co/Qwen/Qwen3-Reranker-0.6B) 的 vLLM 用法(format_instruction、process_inputs、compute_logits、yes/no token 等),输出与 `docs` 等长且顺序一致的 scores。  
181 -  
182 -2. **配置**  
183 - - 在 `config/config.yaml` 的 `services.rerank.backends` 下增加 `qwen3_vllm` 块(model_name、engine、max_model_len、tensor_parallel_size、gpu_memory_utilization、instruction 等)。  
184 - - 在 `config/services_config.py` 或 reranker 专用 config 中增加对 `backend` / `backends` 的读取;环境变量支持 `RERANK_BACKEND=qwen3_vllm`。  
185 -  
186 -3. **注册**  
187 - - 在 `reranker/backends/__init__.py` 的 `get_rerank_backend(name, config)` 中增加 `"qwen3_vllm"` 分支,实例化 `Qwen3VLLMReranker` 并传入 config。  
188 -  
189 -4. **服务启动**  
190 - - 若尚未重构:可暂时在 `reranker/server.py` 中根据 `RERANK_BACKEND` 或 config 选择加载 `BGEReranker` 或 `Qwen3VLLMReranker`。  
191 - - 若已引入 `get_rerank_backend()`:`reranker/server.py` 启动时统一调用 `get_rerank_backend(backend_name, backend_cfg)` 得到实例。  
192 -  
193 -5. **调用方**  
194 - - 无需修改:`providers/rerank.py` 仍为 HTTP,`search/rerank_client.py` 仍调用同一 `/rerank` 接口;仅部署时启动使用 Qwen3-vLLM 后端的 reranker 服务即可。  
195 -  
196 -6. **文档与依赖**  
197 - - 在 `reranker/README.md` 或 `docs/` 中说明 Qwen3-vLLM 的依赖(vllm>=0.8.5、transformers 等)、显存建议、与 BGE 的对比。  
198 - - 若 vLLM 为可选依赖,在 `requirements_ml.txt` 或可选 extra 中声明。  
199 -  
200 ----  
201 -  
202 -## 6. 小结表  
203 -  
204 -| 层次 | 配置键 | 重排 | 向量化(文本/图) |  
205 -|------|--------|------|-------------------|  
206 -| 调用方 | `services.<capability>.provider` | http | http |  
207 -| 调用方 | `services.<capability>.providers.http.base_url` | 6007 | 6005 |  
208 -| 服务内 | `services.<capability>.backend` | bge / qwen3_vllm | (当前在 embeddings/config.py) |  
209 -| 服务内 | `services.<capability>.backends.<name>` | 模型名、batch、vLLM 参数等 | 模型名、device 等 |  
210 -| 协议 | 重排 | `score_with_meta(query, docs, normalize)` | — |  
211 -| 协议 | 向量化 | — | 文本: encode_batch;图: ImageEncoderProtocol |  
212 -  
213 -遵循上述规范后,新增 Qwen3-Reranker-0.6B 或其它重排/向量化后端时,只需实现协议、在配置与工厂中注册,即可与现有 BGE/CLIP 等并列切换,保持框架统一与可插拔。  
214 -  
215 ----  
216 -  
217 -## 7. 与现有配置文件的兼容说明  
218 -  
219 -- **reranker**:当前 `reranker/config.py` 中 `RerankerConfig`(PORT、MODEL_NAME、BATCH_SIZE 等)仅被 BGE 服务使用。扩展多后端时,建议:  
220 - - 保留该文件作为**默认/兜底**(仅当未配置 `services.rerank.backend` 时使用),或  
221 - - 将 BGE 的默认值迁移到 `config.yaml` 的 `services.rerank.backends.bge`,`reranker/config.py` 只读环境变量与 YAML,不再硬编码模型名。  
222 -- **embeddings**:`embeddings/config.py` 的 `EmbeddingConfig` 已包含文本/图片及 clip-as-service 开关,与 `services.embedding` 的 URL 分离(URL 由 `services_config` 管)。后续若增加多种文本/图像后端,可同样在 `services.embedding.backends` 中增加条目,与重排对齐。  
223 -- **环境变量**:所有能力均支持通过环境变量覆盖(如 `RERANKER_SERVICE_URL`、`RERANK_BACKEND`、`EMBEDDING_SERVICE_URL`),便于部署与多环境。  
docs/PROVIDER_ARCHITECTURE.md deleted
@@ -1,8 +0,0 @@ @@ -1,8 +0,0 @@
1 -# Provider 架构(已并入)  
2 -  
3 -本文档已并入 `docs/QUICKSTART.md`,请直接查看:  
4 -  
5 -- `docs/QUICKSTART.md` -> **3. Provider 架构**  
6 -- `docs/QUICKSTART.md` -> **4. 模块扩展规范(Embedding / Rerank)**  
7 -  
8 -保留此文件仅用于兼容历史链接,避免重复维护导致内容漂移。  
docs/QUICKSTART.md
@@ -8,12 +8,7 @@ @@ -8,12 +8,7 @@
8 8
9 ## 为什么这样整合 9 ## 为什么这样整合
10 10
11 -本文已合并并替代以下文档中的核心内容:  
12 -  
13 -- `docs/PROVIDER_ARCHITECTURE.md`  
14 -- `docs/MODULE_EXTENSION_SPEC.md`  
15 -- `docs/基础配置指南.md`  
16 -- 原 `docs/QUICKSTART.md` 11 +以下文档已删除,其核心内容已并入本文与 [DEVELOPER_GUIDE.md](./DEVELOPER_GUIDE.md) §7:原 `PROVIDER_ARCHITECTURE.md`、`MODULE_EXTENSION_SPEC.md`、`基础配置指南.md`。本文保留环境、服务、基础配置、Provider 与模块扩展的速查;协议与新增后端清单见 DEVELOPER_GUIDE §7。
17 12
18 关于 `docs/Usage-Guide.md`:保留为**运行/运维手册**更清晰(日志、故障排查、多环境切换、建议索引运行细节),本文只保留开发常用且高频的信息,避免一个文档同时承担“开发规范 + 运维 runbook”导致冗长和混乱。 13 关于 `docs/Usage-Guide.md`:保留为**运行/运维手册**更清晰(日志、故障排查、多环境切换、建议索引运行细节),本文只保留开发常用且高频的信息,避免一个文档同时承担“开发规范 + 运维 runbook”导致冗长和混乱。
19 14
@@ -295,7 +290,7 @@ saas-search 以 MySQL 中的店匠标准表为权威数据源: @@ -295,7 +290,7 @@ saas-search 以 MySQL 中的店匠标准表为权威数据源:
295 - **provider/服务配置**:`config/config.yaml` 的 `services` 块 290 - **provider/服务配置**:`config/config.yaml` 的 `services` 块
296 - **环境变量**:`.env` 291 - **环境变量**:`.env`
297 292
298 ---- 293 +---·
299 294
300 ## 2. 基础配置与搜索行为 295 ## 2. 基础配置与搜索行为
301 296
docs/TODO.txt 0 → 100644
@@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
  1 +
  2 +
  3 +AI - 生产 - MySQL
  4 +HOST:10.200.16.14 / localhost
  5 +端口:3316
  6 +用户名:root
  7 +密码:qY8tgodLoA&KT#yQ
  8 +
  9 +AI - 生产 - Redis
  10 +HOST:10.200.16.14 / localhost
  11 +端口:6479
  12 +密码:dxEkegEZ@C5SXWKv
  13 +
  14 +
  15 +远程登录方式:
  16 +# redis
  17 +redis-cli -h 43.166.252.75 -p 6479
  18 +
  19 +# mysql 3个用户,都可以远程登录
  20 +mysql -uroot -p'qY8tgodLoA&KT#yQ'
  21 +CREATE USER 'saas'@'%' IDENTIFIED BY '6dlpco6dVGuqzt^l';
  22 +CREATE USER 'sa'@'%' IDENTIFIED BY 'C#HU!GPps7ck8tsM';
  23 +
  24 +
  25 +
  26 +ES:
  27 +HOST:10.200.16.14 / localhost
  28 +端口:9200
  29 +访问示例:
  30 +用户名密码:saas:4hOaLaf41y2VuI8y
  31 +
  32 +
  33 +你安装过nvidia-container-toolkit吗
  34 +现在有一些开源的推理引擎对向量化模型和重排模型支持的比较好,我们这块也正好要单独拎出来,因此想改造下。
  35 +调研了TEI, vLLM, xinference,目前觉得最合适的是xinference+vLLM后端,
  36 +最好以docker方式部署,让gpu对docker可见需要nvidia-container-toolkit,
  37 +我试了多种方法安装赖nvidia-container-toolkit都失败了
  38 +https://mirrors.aliyun.com/github/releases/NVIDIA/nvidia-container-toolkit/
  39 +https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/index.html
  40 +
  41 +
  42 +bge-m3
  43 +qwen3-embedding
  44 +qwen3-reranker
  45 +
  46 +大概耗时是0.026S,现在用这个xinference都得0.5S,看这个xinference的安装和embedding模型的部署是不是有问题
  47 +
  48 +
  49 +
  50 +xinference是直接支持了embedding和reranker模型这些模型类型,相当于vllm的上层的封装,因此调用接口很简单,也支持bge和qwen3系列。 但是性能这么差 估计是有啥问题。
  51 +不好查的话,用vllm或者其他的推理引擎也行,
  52 +
  53 +选一个推理引擎,相比于我自己直接调modelscope/sentence-transformers,主要是多进程和负载均衡、连续批处理,比较有用
  54 +不知道我理解的有没有问题
  55 +调研了TEI, vLLM, xinference,+vLLM后端
  56 +这个推理引擎怎么选合适,是选VLLM还是xinference
  57 +
  58 +
  59 +
  60 +
  61 +
  62 +
  63 +混用 大模型 使用:hunyuan-turbos-latest
  64 +混元 OpenAI 兼容接口相关调用示例:https://cloud.tencent.com/document/product/1729/111007
  65 +
  66 +
  67 +腾讯云 混元大模型 API_KEY:sk-mN2PiW2gp57B3ykxGs4QhvYxhPzXRZ2bcR5kPqadjboGYwiz
  68 +
  69 +hunyuan翻译:使用模型 hunyuan-translation
  70 +https://cloud.tencent.com/document/product/1729/113395#4.-.E7.A4.BA.E4.BE.8B
  71 +
  72 +
  73 +
  74 +谷歌翻译 基础版:https://docs.cloud.google.com/translate/docs/reference/rest/v2/translate
  75 +
  76 +
  77 +
  78 +阿里云 百炼模型 现在使用的apikey是国内的。
  79 +各地域的 Base URL 和对应的 API Key 是绑定的。
  80 +
  81 +现在使用了美国的服务器,使用了美国的地址,需要在 美国地域控制台页面(https://modelstudio.console.aliyun.com/us-east-1 )中创建或获取API_KEY:
  82 +
  83 +登录 百炼美国地域控制台:https://modelstudio.console.aliyun.com/us-east-1?spm=5176.2020520104.0.0.6b383a98WjpXff
  84 +在 API Key 管理 中创建或复制一个适用于美国地域的 Key
  85 +
  86 +
docs/基础配置指南.md deleted
@@ -1,12 +0,0 @@ @@ -1,12 +0,0 @@
1 -# 基础配置指南(已并入)  
2 -  
3 -本文档内容已并入 `docs/QUICKSTART.md`,请直接查看:  
4 -  
5 -- `docs/QUICKSTART.md` -> **2. 基础配置与搜索行为**  
6 -  
7 -说明:  
8 -  
9 -- 历史版本中“统一硬编码配置”的描述已过时。  
10 -- 当前搜索行为与 provider 配置以 `config/config.yaml` 为主,索引结构在 `mappings/search_products.json`。  
11 -  
12 -保留此文件仅用于兼容历史链接。  
docs/翻译模块说明.md
@@ -17,4 +17,4 @@ TRANSLATION_MODEL=qwen # 或 deepl @@ -17,4 +17,4 @@ TRANSLATION_MODEL=qwen # 或 deepl
17 17
18 ## Provider 配置 18 ## Provider 配置
19 19
20 -Provider 与 URL 在 `config/config.yaml` 的 `services.translation`。详见 `docs/PROVIDER_ARCHITECTURE.md`。 20 +Provider 与 URL 在 `config/config.yaml` 的 `services.translation`。详见 [QUICKSTART.md](./QUICKSTART.md) §3 与 [DEVELOPER_GUIDE.md](./DEVELOPER_GUIDE.md) §7.2。
reranker/README.md
1 # Reranker 模块 1 # Reranker 模块
2 2
3 -**请求示例**见 `docs/QUICKSTART.md` §3.5。扩展规范见 `docs/MODULE_EXTENSION_SPEC.md` 3 +**请求示例**见 `docs/QUICKSTART.md` §3.5。扩展规范见 `docs/DEVELOPER_GUIDE.md` §7
4 4
5 --- 5 ---
6 6