Commit bc54124ca4289b685b811b92914875d62082a345
1 parent
701ae503
docs
Showing
5 changed files
with
311 additions
and
266 deletions
Show diff stats
docs/PROVIDER_ARCHITECTURE.md
| 1 | -# Provider 架构与扩展指南 | |
| 1 | +# Provider 架构(已并入) | |
| 2 | 2 | |
| 3 | -本文档说明如何统一管理翻译、向量化、重排等“能力提供者(provider)”。 | |
| 3 | +本文档已并入 `docs/QUICKSTART.md`,请直接查看: | |
| 4 | 4 | |
| 5 | -**扩展重排/向量化后端(如新增 Qwen3-Reranker、vLLM 等)**:请同时参阅 [模块扩展规范(MODULE_EXTENSION_SPEC.md)](./MODULE_EXTENSION_SPEC.md),其中定义了服务内后端协议、统一配置结构与可插拔实现方式。 | |
| 5 | +- `docs/QUICKSTART.md` -> **3. Provider 架构** | |
| 6 | +- `docs/QUICKSTART.md` -> **4. 模块扩展规范(Embedding / Rerank)** | |
| 6 | 7 | |
| 7 | -## 1. 设计目标 | |
| 8 | - | |
| 9 | -- **调用方稳定**:业务代码不关心具体供应商,只调用统一接口。 | |
| 10 | -- **配置可切换**:通过配置切换 provider,不改业务代码。 | |
| 11 | -- **单一配置源**:所有 provider 配置在 `config/config.yaml` 的 `services` 块。 | |
| 12 | - | |
| 13 | -## 2. 当前落地状态 | |
| 14 | - | |
| 15 | -### 2.1 统一入口 | |
| 16 | - | |
| 17 | -- **模块**:`providers/` | |
| 18 | -- **工厂**:`create_translation_provider()`, `create_rerank_provider()`, `create_embedding_provider()` | |
| 19 | -- **配置**:`config/services_config.py` 从 `services` 块加载,env 可覆盖 | |
| 20 | - | |
| 21 | -### 2.2 翻译 | |
| 22 | - | |
| 23 | -- `providers/translation.py`:`direct`(进程内 Translator)、`http`(HTTP 服务) | |
| 24 | -- 调用方:`query/query_parser.py`, `indexer/indexing_utils.py` | |
| 25 | - | |
| 26 | -### 2.3 重排 | |
| 27 | - | |
| 28 | -- `providers/rerank.py`:`http`(vllm 预留) | |
| 29 | -- 调用方:`search/rerank_client.py` → `run_rerank()` | |
| 30 | - | |
| 31 | -### 2.4 向量化 | |
| 32 | - | |
| 33 | -- `providers/embedding.py`:`http`(vllm 预留) | |
| 34 | -- 封装 `BgeEncoder` / `CLIPImageEncoder`,URL 来自 `services_config` | |
| 35 | - | |
| 36 | -## 3. 配置 | |
| 37 | - | |
| 38 | -**单一配置源**:`config/config.yaml` 的 `services` 块。 | |
| 39 | - | |
| 40 | -```yaml | |
| 41 | -services: | |
| 42 | - translation: | |
| 43 | - provider: "direct" # direct | http | |
| 44 | - providers: | |
| 45 | - direct: { model: "qwen" } | |
| 46 | - http: { base_url: "http://127.0.0.1:6006", model: "qwen", timeout_sec: 10.0 } | |
| 47 | - embedding: | |
| 48 | - provider: "http" | |
| 49 | - providers: | |
| 50 | - http: { base_url: "http://127.0.0.1:6005" } | |
| 51 | - rerank: | |
| 52 | - provider: "http" | |
| 53 | - providers: | |
| 54 | - http: { base_url: "http://127.0.0.1:6007" } | |
| 55 | -``` | |
| 56 | - | |
| 57 | -**环境变量**(部署态覆盖):`TRANSLATION_PROVIDER`, `TRANSLATION_SERVICE_URL`, `EMBEDDING_SERVICE_URL`, `RERANKER_SERVICE_URL` | |
| 58 | - | |
| 59 | -## 4. 新增 provider | |
| 60 | - | |
| 61 | -1. 在 `providers/<capability>.py` 中实现新 provider 类 | |
| 62 | -2. 在 `create_*_provider()` 中注册分支 | |
| 63 | -3. 在 `config/config.yaml` 的 `services.<capability>.providers` 中补充参数 | |
| 8 | +保留此文件仅用于兼容历史链接,避免重复维护导致内容漂移。 | ... | ... |
docs/QUICKSTART.md
| 1 | -# 开发者快速上手 | |
| 1 | +# 开发与配置指南 | |
| 2 | 2 | |
| 3 | -新人入口文档:环境、服务、模块、请求示例一页搞定。 | |
| 3 | +新人入口:环境、服务、模块、请求示例、基础配置、Provider 架构、模块扩展规范,一文档搞定。 | |
| 4 | 4 | |
| 5 | -**建议**:首次参与开发请先阅读 [DEVELOPER_GUIDE.md](./DEVELOPER_GUIDE.md) 建立项目全貌与规范,再使用本页做环境与请求速查。 | |
| 5 | +**建议**:首次参与开发请先阅读 [DEVELOPER_GUIDE.md](./DEVELOPER_GUIDE.md) 建立项目全貌与协作规范,再使用本文做环境与配置速查。 | |
| 6 | 6 | |
| 7 | -## 1. 环境 | |
| 7 | +--- | |
| 8 | + | |
| 9 | +## 为什么这样整合 | |
| 10 | + | |
| 11 | +本文已合并并替代以下文档中的核心内容: | |
| 12 | + | |
| 13 | +- `docs/PROVIDER_ARCHITECTURE.md` | |
| 14 | +- `docs/MODULE_EXTENSION_SPEC.md` | |
| 15 | +- `docs/基础配置指南.md` | |
| 16 | +- 原 `docs/QUICKSTART.md` | |
| 17 | + | |
| 18 | +关于 `docs/Usage-Guide.md`:保留为**运行/运维手册**更清晰(日志、故障排查、多环境切换、建议索引运行细节),本文只保留开发常用且高频的信息,避免一个文档同时承担“开发规范 + 运维 runbook”导致冗长和混乱。 | |
| 19 | + | |
| 20 | +--- | |
| 21 | + | |
| 22 | +## 目录 | |
| 23 | + | |
| 24 | +1. [快速上手](#1-快速上手) | |
| 25 | +2. [基础配置与搜索行为](#2-基础配置与搜索行为) | |
| 26 | +3. [Provider 架构](#3-provider-架构) | |
| 27 | +4. [模块扩展规范(Embedding / Rerank)](#4-模块扩展规范embedding--rerank) | |
| 28 | +5. [验证、日志与常见排障入口](#5-验证日志与常见排障入口) | |
| 29 | +6. [相关文档](#6-相关文档) | |
| 30 | + | |
| 31 | +--- | |
| 32 | + | |
| 33 | +## 1. 快速上手 | |
| 34 | + | |
| 35 | +### 1.1 环境准备 | |
| 36 | + | |
| 37 | +```bash | |
| 38 | +source activate.sh | |
| 39 | +# 首次推荐: | |
| 40 | +./scripts/create_venv.sh | |
| 41 | +# 或使用 conda: | |
| 42 | +# conda env create -f environment.yml | |
| 43 | +``` | |
| 44 | + | |
| 45 | +依赖:Python 3.8+、Elasticsearch 8.x、MySQL、Redis(可选,缓存用途)。 | |
| 46 | + | |
| 47 | +如果需要本地运行 embedding 模型(torch/transformers 等重依赖): | |
| 8 | 48 | |
| 9 | 49 | ```bash |
| 50 | +INSTALL_ML=1 ./scripts/create_venv.sh | |
| 10 | 51 | source activate.sh |
| 11 | -# 首次:./scripts/create_venv.sh 或 conda env create -f environment.yml | |
| 12 | 52 | ``` |
| 13 | 53 | |
| 14 | -依赖:Python 3.8+、Elasticsearch 8.x、MySQL、Redis(可选)。详见 `docs/环境配置说明.md`。 | |
| 54 | +详细环境说明见 `docs/环境配置说明.md`。 | |
| 15 | 55 | |
| 16 | -## 2. 服务与端口 | |
| 56 | +### 1.2 服务与端口 | |
| 17 | 57 | |
| 18 | 58 | | 服务 | 端口 | 默认启动 | 说明 | |
| 19 | 59 | |------|-----:|:--------:|------| |
| 20 | -| backend | 6002 | ✓ | 搜索 API | | |
| 21 | -| indexer | 6004 | ✓ | 索引 API | | |
| 60 | +| backend | 6002 | ✓ | 搜索 API(`/search/*`)+ 管理接口(`/admin/*`) | | |
| 61 | +| indexer | 6004 | ✓ | 索引 API(`/indexer/*`) | | |
| 22 | 62 | | frontend | 6003 | ✓ | 调试 UI | |
| 23 | -| embedding | 6005 | - | 向量服务 | | |
| 24 | -| translator | 6006 | - | 翻译服务 | | |
| 25 | -| reranker | 6007 | - | 重排服务 | | |
| 63 | +| embedding | 6005 | - | 向量服务(`/embed/text`, `/embed/image`) | | |
| 64 | +| translator | 6006 | - | 翻译服务(`/translate`) | | |
| 65 | +| reranker | 6007 | - | 重排服务(`/rerank`) | | |
| 66 | + | |
| 67 | +启动与停止: | |
| 26 | 68 | |
| 27 | 69 | ```bash |
| 28 | 70 | ./run.sh |
| 29 | -# 全功能:START_EMBEDDING=1 START_TRANSLATOR=1 START_RERANKER=1 ./run.sh | |
| 71 | +# 启动全部能力 | |
| 72 | +START_EMBEDDING=1 START_TRANSLATOR=1 START_RERANKER=1 ./run.sh | |
| 73 | + | |
| 30 | 74 | ./scripts/service_ctl.sh status |
| 31 | 75 | ./scripts/stop.sh |
| 32 | 76 | ``` |
| 33 | 77 | |
| 34 | -## 3. 模块与请求 | |
| 78 | +### 1.3 常用 API 请求示例 | |
| 35 | 79 | |
| 36 | -### 3.1 搜索 API(backend 6002) | |
| 80 | +#### 搜索 API(backend 6002) | |
| 37 | 81 | |
| 38 | 82 | ```bash |
| 39 | 83 | # 文本搜索 |
| ... | ... | @@ -48,77 +92,285 @@ curl -X POST http://localhost:6002/search/image \ |
| 48 | 92 | -H "X-Tenant-ID: 162" \ |
| 49 | 93 | -d '{"image_url": "https://example.com/img.jpg", "size": 10}' |
| 50 | 94 | |
| 51 | -# 建议 | |
| 52 | -curl "http://localhost:6002/search/suggestions?q=玩&size=5" -H "X-Tenant-ID: 162" | |
| 95 | +# Suggestion | |
| 96 | +curl "http://localhost:6002/search/suggestions?q=玩&size=5" \ | |
| 97 | + -H "X-Tenant-ID: 162" | |
| 98 | + | |
| 99 | +# 健康与统计 | |
| 100 | +curl http://localhost:6002/admin/health | |
| 101 | +curl http://localhost:6002/admin/stats | |
| 53 | 102 | ``` |
| 54 | 103 | |
| 55 | -API 文档:http://localhost:6002/docs | |
| 104 | +API 文档:`http://localhost:6002/docs` | |
| 56 | 105 | |
| 57 | -### 3.2 索引 API(indexer 6004) | |
| 106 | +#### 索引 API(indexer 6004) | |
| 58 | 107 | |
| 59 | 108 | ```bash |
| 60 | 109 | # 创建租户索引 |
| 61 | 110 | ./scripts/create_tenant_index.sh 162 |
| 62 | 111 | |
| 63 | -# 全量索引 | |
| 112 | +# 全量重建(更新/写入,不删除旧索引) | |
| 64 | 113 | curl -X POST http://localhost:6004/indexer/reindex \ |
| 65 | 114 | -H "Content-Type: application/json" \ |
| 66 | 115 | -d '{"tenant_id": "162", "batch_size": 500}' |
| 67 | 116 | |
| 68 | -# 构建文档(不写 ES,供上游调用) | |
| 117 | +# 增量索引 | |
| 118 | +curl -X POST http://localhost:6004/indexer/index \ | |
| 119 | + -H "Content-Type: application/json" \ | |
| 120 | + -d '{"tenant_id": "162", "spu_ids": ["1001", "1002"]}' | |
| 121 | + | |
| 122 | +# 构建文档(不写 ES) | |
| 69 | 123 | curl -X POST http://localhost:6004/indexer/build-docs \ |
| 70 | 124 | -H "Content-Type: application/json" \ |
| 71 | - -d '{"tenant_id": "162", "items": [{"spu": {...}, "skus": [...], "options": [...]}]}' | |
| 125 | + -d '{"tenant_id":"162","items":[{"spu":{},"skus":[],"options":[]}]}' | |
| 72 | 126 | ``` |
| 73 | 127 | |
| 74 | -### 3.3 向量服务(embedding 6005) | |
| 128 | +API 文档:`http://localhost:6004/docs` | |
| 129 | + | |
| 130 | +#### Embedding 服务(6005) | |
| 75 | 131 | |
| 76 | 132 | ```bash |
| 77 | 133 | ./scripts/start_embedding_service.sh |
| 78 | 134 | |
| 79 | -# 文本向量 | |
| 80 | 135 | curl -X POST http://localhost:6005/embed/text \ |
| 81 | 136 | -H "Content-Type: application/json" \ |
| 82 | 137 | -d '["衣服", "Bohemian Maxi Dress"]' |
| 83 | 138 | |
| 84 | -# 图片向量(URL 列表) | |
| 85 | 139 | curl -X POST http://localhost:6005/embed/image \ |
| 86 | 140 | -H "Content-Type: application/json" \ |
| 87 | 141 | -d '["https://example.com/img.jpg"]' |
| 88 | 142 | ``` |
| 89 | 143 | |
| 90 | -### 3.4 翻译服务(translator 6006) | |
| 144 | +#### Translator 服务(6006) | |
| 91 | 145 | |
| 92 | 146 | ```bash |
| 93 | 147 | ./scripts/start_translator.sh |
| 94 | 148 | |
| 95 | 149 | curl -X POST http://localhost:6006/translate \ |
| 96 | 150 | -H "Content-Type: application/json" \ |
| 97 | - -d '{"text": "商品名称", "target_lang": "en", "source_lang": "zh"}' | |
| 151 | + -d '{"text":"商品名称","target_lang":"en","source_lang":"zh"}' | |
| 98 | 152 | ``` |
| 99 | 153 | |
| 100 | -### 3.5 重排服务(reranker 6007) | |
| 154 | +#### Reranker 服务(6007) | |
| 101 | 155 | |
| 102 | 156 | ```bash |
| 103 | 157 | ./scripts/start_reranker.sh |
| 104 | 158 | |
| 105 | 159 | curl -X POST http://localhost:6007/rerank \ |
| 106 | 160 | -H "Content-Type: application/json" \ |
| 107 | - -d '{"query": "wireless mouse", "docs": ["logitech mx master", "usb cable"]}' | |
| 161 | + -d '{"query":"wireless mouse","docs":["logitech mx master","usb cable"]}' | |
| 162 | +``` | |
| 163 | + | |
| 164 | +### 1.4 配置入口总览 | |
| 165 | + | |
| 166 | +- **搜索行为配置**:`config/config.yaml` | |
| 167 | +- **索引结构定义**:`mappings/search_products.json` | |
| 168 | +- **provider/服务配置**:`config/config.yaml` 的 `services` 块 | |
| 169 | +- **环境变量**:`.env` | |
| 170 | + | |
| 171 | +--- | |
| 172 | + | |
| 173 | +## 2. 基础配置与搜索行为 | |
| 174 | + | |
| 175 | +### 2.1 总体原则 | |
| 176 | + | |
| 177 | +- **统一索引结构**:所有租户使用同一套 mapping(按租户数据分索引名 + 文档内 `tenant_id` 隔离) | |
| 178 | +- **SPU 级索引**:每个文档是一个 SPU,包含嵌套 `skus`、`specifications` | |
| 179 | +- **配置文件驱动**:搜索权重、搜索域、重排融合、provider 全在 `config/config.yaml`,不再以“硬编码配置”为主 | |
| 180 | + | |
| 181 | +### 2.2 索引结构(Mapping) | |
| 182 | + | |
| 183 | +文件:`mappings/search_products.json` | |
| 184 | + | |
| 185 | +核心字段可分为: | |
| 186 | + | |
| 187 | +- 标识字段:`tenant_id`, `spu_id` | |
| 188 | +- 多语言文本:`title.zh/en`, `brief.zh/en`, `description.zh/en`, `vendor.zh/en`, `category_path.zh/en`, `category_name_text.zh/en` | |
| 189 | +- 类目过滤:`category1_name`, `category2_name`, `category3_name` 等 | |
| 190 | +- 规格/变体:`specifications`(nested)、`skus`(nested) | |
| 191 | +- 价格库存:`min_price`, `max_price`, `total_inventory` 等 | |
| 192 | +- 向量:`title_embedding`(dense vector)、`image_embedding`(nested) | |
| 193 | + | |
| 194 | +### 2.3 查询、权重、排序(`config/config.yaml`) | |
| 195 | + | |
| 196 | +- `field_boosts`:字段权重(如标题、品牌、类目) | |
| 197 | +- `indexes`:搜索域(default/title/vendor/category/tags) | |
| 198 | +- `query_config`:语言、embedding 开关、source_fields、knn_boost、翻译提示词等 | |
| 199 | +- `ranking.expression`:融合表达式(例如 `bm25() + 0.25*text_embedding_relevance()`) | |
| 200 | +- `function_score`:ES 层加权函数 | |
| 201 | +- `rerank`:重排窗口、超时、ES/AI 融合权重 | |
| 202 | + | |
| 203 | +### 2.4 分面与返回字段 | |
| 204 | + | |
| 205 | +- 分面字段通常包括:`category1_name`、`category2_name`、`category3_name`、`specifications.*` | |
| 206 | +- `query_config.source_fields` 控制返回字段(`null`=全部,`[]`=不返回 source,列表=指定字段) | |
| 207 | +- 多语言返回遵循请求 language 与字段回退策略 | |
| 208 | + | |
| 209 | +### 2.5 修改配置时怎么做 | |
| 210 | + | |
| 211 | +| 修改项 | 操作 | | |
| 212 | +|--------|------| | |
| 213 | +| 索引结构(mapping) | 修改 `mappings/search_products.json` → `./scripts/create_tenant_index.sh <tenant_id>` → 重新导入 | | |
| 214 | +| 搜索域/权重/排序/重排 | 修改 `config/config.yaml` 对应块 | | |
| 215 | +| provider 与服务 URL | 修改 `config/config.yaml` 的 `services` 块,或用环境变量覆盖 | | |
| 216 | + | |
| 217 | +--- | |
| 218 | + | |
| 219 | +## 3. Provider 架构 | |
| 220 | + | |
| 221 | +目标:调用方稳定、配置可切换、单一配置源。 | |
| 222 | + | |
| 223 | +### 3.1 当前代码结构 | |
| 224 | + | |
| 225 | +- 模块:`providers/` | |
| 226 | +- 工厂:`create_translation_provider()`、`create_embedding_provider()`、`create_rerank_provider()` | |
| 227 | +- 配置解析:`config/services_config.py` | |
| 228 | + | |
| 229 | +| 能力 | Provider 实现 | 调用方 | | |
| 230 | +|------|---------------|--------| | |
| 231 | +| translation | `providers/translation.py`(direct/http) | `query/query_parser.py`、索引链路 | | |
| 232 | +| embedding | `providers/embedding.py`(http) | 文本/图像编码调用 | | |
| 233 | +| rerank | `providers/rerank.py`(http) | `search/rerank_client.py` | | |
| 234 | + | |
| 235 | +### 3.2 配置与覆盖 | |
| 236 | + | |
| 237 | +统一在 `config/config.yaml`: | |
| 238 | + | |
| 239 | +```yaml | |
| 240 | +services: | |
| 241 | + translation: | |
| 242 | + provider: "direct" | |
| 243 | + providers: | |
| 244 | + direct: { model: "qwen" } | |
| 245 | + http: { base_url: "http://127.0.0.1:6006", model: "qwen", timeout_sec: 10.0 } | |
| 246 | + embedding: | |
| 247 | + provider: "http" | |
| 248 | + providers: | |
| 249 | + http: { base_url: "http://127.0.0.1:6005" } | |
| 250 | + rerank: | |
| 251 | + provider: "http" | |
| 252 | + providers: | |
| 253 | + http: { base_url: "http://127.0.0.1:6007", service_url: "http://127.0.0.1:6007/rerank" } | |
| 254 | +``` | |
| 255 | + | |
| 256 | +环境变量覆盖(优先级更高): | |
| 257 | + | |
| 258 | +- `TRANSLATION_PROVIDER` | |
| 259 | +- `TRANSLATION_SERVICE_URL` | |
| 260 | +- `EMBEDDING_SERVICE_URL` | |
| 261 | +- `RERANKER_SERVICE_URL` | |
| 262 | +- `RERANK_BACKEND`(服务内后端) | |
| 263 | + | |
| 264 | +### 3.3 新增 provider 的最小步骤 | |
| 265 | + | |
| 266 | +1. 在 `providers/<capability>.py` 实现 provider 类 | |
| 267 | +2. 在 `create_*_provider()` 注册 | |
| 268 | +3. 在 `config/config.yaml` 的 `services.<capability>.providers` 新增配置 | |
| 269 | + | |
| 270 | +--- | |
| 271 | + | |
| 272 | +## 4. 模块扩展规范(Embedding / Rerank) | |
| 273 | + | |
| 274 | +这里重点区分两层: | |
| 275 | + | |
| 276 | +- **Provider 层(调用方式)**:调用方如何访问能力(http/direct) | |
| 277 | +- **Backend 层(推理实现)**:服务进程内部具体模型实现(bge / qwen3_vllm / ...) | |
| 278 | + | |
| 279 | +### 4.1 Rerank(重排)扩展 | |
| 280 | + | |
| 281 | +调用链: | |
| 282 | + | |
| 283 | +`search/rerank_client.py` -> `create_rerank_provider()` -> `HttpRerankProvider` -> `POST /rerank` | |
| 284 | + | |
| 285 | +服务实现: | |
| 286 | + | |
| 287 | +- `reranker/server.py` | |
| 288 | +- `reranker/backends/__init__.py`(工厂) | |
| 289 | +- `reranker/backends/bge.py` | |
| 290 | +- `reranker/backends/qwen3_vllm.py` | |
| 291 | + | |
| 292 | +后端协议(服务内): | |
| 293 | + | |
| 294 | +- 实现 `score_with_meta(query, docs, normalize) -> (scores, meta)` | |
| 295 | +- 返回 `scores` 与输入 `docs` 等长且顺序一致 | |
| 296 | + | |
| 297 | +配置位置: | |
| 298 | + | |
| 299 | +`config/config.yaml` -> `services.rerank.backend` + `services.rerank.backends.<name>` | |
| 300 | + | |
| 301 | +### 4.2 Embedding(向量化)扩展 | |
| 302 | + | |
| 303 | +调用链: | |
| 304 | + | |
| 305 | +`create_embedding_provider()` -> `POST /embed/text` / `POST /embed/image` | |
| 306 | + | |
| 307 | +服务实现: | |
| 308 | + | |
| 309 | +- `embeddings/server.py`(文本和图像可独立加载) | |
| 310 | +- 文本后端现用 BGE | |
| 311 | +- 图像后端支持本地 CLIP 或 clip-as-service | |
| 312 | + | |
| 313 | +扩展建议: | |
| 314 | + | |
| 315 | +- 文本后端统一提供批量编码能力(与输入索引对齐) | |
| 316 | +- 图像后端实现 `ImageEncoderProtocol`(`encode_image_urls`) | |
| 317 | +- 如后续后端增多,建议与 rerank 一样在 `services.embedding.backend(s)` 统一配置 | |
| 318 | + | |
| 319 | +### 4.3 新增后端检查清单(以 `qwen3_vllm` 为例) | |
| 320 | + | |
| 321 | +1. 实现后端协议(服务内) | |
| 322 | +2. 在后端工厂注册(如 `get_rerank_backend`) | |
| 323 | +3. 增加 `config/config.yaml` 对应 backend 配置 | |
| 324 | +4. 提供健康检查中的 backend/model 可观测信息 | |
| 325 | +5. 保持外部 HTTP 契约不变,调用方无需改造 | |
| 326 | + | |
| 327 | +--- | |
| 328 | + | |
| 329 | +## 5. 验证、日志与常见排障入口 | |
| 330 | + | |
| 331 | +### 5.1 快速健康检查 | |
| 332 | + | |
| 333 | +```bash | |
| 334 | +curl http://localhost:6002/health | |
| 335 | +curl http://localhost:6002/admin/health | |
| 336 | +curl http://localhost:6004/health | |
| 337 | +curl http://localhost:6005/health | |
| 338 | +curl http://localhost:6006/health | |
| 339 | +curl http://localhost:6007/health | |
| 340 | +``` | |
| 341 | + | |
| 342 | +### 5.2 常看日志 | |
| 343 | + | |
| 344 | +- `logs/backend.log` | |
| 345 | +- `logs/indexer.log` | |
| 346 | +- `logs/frontend.log` | |
| 347 | +- `logs/embedding.log` | |
| 348 | +- `logs/translator.log` | |
| 349 | +- `logs/reranker.log` | |
| 350 | +- `logs/search_engine.log` | |
| 351 | +- `logs/errors.log` | |
| 352 | + | |
| 353 | +### 5.3 常用排障命令 | |
| 354 | + | |
| 355 | +```bash | |
| 356 | +./scripts/service_ctl.sh status | |
| 357 | +curl http://localhost:9200 | |
| 358 | +lsof -i :6002 | |
| 359 | +lsof -i :6004 | |
| 108 | 360 | ``` |
| 109 | 361 | |
| 110 | -## 4. 配置 | |
| 362 | +更完整的运行排障(多环境切换、Suggestion 构建、FAQ)见 `docs/Usage-Guide.md`。 | |
| 111 | 363 | |
| 112 | -- **主配置**:`config/config.yaml`(搜索行为、字段权重、分面等) | |
| 113 | -- **服务 provider**:`config/config.yaml` 的 `services` 块(翻译/向量/重排的 provider 与 URL) | |
| 114 | -- **环境变量**:`.env`(DB、ES、Redis、API Key 等) | |
| 364 | +--- | |
| 115 | 365 | |
| 116 | -## 5. 延伸阅读 | |
| 366 | +## 6. 相关文档 | |
| 117 | 367 | |
| 118 | 368 | | 文档 | 用途 | |
| 119 | 369 | |------|------| |
| 120 | -| `docs/Usage-Guide.md` | 运维:日志、多环境、故障排查 | | |
| 370 | +| `docs/DEVELOPER_GUIDE.md` | 项目全貌、规范、协作方式 | | |
| 371 | +| `docs/Usage-Guide.md` | 运行运维手册:日志、多环境、故障排查、Suggestion 运维 | | |
| 121 | 372 | | `docs/搜索API速查表.md` | 搜索 API 参数速查 | |
| 122 | 373 | | `docs/搜索API对接指南.md` | 搜索 API 完整说明 | |
| 123 | -| `docs/PROVIDER_ARCHITECTURE.md` | 翻译/向量/重排 provider 扩展 | | |
| 124 | 374 | | `indexer/README.md` | 索引模块职责与接口 | |
| 375 | +| `embeddings/README.md` | 向量化服务说明 | | |
| 376 | +| `reranker/README.md` | 重排服务说明 | | ... | ... |
docs/Usage-Guide.md
| 1 | -# 使用指南 - saas-search | |
| 1 | +# 使用指南 - saas-search(运行与运维) | |
| 2 | 2 | |
| 3 | -本文档提供完整的使用指南,包括环境准备、服务启动、配置说明、日志查看等。 | |
| 3 | +本文档聚焦运行与运维:服务启动/停止、日志查看、多环境切换、故障排查、Suggestion 索引运维。 | |
| 4 | + | |
| 5 | +开发与配置(环境入口、配置体系、Provider 架构、模块扩展规范)请优先阅读 `docs/QUICKSTART.md`。 | |
| 4 | 6 | |
| 5 | 7 | ## 目录 |
| 6 | 8 | |
| ... | ... | @@ -79,15 +81,15 @@ DB_PASSWORD=your_password |
| 79 | 81 | # Elasticsearch配置 |
| 80 | 82 | ES_HOST=http://localhost:9200 |
| 81 | 83 | ES_USERNAME=essa |
| 82 | -ES_PASSWORD=4hOaLaf41y2VuI8y | |
| 84 | +ES_PASSWORD=your_es_password | |
| 83 | 85 | |
| 84 | 86 | # Redis配置(可选,用于缓存) |
| 85 | 87 | REDIS_HOST=localhost |
| 86 | 88 | REDIS_PORT=6479 |
| 87 | -REDIS_PASSWORD=BMfv5aI31kgHWtlx | |
| 89 | +REDIS_PASSWORD=your_redis_password | |
| 88 | 90 | |
| 89 | 91 | # DeepL翻译API(可选) |
| 90 | -DEEPL_AUTH_KEY=c9293ab4-ad25-479b-919f-ab4e63b429ed | |
| 92 | +DEEPL_AUTH_KEY=your_deepl_auth_key | |
| 91 | 93 | |
| 92 | 94 | # 运行环境(用于区分 prod / uat / test / dev) |
| 93 | 95 | RUNTIME_ENV=prod |
| ... | ... | @@ -263,7 +265,7 @@ python -m http.server 6003 |
| 263 | 265 | # Elasticsearch配置 |
| 264 | 266 | ES_HOST=http://localhost:9200 |
| 265 | 267 | ES_USERNAME=essa |
| 266 | -ES_PASSWORD=4hOaLaf41y2VuI8y | |
| 268 | +ES_PASSWORD=your_es_password | |
| 267 | 269 | |
| 268 | 270 | # MySQL配置 |
| 269 | 271 | DB_HOST=120.79.247.228 |
| ... | ... | @@ -275,10 +277,10 @@ DB_PASSWORD=your_password |
| 275 | 277 | # Redis配置(可选,用于缓存) |
| 276 | 278 | REDIS_HOST=localhost |
| 277 | 279 | REDIS_PORT=6479 |
| 278 | -REDIS_PASSWORD=BMfv5aI31kgHWtlx | |
| 280 | +REDIS_PASSWORD=your_redis_password | |
| 279 | 281 | |
| 280 | 282 | # DeepL翻译API |
| 281 | -DEEPL_AUTH_KEY=c9293ab4-ad25-479b-919f-ab4e63b429ed | |
| 283 | +DEEPL_AUTH_KEY=your_deepl_auth_key | |
| 282 | 284 | |
| 283 | 285 | # API服务配置 |
| 284 | 286 | API_HOST=0.0.0.0 | ... | ... |
docs/基础配置指南.md
| 1 | -# 基础配置指南 | |
| 1 | +# 基础配置指南(已并入) | |
| 2 | 2 | |
| 3 | -## 概述 | |
| 3 | +本文档内容已并入 `docs/QUICKSTART.md`,请直接查看: | |
| 4 | 4 | |
| 5 | -搜索引擎采用**统一硬编码配置**方案,所有租户共享相同的索引结构和查询配置,无需单独配置。 | |
| 5 | +- `docs/QUICKSTART.md` -> **2. 基础配置与搜索行为** | |
| 6 | 6 | |
| 7 | -## 核心特性 | |
| 7 | +说明: | |
| 8 | 8 | |
| 9 | -- **统一索引结构**: 所有租户共享 `search_products` 索引 | |
| 10 | -- **硬编码配置**: 索引 mapping 和查询配置直接硬编码在代码中,无需配置文件 | |
| 11 | -- **SPU级别索引**: 每个ES文档代表一个SPU,包含嵌套的 `skus` 和 `specifications` 数组 | |
| 12 | -- **租户隔离**: 通过 `tenant_id` 字段实现数据隔离 | |
| 13 | -- **多语言支持**: 文本字段支持中英文双语,后端根据 `language` 参数自动选择 | |
| 9 | +- 历史版本中“统一硬编码配置”的描述已过时。 | |
| 10 | +- 当前搜索行为与 provider 配置以 `config/config.yaml` 为主,索引结构在 `mappings/search_products.json`。 | |
| 14 | 11 | |
| 15 | -## 索引结构 | |
| 16 | - | |
| 17 | -### Mapping 文件位置 | |
| 18 | - | |
| 19 | -`mappings/search_products.json` | |
| 20 | - | |
| 21 | -### 主要字段 | |
| 22 | - | |
| 23 | -#### 基础标识 | |
| 24 | -- `tenant_id` (keyword) - 租户ID(必需,用于隔离) | |
| 25 | -- `spu_id` (keyword) - SPU ID | |
| 26 | -- `create_time`, `update_time` (date) - 时间字段 | |
| 27 | - | |
| 28 | -#### 多语言文本字段 | |
| 29 | -- `title.zh`, `title.en` (text) - 标题(中英文) | |
| 30 | -- `brief.zh`, `brief.en` (text) - 短描述(中英文) | |
| 31 | -- `description.zh`, `description.en` (text) - 详细描述(中英文) | |
| 32 | -- `vendor.zh`, `vendor.en` (text) - 供应商/品牌(中英文,含keyword子字段) | |
| 33 | -- `category_path.zh`, `category_path.en` (text) - 类目路径(中英文) | |
| 34 | -- `category_name_text.zh`, `category_name_text.en` (text) - 类目名称(中英文) | |
| 35 | - | |
| 36 | -#### 类目字段 | |
| 37 | -- `category_id` (keyword) - 类目ID | |
| 38 | -- `category_name` (keyword) - 类目名称 | |
| 39 | -- `category_level` (integer) - 类目层级 | |
| 40 | -- `category1_name`, `category2_name`, `category3_name` (keyword) - 多级类目 | |
| 41 | - | |
| 42 | -#### 规格和选项 | |
| 43 | -- `specifications` (nested) - 规格列表(name, value, sku_id) | |
| 44 | -- `option1_name`, `option2_name`, `option3_name` (keyword) - 选项名称 | |
| 45 | - | |
| 46 | -#### 价格和库存 | |
| 47 | -- `min_price`, `max_price`, `compare_at_price` (float) - 价格字段 | |
| 48 | -- `sku_prices` (float) - SKU价格列表(数组) | |
| 49 | -- `sku_weights` (long) - SKU重量列表(数组) | |
| 50 | -- `sku_weight_units` (keyword) - SKU重量单位列表(数组) | |
| 51 | -- `total_inventory` (long) - 总库存 | |
| 52 | - | |
| 53 | -#### 嵌套字段 | |
| 54 | -- `skus` (nested) - SKU详细信息数组 | |
| 55 | -- `image_embedding` (nested) - 图片向量(仅用于搜索) | |
| 56 | - | |
| 57 | -#### 其他 | |
| 58 | -- `tags` (keyword) - 标签列表(数组) | |
| 59 | -- `image_url` (keyword, index: false) - 主图URL | |
| 60 | -- `title_embedding` (dense_vector) - 标题向量(仅用于搜索,不返回) | |
| 61 | - | |
| 62 | -## 查询配置 | |
| 63 | - | |
| 64 | -### 文本召回字段 | |
| 65 | - | |
| 66 | -默认同时搜索以下字段(中英文都包含): | |
| 67 | -- `title.zh^3.0`, `title.en^3.0` | |
| 68 | -- `brief.zh^1.5`, `brief.en^1.5` | |
| 69 | -- `description.zh^1.0`, `description.en^1.0` | |
| 70 | -- `vendor.zh^1.5`, `vendor.en^1.5` | |
| 71 | -- `category_path.zh^1.5`, `category_path.en^1.5` | |
| 72 | -- `category_name_text.zh^1.5`, `category_name_text.en^1.5` | |
| 73 | -- `tags^1.0` | |
| 74 | - | |
| 75 | -### 查询架构 | |
| 76 | - | |
| 77 | -**结构**: `filters AND (text_recall OR embedding_recall)` | |
| 78 | - | |
| 79 | -- **filters**: 前端传递的过滤条件(永远起作用) | |
| 80 | -- **text_recall**: 文本相关性召回(同时搜索中英文字段) | |
| 81 | -- **embedding_recall**: 向量召回(KNN,使用 `title_embedding`),根据 query_tokens 自适应调整 k、num_candidates、boost(详见 `docs/相关性检索优化说明.md` 3.6 节) | |
| 82 | -- **function_score**: 包装召回部分,支持提权字段 | |
| 83 | - | |
| 84 | -### Function Score 配置 | |
| 85 | - | |
| 86 | -位置: `search/query_config.py` 中的 `FUNCTION_SCORE_CONFIG` | |
| 87 | - | |
| 88 | -支持的类型: | |
| 89 | -- `filter_weight`: 条件权重(如新品提权) | |
| 90 | -- `field_value_factor`: 字段值因子(如销量因子) | |
| 91 | -- `decay`: 衰减函数(如时间衰减) | |
| 92 | - | |
| 93 | -## 分面配置 | |
| 94 | - | |
| 95 | -### 默认分面字段 | |
| 96 | - | |
| 97 | -- `category1_name` - 一级类目 | |
| 98 | -- `category2_name` - 二级类目 | |
| 99 | -- `category3_name` - 三级类目 | |
| 100 | -- `specifications` - 规格分面(嵌套聚合,按name分组,然后按value聚合) | |
| 101 | - | |
| 102 | -### 规格分面说明 | |
| 103 | - | |
| 104 | -`specifications` 使用特殊的嵌套聚合: | |
| 105 | -- 按 `specifications.name` 分组(如"color"、"size") | |
| 106 | -- 每个 `name` 下按 `specifications.value` 聚合(如"white"、"black") | |
| 107 | - | |
| 108 | -返回格式: | |
| 109 | -```json | |
| 110 | -{ | |
| 111 | - "field": "specifications.color", | |
| 112 | - "label": "color", | |
| 113 | - "type": "terms", | |
| 114 | - "values": [ | |
| 115 | - {"value": "white", "count": 50}, | |
| 116 | - {"value": "black", "count": 30} | |
| 117 | - ] | |
| 118 | -} | |
| 119 | -``` | |
| 120 | - | |
| 121 | -## 返回字段映射 | |
| 122 | - | |
| 123 | -后端根据请求的 `language` 参数(`zh` 或 `en`)自动选择对应的中英文字段: | |
| 124 | - | |
| 125 | -- `language="zh"`: 优先返回 `*_zh` 字段,如果为空则回退到 `*_en` 字段 | |
| 126 | -- `language="en"`: 优先返回 `*_en` 字段,如果为空则回退到 `*_zh` 字段 | |
| 127 | - | |
| 128 | -映射规则: | |
| 129 | -- `title.zh/en` → `title` | |
| 130 | -- `brief.zh/en` → `brief` | |
| 131 | -- `description.zh/en` → `description` | |
| 132 | -- `vendor.zh/en` → `vendor` | |
| 133 | -- `category_path.zh/en` → `category_path` | |
| 134 | -- `category_name_text.zh/en` → `category_name` | |
| 135 | - | |
| 136 | -## 配置修改 | |
| 137 | - | |
| 138 | -### 修改索引结构 | |
| 139 | - | |
| 140 | -编辑 `mappings/search_products.json`,然后: | |
| 141 | -1. 重建租户索引结构: `./scripts/create_tenant_index.sh <tenant_id>` | |
| 142 | -2. 重新导入数据: `POST /indexer/reindex` | |
| 143 | - | |
| 144 | -### 修改查询配置 | |
| 145 | - | |
| 146 | -编辑 `search/query_config.py`: | |
| 147 | -- `DEFAULT_MATCH_FIELDS`: 文本召回字段列表 | |
| 148 | -- `FUNCTION_SCORE_CONFIG`: Function score 配置 | |
| 149 | -- `DEFAULT_FACETS`: 默认分面字段 | |
| 150 | - | |
| 151 | -### 修改返回字段 | |
| 152 | - | |
| 153 | -编辑 `search/query_config.py` 中的 `SOURCE_FIELDS` 列表。 | |
| 154 | - | |
| 155 | -## 注意事项 | |
| 156 | - | |
| 157 | -1. **无需配置文件**: 所有配置都是硬编码的,不需要为每个租户创建配置文件 | |
| 158 | -2. **统一结构**: 所有租户共享相同的索引结构和查询逻辑 | |
| 159 | -3. **多租户隔离**: 所有查询必须包含 `tenant_id` 过滤条件 | |
| 160 | -4. **向量字段**: `title_embedding` 和 `image_embedding` 仅用于搜索,不会返回给前端 | |
| 161 | - | |
| 162 | -## 相关文档 | |
| 163 | - | |
| 164 | -- `索引字段说明v2.md` - 详细的字段说明 | |
| 165 | -- `搜索API对接指南.md` - API使用说明 | |
| 166 | -- `mappings/search_products.json` - 索引 mapping 定义 | |
| 12 | +保留此文件仅用于兼容历史链接。 | ... | ... |
main.py
| ... | ... | @@ -30,7 +30,7 @@ def cmd_serve(args): |
| 30 | 30 | os.environ['ES_HOST'] = args.es_host |
| 31 | 31 | |
| 32 | 32 | print("Starting API service (multi-tenant)...") |
| 33 | - print(f" Host: {args.host}:{args.port} (search + indexer routes)") | |
| 33 | + print(f" Host: {args.host}:{args.port} (search + admin routes)") | |
| 34 | 34 | print(f" Elasticsearch: {args.es_host}") |
| 35 | 35 | |
| 36 | 36 | uvicorn.run( | ... | ... |