docs(api): rewrite markdown to match current routes

Refs #890 #1049 #1168.

按集成方视角全量审计 17 个 API markdown 文档与 internal/router/router.go
对齐。每个端点新增参数说明小节(path/query/body 字段含义)和响应字段
含义说明(#1168 的核心诉求)。

【与代码对齐】
- 删除已下线端点:system.md 中的 /system/minio/buckets(代码中已无对
  应路由)。
- 修正路径错误:chunk.md 中 /chunks/get-by-id/:id → /chunks/by-id/:id;
  /chunks/:id/delete-question → /chunks/by-id/:id/questions;
  organization.md 中 /organizations/preview/:invite_code → :code。
- 修正字段类型:faq tag_id / entry_id 由 string 改为 int64;
  knowledge.search 响应结构纠正。
- 补齐缺失端点(move-targets、batch-delete、move/progress、pin/unpin/
  stop/continue-stream、tool-approvals、organization agent-shares 等
  30+ 条)。

【精简】
- knowledge-base.md / model.md 把重复 5 次 / 3 次的完整对象样例
  收敛为指向首次出现("字段结构同 POST /xxx 响应"),节省约 400 行
  而不损失信息(仅去重,原作者写的每个字段定义都保留可达)。
- 示例 X-API-Key 统一为 sk-xxxxx(避免读者复制看似真实的 key)。

【清理】
- 删除内部实现细节引用:mcp-service.md 中 6 处 "issue #1173"、
  organization.md 中 "RegisterOrganizationRoutes" 等。

不动 initialization.md:其中端点(KB 配置、模型连通性测试、Ollama 管理)
对集成方有实用价值,保留原作者写好的内容不删。

格式统一遵循 web-search.md 重写后的范式(路由表 + 每端点方法/路径 +
参数表 + curl + 响应 JSON + 字段说明)。
This commit is contained in:
nullkey
2026-05-11 17:37:14 +08:00
committed by lyingbug
parent 54b6f2dc35
commit 1c7171b2c6
17 changed files with 3312 additions and 2393 deletions

View File

@@ -6,6 +6,8 @@
智能体 API 用于管理自定义智能体Custom Agent。系统提供了内置智能体同时支持用户创建自定义智能体来满足不同的业务场景需求。
> 智能体的共享与跨组织分发(`/agents/:id/shares` 等)属于组织协作能力,文档见 [组织管理 API](./organization.md)。本文件只覆盖智能体自身的 CRUD、复制、占位符、类型预设以及推荐问题接口。
### 内置智能体
系统默认提供以下内置智能体:
@@ -25,27 +27,36 @@
## API 列表
| 方法 | 路径 | 描述 |
|------|------|------|
| POST | `/agents` | 创建智能体 |
| GET | `/agents` | 获取智能体列表 |
| GET | `/agents/:id` | 获取智能体详情 |
| PUT | `/agents/:id` | 更新智能体 |
| DELETE | `/agents/:id` | 删除智能体 |
| POST | `/agents/:id/copy` | 复制智能体 |
| GET | `/agents/placeholders` | 获取占位符定义 |
| 方法 | 路径 | 描述 |
| ------ | -------------------------- | -------------------------- |
| POST | `/agents` | 创建智能体 |
| GET | `/agents` | 获取智能体列表 |
| GET | `/agents/:id` | 获取智能体详情 |
| PUT | `/agents/:id` | 更新智能体 |
| DELETE | `/agents/:id` | 删除智能体 |
| POST | `/agents/:id/copy` | 复制智能体 |
| GET | `/agents/placeholders` | 获取占位符定义 |
---
## POST `/agents` - 创建智能体
创建新的自定义智能体。
创建新的自定义智能体。成功返回 HTTP 201。
**请求体参数**:
| 参数 | 类型 | 必填 | 说明 |
| ------------- | ------ | ---- | ------------------------------------------------- |
| `name` | string | 是 | 智能体名称 |
| `description` | string | 否 | 智能体描述 |
| `avatar` | string | 否 | 头像emoji 或图标名称) |
| `config` | object | 否 | 智能体配置,详见 [配置参数](#配置参数) |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/agents' \
--header 'X-API-Key: your_api_key' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"name": "我的智能体",
@@ -64,15 +75,6 @@ curl --location 'http://localhost:8080/api/v1/agents' \
}'
```
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `name` | string | 是 | 智能体名称 |
| `description` | string | 否 | 智能体描述 |
| `avatar` | string | 否 | 智能体头像emoji 或图标名称) |
| `config` | object | 否 | 智能体配置,详见 [配置参数](#配置参数) |
**响应**:
```json
@@ -100,22 +102,22 @@ curl --location 'http://localhost:8080/api/v1/agents' \
**错误响应**:
| 状态码 | 错误码 | 错误 | 说明 |
|--------|--------|------|------|
| 400 | 1000 | Bad Request | 请求参数错误或智能体名称为空 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
| 状态码 | 错误码 | 错误 | 说明 |
| ------ | ------ | --------------------- | --------------------------------- |
| 400 | 1000 | Bad Request | 请求参数错误或智能体名称为空 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
---
## GET `/agents` - 获取智能体列表
获取当前租户的所有智能体,包括内置智能体和自定义智能体。
获取当前租户的所有智能体,包括内置智能体和自定义智能体。响应中额外返回 `disabled_own_agent_ids`,指示当前租户在前端对话下拉框中主动隐藏的本租户自有智能体 ID 列表(不影响其他租户)。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/agents' \
--header 'X-API-Key: your_api_key'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
@@ -134,78 +136,54 @@ curl --location 'http://localhost:8080/api/v1/agents' \
"created_by": "",
"config": {
"agent_mode": "quick-answer",
"system_prompt": "你是一个专业的智能信息检索助手名为WeKnora。你犹如专业的高级秘书依据检索到的信息回答用户问题不能利用任何先验知识。\n当用户提出问题时助手会基于特定的信息进行解答。助手首先在心中思考推理过程然后向用户提供答案。\n",
"context_template": "...",
"model_id": "...",
"rerank_model_id": "",
"temperature": 0.3,
"max_completion_tokens": 2048,
"max_iterations": 10,
"allowed_tools": [],
"reflection_enabled": false,
"mcp_selection_mode": "",
"mcp_services": null,
"kb_selection_mode": "all",
"knowledge_bases": [],
"supported_file_types": null,
"faq_priority_enabled": false,
"faq_direct_answer_threshold": 0,
"faq_score_boost": 0,
"web_search_enabled": false,
"web_search_max_results": 5,
"multi_turn_enabled": true,
"history_turns": 5,
"embedding_top_k": 10,
"keyword_threshold": 0.3,
"vector_threshold": 0.5,
"rerank_top_k": 5,
"rerank_threshold": 0.5,
"enable_query_expansion": true,
"enable_rewrite": true,
"rewrite_prompt_system": "...",
"rewrite_prompt_user": "...",
"fallback_strategy": "fixed",
"fallback_response": "...",
"fallback_prompt": "..."
"history_turns": 5
},
"created_at": "2025-12-29T20:06:01.696308+08:00",
"updated_at": "2025-12-29T20:06:01.696308+08:00",
"deleted_at": null
},
{
"id": "builtin-smart-reasoning",
"name": "智能推理",
"description": "ReAct 推理框架,支持多步思考和工具调用",
"is_builtin": true,
"config": {
"agent_mode": "smart-reasoning"
}
},
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "我的智能体",
"description": "自定义智能体描述",
"is_builtin": false,
"config": {
"agent_mode": "smart-reasoning"
}
}
]
],
"disabled_own_agent_ids": []
}
```
**错误响应**:
| 状态码 | 错误码 | 错误 | 说明 |
| ------ | ------ | --------------------- | ------------------ |
| 401 | 1001 | Unauthorized | 缺少租户上下文 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
---
## GET `/agents/:id` - 获取智能体详情
根据 ID 获取智能体的详细信息。
**路径参数**:
| 参数 | 类型 | 说明 |
| ---- | ------ | -------- |
| `id` | string | 智能体 ID |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/agents/builtin-quick-answer' \
--header 'X-API-Key: your_api_key'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
@@ -238,23 +216,38 @@ curl --location 'http://localhost:8080/api/v1/agents/builtin-quick-answer' \
**错误响应**:
| 状态码 | 错误码 | 错误 | 说明 |
|--------|--------|------|------|
| 400 | 1000 | Bad Request | 智能体 ID 为空 |
| 404 | 1003 | Not Found | 智能体不存在 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
| 状态码 | 错误码 | 错误 | 说明 |
| ------ | ------ | --------------------- | ------------------ |
| 400 | 1000 | Bad Request | 智能体 ID 为空 |
| 404 | 1003 | Not Found | 智能体不存在 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
---
## PUT `/agents/:id` - 更新智能体
更新智能体的名称、描述和配置。内置智能体不可修改。
更新智能体的名称、描述、头像和配置。内置智能体不可修改。
**路径参数**:
| 参数 | 类型 | 说明 |
| ---- | ------ | -------- |
| `id` | string | 智能体 ID |
**请求体参数**:
| 参数 | 类型 | 必填 | 说明 |
| ------------- | ------ | ---- | ------------ |
| `name` | string | 否 | 智能体名称 |
| `description` | string | 否 | 智能体描述 |
| `avatar` | string | 否 | 智能体头像 |
| `config` | object | 否 | 智能体配置 |
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/agents/550e8400-e29b-41d4-a716-446655440000' \
--header 'X-API-Key: your_api_key' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"name": "更新后的智能体",
@@ -267,15 +260,6 @@ curl --location --request PUT 'http://localhost:8080/api/v1/agents/550e8400-e29b
}'
```
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `name` | string | 否 | 智能体名称 |
| `description` | string | 否 | 智能体描述 |
| `avatar` | string | 否 | 智能体头像 |
| `config` | object | 否 | 智能体配置 |
**响应**:
```json
@@ -297,12 +281,12 @@ curl --location --request PUT 'http://localhost:8080/api/v1/agents/550e8400-e29b
**错误响应**:
| 状态码 | 错误码 | 错误 | 说明 |
|--------|--------|------|------|
| 400 | 1000 | Bad Request | 请求参数错误或智能体名称为空 |
| 403 | 1002 | Forbidden | 无法修改内置智能体的基本信息 |
| 404 | 1003 | Not Found | 智能体不存在 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
| 状态码 | 错误码 | 错误 | 说明 |
| ------ | ------ | --------------------- | --------------------------------- |
| 400 | 1000 | Bad Request | 请求参数错误或智能体名称为空 |
| 403 | 1002 | Forbidden | 无法修改内置智能体 |
| 404 | 1003 | Not Found | 智能体不存在 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
---
@@ -310,11 +294,17 @@ curl --location --request PUT 'http://localhost:8080/api/v1/agents/550e8400-e29b
删除指定的自定义智能体。内置智能体不可删除。
**路径参数**:
| 参数 | 类型 | 说明 |
| ---- | ------ | -------- |
| `id` | string | 智能体 ID |
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/agents/550e8400-e29b-41d4-a716-446655440000' \
--header 'X-API-Key: your_api_key'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
@@ -328,24 +318,30 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/agents/550e8400-e
**错误响应**:
| 状态码 | 错误码 | 错误 | 说明 |
|--------|--------|------|------|
| 400 | 1000 | Bad Request | 智能体 ID 为空 |
| 403 | 1002 | Forbidden | 无法删除内置智能体 |
| 404 | 1003 | Not Found | 智能体不存在 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
| 状态码 | 错误码 | 错误 | 说明 |
| ------ | ------ | --------------------- | --------------------- |
| 400 | 1000 | Bad Request | 智能体 ID 为空 |
| 403 | 1002 | Forbidden | 无法删除内置智能体 |
| 404 | 1003 | Not Found | 智能体不存在 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
---
## POST `/agents/:id/copy` - 复制智能体
复制指定的智能体,创建一个新的副本。支持复制内置智能体
复制指定的智能体,创建一个新的副本,副本始终为自定义智能体。支持复制内置智能体。成功返回 HTTP 201
**路径参数**:
| 参数 | 类型 | 说明 |
| ---- | ------ | -------------- |
| `id` | string | 源智能体 ID |
**请求**:
```curl
curl --location --request POST 'http://localhost:8080/api/v1/agents/builtin-smart-reasoning/copy' \
--header 'X-API-Key: your_api_key'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
@@ -370,11 +366,11 @@ curl --location --request POST 'http://localhost:8080/api/v1/agents/builtin-smar
**错误响应**:
| 状态码 | 错误码 | 错误 | 说明 |
|--------|--------|------|------|
| 400 | 1000 | Bad Request | 智能体 ID 为空 |
| 404 | 1003 | Not Found | 智能体不存在 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
| 状态码 | 错误码 | 错误 | 说明 |
| ------ | ------ | --------------------- | ------------------ |
| 400 | 1000 | Bad Request | 智能体 ID 为空 |
| 404 | 1003 | Not Found | 智能体不存在 |
| 500 | 1007 | Internal Server Error | 服务器内部错误 |
---
@@ -523,7 +519,7 @@ curl --location 'http://localhost:8080/api/v1/agents/placeholders' \
```curl
curl --location 'http://localhost:8080/api/v1/agent-chat/session-123' \
--header 'X-API-Key: your_api_key' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"query": "帮我分析一下这份数据",
@@ -531,3 +527,9 @@ curl --location 'http://localhost:8080/api/v1/agent-chat/session-123' \
"agent_id": "builtin-data-analyst"
}'
```
## 相关文档
- 智能体的组织共享、跨租户分发与禁用(`/agents/:id/shares``/shared-agents` 等):见 [组织管理 API](./organization.md)
- 智能体绑定 IM 渠道(`/agents/:id/im-channels`):见组织/IM 渠道相关文档
- 网络搜索提供者配置(被 `web_search_provider_id` 引用):见 [Web Search API](./web-search.md)

View File

@@ -2,22 +2,35 @@
[返回目录](./README.md)
| 方法 | 路径 | 描述 |
| ------ | --------------------------- | ------------------------ |
| GET | `/chunks/:knowledge_id` | 获取知识的分块列表 |
| PUT | `/chunks/:knowledge_id/:id` | 更新分块 |
| DELETE | `/chunks/:knowledge_id/:id` | 删除分块 |
| DELETE | `/chunks/:knowledge_id` | 删除知识下的所有分块 |
| GET | `/chunks/get-by-id/:id` | 根据ID直接获取分块 |
| DELETE | `/chunks/:id/delete-question` | 删除分块生成问题 |
| 方法 | 路径 | 描述 |
| ------ | --------------------------------- | -------------------------- |
| GET | `/chunks/:knowledge_id` | 获取知识的分块列表 |
| PUT | `/chunks/:knowledge_id/:id` | 更新分块 |
| DELETE | `/chunks/:knowledge_id/:id` | 删除单个分块 |
| DELETE | `/chunks/:knowledge_id` | 删除知识下的所有分块 |
| GET | `/chunks/by-id/:id` | 根据分块 ID 直接获取分块 |
| DELETE | `/chunks/by-id/:id/questions` | 删除分块下的某个生成问题 |
## GET `/chunks/:knowledge_id?page=&page_size=` - 获取知识的分块列表
## GET `/chunks/:knowledge_id` - 获取知识的分块列表
**路径参数**:
| 字段 | 类型 | 说明 |
| ------------- | ------ | ----------- |
| knowledge_id | string | 知识 ID |
**查询参数**:
| 字段 | 类型 | 默认 | 说明 |
| ---------- | ---- | ---- | ---------- |
| page | int | 1 | 页码 |
| page_size | int | 20 | 每页条数 |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/chunks/4c4e7c1a-09cf-485b-a7b5-24b8cdc5acf5?page=1&page_size=1' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
@@ -61,21 +74,31 @@ curl --location 'http://localhost:8080/api/v1/chunks/4c4e7c1a-09cf-485b-a7b5-24b
## PUT `/chunks/:knowledge_id/:id` - 更新分块
更新指定分块的内容和属性。
更新指定分块的内容和属性。所有字段均可选,未传则保留原值。
**请求参数**:
- `content`: 分块内容(可选)
- `chunk_index`: 分块索引(可选)
- `is_enabled`: 是否启用(可选)
- `start_at`: 起始位置(可选)
- `end_at`: 结束位置(可选)
- `image_info`: 图片信息(可选)
**路径参数**:
| 字段 | 类型 | 说明 |
| ------------- | ------ | ----------- |
| knowledge_id | string | 知识 ID |
| id | string | 分块 ID |
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ------------ | ------- | ---- | --------------------- |
| content | string | 否 | 分块内容 |
| chunk_index | int | 否 | 分块在知识中的序号 |
| is_enabled | boolean | 否 | 是否启用 |
| start_at | int | 否 | 起始位置(字符偏移) |
| end_at | int | 否 | 结束位置(字符偏移) |
| image_info | string | 否 | 图像分块的元信息JSON 字符串) |
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/chunks/4c4e7c1a-09cf-485b-a7b5-24b8cdc5acf5/df10b37d-cd05-4b14-ba8a-e1bd0eb3bbd7' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"content": "更新后的分块内容",
@@ -89,41 +112,23 @@ curl --location --request PUT 'http://localhost:8080/api/v1/chunks/4c4e7c1a-09cf
{
"data": {
"id": "df10b37d-cd05-4b14-ba8a-e1bd0eb3bbd7",
"tenant_id": 1,
"knowledge_id": "4c4e7c1a-09cf-485b-a7b5-24b8cdc5acf5",
"knowledge_base_id": "kb-00000001",
"tag_id": "",
"content": "更新后的分块内容",
"chunk_index": 0,
"is_enabled": true,
"status": 2,
"start_at": 0,
"end_at": 964,
"pre_chunk_id": "",
"next_chunk_id": "",
"chunk_type": "text",
"parent_chunk_id": "",
"relation_chunks": null,
"indirect_relation_chunks": null,
"metadata": null,
"content_hash": "",
"image_info": "",
"created_at": "2025-08-12T11:52:36.168632+08:00",
"updated_at": "2025-08-12T12:00:00.000000+08:00",
"deleted_at": null
"...": "其他字段同 GET 响应"
},
"success": true
}
```
## DELETE `/chunks/:knowledge_id/:id` - 删除分块
## DELETE `/chunks/:knowledge_id/:id` - 删除单个分块
**路径参数**: 同 PUT。
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/chunks/4c4e7c1a-09cf-485b-a7b5-24b8cdc5acf5/df10b37d-cd05-4b14-ba8a-e1bd0eb3bbd7' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'Content-Type: application/json'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
@@ -137,12 +142,17 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/chunks/4c4e7c1a-0
## DELETE `/chunks/:knowledge_id` - 删除知识下的所有分块
**路径参数**:
| 字段 | 类型 | 说明 |
| ------------- | ------ | ----------- |
| knowledge_id | string | 知识 ID |
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/chunks/4c4e7c1a-09cf-485b-a7b5-24b8cdc5acf5' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'Content-Type: application/json'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
@@ -154,60 +164,46 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/chunks/4c4e7c1a-0
}
```
## GET `/chunks/get-by-id/:id` - 根据ID直接获取分块
## GET `/chunks/by-id/:id` - 根据 ID 直接获取分块
根据分块ID直接获取分块信息无需提供知识ID
无需提供 `knowledge_id` 即可获取分块。常用于跨知识库的引用展示
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | ------- |
| id | string | 分块 ID |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/chunks/get-by-id/df10b37d-cd05-4b14-ba8a-e1bd0eb3bbd7' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'Content-Type: application/json'
curl --location 'http://localhost:8080/api/v1/chunks/by-id/df10b37d-cd05-4b14-ba8a-e1bd0eb3bbd7' \
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
**响应**:`GET /chunks/:knowledge_id` 列表中的单条 data。
```json
{
"data": {
"id": "df10b37d-cd05-4b14-ba8a-e1bd0eb3bbd7",
"tenant_id": 1,
"knowledge_id": "4c4e7c1a-09cf-485b-a7b5-24b8cdc5acf5",
"knowledge_base_id": "kb-00000001",
"tag_id": "",
"content": "彗星xxxx",
"chunk_index": 0,
"is_enabled": true,
"status": 2,
"start_at": 0,
"end_at": 964,
"pre_chunk_id": "",
"next_chunk_id": "",
"chunk_type": "text",
"parent_chunk_id": "",
"relation_chunks": null,
"indirect_relation_chunks": null,
"metadata": null,
"content_hash": "",
"image_info": "",
"created_at": "2025-08-12T11:52:36.168632+08:00",
"updated_at": "2025-08-12T11:52:53.376871+08:00",
"deleted_at": null
},
"success": true
}
```
## DELETE `/chunks/by-id/:id/questions` - 删除分块下的某个生成问题
## DELETE `/chunks/:id/delete-question` - 删除分块的生成问题
删除指定分块关联的某条生成问题
删除指定分块关联的生成问题。
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | ------- |
| id | string | 分块 ID |
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------- | ------ | ---- | ----------- |
| question_id | string | 是 | 问题 ID |
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/chunks/df10b37d-cd05-4b14-ba8a-e1bd0eb3bbd7/delete-question' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
curl --location --request DELETE 'http://localhost:8080/api/v1/chunks/by-id/df10b37d-cd05-4b14-ba8a-e1bd0eb3bbd7/questions' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"question_id": "q-00000001"

View File

@@ -2,22 +2,26 @@
[返回目录](./README.md)
| 方法 | 路径 | 描述 |
| ---- | ------------- | --------------------- |
| GET | `/evaluation` | 获取评估任务 |
| POST | `/evaluation` | 创建评估任务 |
| 方法 | 路径 | 描述 |
| ---- | -------------- | --------------------- |
| GET | `/evaluation/` | 获取评估任务结果 |
| POST | `/evaluation/` | 创建评估任务 |
## GET `/evaluation` - 获取评估任务
> 服务端路由带尾斜杠Gin 会自动从 `/evaluation` 重定向到 `/evaluation/`),下方示例为方便阅读用了 `/evaluation`。
**请求参数**:
- `task_id`: 从 `POST /evaluation` 接口中获取到的任务 ID
- `X-API-Key`: 用户 API Key
## GET `/evaluation` - 获取评估任务结果
**参数说明(查询参数)**:
| 字段 | 类型 | 必填 | 说明 |
| -------- | ------ | ---- | --------------------------------------------------- |
| task_id | string | 是 | 从 `POST /evaluation` 返回的任务 ID |
**请求**:
```bash
curl --location 'http://localhost:8080/api/v1/evaluation?task_id=c34563ad-b09f-4858-b72e-e92beb80becb' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
@@ -88,17 +92,20 @@ curl --location 'http://localhost:8080/api/v1/evaluation?task_id=c34563ad-b09f-4
## POST `/evaluation` - 创建评估任务
**请求参数**:
- `dataset_id`: 评估使用的数据集,暂时只支持官方测试数据集 `default`
- `knowledge_base_id`: 评估使用的知识库
- `chat_id`: 评估使用的对话模型
- `rerank_id`: 评估使用的重排序模型
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------------- | ------ | ---- | ----------------------------------------------- |
| dataset_id | string | 是 | 评估数据集,目前仅支持 `default`(官方测试集) |
| knowledge_base_id | string | 是 | 评估使用的知识库 ID |
| chat_id | string | 是 | 评估使用的对话模型 ID |
| rerank_id | string | 是 | 评估使用的重排序模型 ID |
**请求**:
```bash
curl --location 'http://localhost:8080/api/v1/evaluation' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"dataset_id": "default",

View File

@@ -2,55 +2,54 @@
[返回目录](./README.md)
| 方法 | 路径 | 描述 |
| ------ | ------------------------------------------- | ------------------------ |
| GET | `/knowledge-bases/:id/faq/entries` | 获取FAQ条目列表 |
| POST | `/knowledge-bases/:id/faq/entries` | 批量导入FAQ条目 |
| POST | `/knowledge-bases/:id/faq/entry` | 创建单个FAQ条目 |
| GET | `/knowledge-bases/:id/faq/entries/:entry_id`| 获取单个FAQ条目 |
| PUT | `/knowledge-bases/:id/faq/entries/:entry_id`| 更新单个FAQ条目 |
| POST | `/knowledge-bases/:id/faq/entries/:entry_id/similar-questions` | 添加相似问题 |
| PUT | `/knowledge-bases/:id/faq/entries/fields` | 批量更新FAQ字段 |
| PUT | `/knowledge-bases/:id/faq/entries/tags` | 批量更新FAQ标签 |
| DELETE | `/knowledge-bases/:id/faq/entries` | 批量删除FAQ条目 |
| POST | `/knowledge-bases/:id/faq/search` | 混合搜索FAQ |
| GET | `/knowledge-bases/:id/faq/entries/export` | 导出FAQ条目(CSV) |
| GET | `/faq/import/progress/:task_id` | 获取FAQ导入进度 |
| PUT | `/knowledge-bases/:id/faq/import/last-result/display` | 更新导入结果显示状态 |
FAQ 接口分为两组:
## GET `/knowledge-bases/:id/faq/entries` - 获取FAQ条目列表
- `/knowledge-bases/:id/faq/*`:知识库范围内的 FAQ 条目 CRUD、批量操作、搜索与导入导出。
- `/faq/import/progress/:task_id`**不属于知识库分组**,用于查询异步导入/dry-run 任务的进度,仅需任务 ID 即可调用。
| 方法 | 路径 | 描述 |
| ------ | ----------------------------------------------------------------- | --------------------------------- |
| GET | `/knowledge-bases/:id/faq/entries` | 获取 FAQ 条目列表 |
| GET | `/knowledge-bases/:id/faq/entries/export` | 导出 FAQ 条目CSV |
| GET | `/knowledge-bases/:id/faq/entries/:entry_id` | 获取单个 FAQ 条目(按 seq_id |
| POST | `/knowledge-bases/:id/faq/entries` | 批量 Upsert FAQ 条目(异步) |
| POST | `/knowledge-bases/:id/faq/entry` | 同步创建单个 FAQ 条目 |
| PUT | `/knowledge-bases/:id/faq/entries/:entry_id` | 更新单个 FAQ 条目 |
| POST | `/knowledge-bases/:id/faq/entries/:entry_id/similar-questions` | 为 FAQ 条目追加相似问 |
| PUT | `/knowledge-bases/:id/faq/entries/fields` | 批量更新字段(启用/推荐/标签) |
| PUT | `/knowledge-bases/:id/faq/entries/tags` | 批量更新标签 |
| DELETE | `/knowledge-bases/:id/faq/entries` | 批量删除 FAQ 条目 |
| POST | `/knowledge-bases/:id/faq/search` | FAQ 混合搜索 |
| PUT | `/knowledge-bases/:id/faq/import/last-result/display` | 更新上次导入结果卡片显示状态 |
| GET | `/faq/import/progress/:task_id` | 查询 FAQ 导入任务进度(公共) |
> **路径参数说明**`:entry_id` 始终是 FAQ 条目的 `seq_id`(整数),不是字符串形式的 ID。同理批量接口中的 `by_id` / `by_tag` / `exclude_ids` / `ids` 字段均为 `seq_id` 列表(整数)。
## GET `/knowledge-bases/:id/faq/entries` - 获取 FAQ 条目列表
支持分页、按标签过滤、关键字搜索与排序。
**查询参数**:
- `page`: 页码(默认 1
- `page_size`: 每页条数(默认 20
- `tag_id`: 按标签ID筛选可选
- `keyword`: 关键字搜索(可选)
- `search_field`: 搜索字段(可选),可选值:
- `standard_question`: 只搜索标准问题
- `similar_questions`: 只搜索相似问法
- `answers`: 只搜索答案
- 留空或不传:搜索全部字段
- `sort_order`: 排序方式(可选),`asc` 表示按更新时间正序,默认按更新时间倒序
| 参数 | 类型 | 必填 | 说明 |
| ------------ | ------ | ---- | --------------------------------------------------------------------------------------------- |
| page | int | 否 | 页码,默认 1 |
| page_size | int | 否 | 每页数量,默认 20 |
| tag_id | int | 否 | 按标签 `seq_id` 过滤 |
| keyword | string | 否 | 关键字搜索 |
| search_field | string | 否 | 搜索字段:`standard_question` / `similar_questions` / `answers`,留空则全字段搜索 |
| sort_order | string | 否 | 排序方式,`asc` 表示按更新时间正序,默认按更新时间倒序 |
**请求**:
```curl
# 搜索全部字段
# 全字段搜索
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries?page=1&page_size=10&keyword=密码' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'Content-Type: application/json'
--header 'X-API-Key: sk-xxxxx'
# 搜索标准问
# 搜索标准问
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries?keyword=密码&search_field=standard_question' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ'
# 只搜索相似问法
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries?keyword=忘记&search_field=similar_questions' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ'
# 只搜索答案
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries?keyword=点击&search_field=answers' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
@@ -63,16 +62,19 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/en
"page_size": 10,
"data": [
{
"id": "faq-00000001",
"id": 1,
"chunk_id": "chunk-00000001",
"knowledge_id": "knowledge-00000001",
"knowledge_base_id": "kb-00000001",
"tag_id": "tag-00000001",
"tag_id": 12,
"tag_name": "账户",
"is_enabled": true,
"is_recommended": false,
"standard_question": "如何重置密码?",
"similar_questions": ["忘记密码怎么办", "密码找回"],
"negative_questions": ["如何修改用户名"],
"answers": ["您可以通过点击登录页面的'忘记密码'链接来重置密码。"],
"answer_strategy": "all",
"index_mode": "hybrid",
"chunk_type": "faq",
"created_at": "2025-08-12T10:00:00+08:00",
@@ -84,18 +86,94 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/en
}
```
## POST `/knowledge-bases/:id/faq/entries` - 批量导入FAQ条目
## GET `/knowledge-bases/:id/faq/entries/export` - 导出 FAQ 条目
**请求参数**:
- `mode`: 导入模式,`append`(追加)或 `replace`(替换)
- `entries`: FAQ条目数组
- `knowledge_id`: 关联的知识ID可选
将知识库下的所有 FAQ 条目导出为 CSVUTF-8 带 BOMExcel 兼容)。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries/export' \
--header 'X-API-Key: sk-xxxxx' \
--output faq_export.csv
```
**响应**: `Content-Type: text/csv; charset=utf-8`,附带文件名 `faq_export.csv`
## GET `/knowledge-bases/:id/faq/entries/:entry_id` - 获取单个 FAQ 条目
根据 `seq_id`(整数)获取单个 FAQ 条目详情。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries/1' \
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
```json
{
"data": {
"id": 1,
"chunk_id": "chunk-00000001",
"knowledge_id": "knowledge-00000001",
"knowledge_base_id": "kb-00000001",
"tag_id": 12,
"tag_name": "账户",
"is_enabled": true,
"is_recommended": false,
"standard_question": "如何重置密码?",
"similar_questions": ["忘记密码怎么办", "密码找回"],
"negative_questions": [],
"answers": ["您可以通过点击登录页面的'忘记密码'链接来重置密码。"],
"answer_strategy": "all",
"index_mode": "hybrid",
"chunk_type": "faq",
"created_at": "2025-08-12T10:00:00+08:00",
"updated_at": "2025-08-12T10:00:00+08:00"
},
"success": true
}
```
## POST `/knowledge-bases/:id/faq/entries` - 批量 Upsert FAQ 条目(异步)
**异步**批量导入或更新 FAQ 条目。接口立即返回 `task_id`,调用方需通过 `GET /faq/import/progress/:task_id` 查询进度与结果。
支持 `dry_run=true`:异步执行仅校验(格式 / 批内重复 / 与库内重复 / 内容安全),不实际写入。
**请求体(`types.FAQBatchUpsertPayload`**:
| 字段 | 类型 | 必填 | 说明 |
| ------------ | -------------------------- | ---- | ----------------------------------------------------------------------------------- |
| entries | `[]FAQEntryPayload` | 是 | FAQ 条目数组 |
| mode | string | 是 | `append``replace`(替换会清空已有条目) |
| knowledge_id | string | 否 | 关联的 FAQ Knowledge ID不传则使用知识库默认 FAQ knowledge |
| task_id | string | 否 | 任务 ID不传则自动生成 UUID |
| dry_run | boolean | 否 | 仅验证不导入 |
`FAQEntryPayload` 字段:
| 字段 | 类型 | 必填 | 说明 |
| ------------------- | --------- | ---- | ------------------------------------------------------------- |
| id | int64 | 否 | 指定 `seq_id`(数据迁移场景,需小于自增起始值 100000000 |
| standard_question | string | 是 | 标准问 |
| similar_questions | string[] | 否 | 相似问列表 |
| negative_questions | string[] | 否 | 反例问题列表 |
| answers | string[] | 否 | 答案列表 |
| answer_strategy | string | 否 | 答案返回策略:`all``random` |
| tag_id | int64 | 否 | 标签 `seq_id` |
| tag_name | string | 否 | 标签名(用于按名匹配标签) |
| is_enabled | boolean | 否 | 是否启用 |
| is_recommended | boolean | 否 | 是否推荐 |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"mode": "append",
@@ -104,7 +182,7 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/en
"standard_question": "如何联系客服?",
"similar_questions": ["客服电话", "在线客服"],
"answers": ["您可以通过拨打400-xxx-xxxx联系我们的客服。"],
"tag_id": "tag-00000001"
"tag_id": 1
},
{
"standard_question": "退款政策是什么?",
@@ -118,38 +196,30 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/en
```json
{
"data": {
"task_id": "task-00000001"
},
"data": { "task_id": "task-00000001" },
"success": true
}
```
批量导入为异步操作返回任务ID用于追踪进度
> 用 `GET /faq/import/progress/:task_id` 查询任务最终状态
## POST `/knowledge-bases/:id/faq/entry` - 创建单个FAQ条目
## POST `/knowledge-bases/:id/faq/entry` - 同步创建单个 FAQ 条目
同步创建单FAQ条目适用于单条录入场景。会自动检查标准问相似问是否与已有FAQ重复。
**同步**创建单FAQ 条目,会即时校验标准问/相似问与库内已有条目的重复。
**请求参数**:
- `standard_question`: 标准问(必填)
- `similar_questions`: 相似问数组(可选)
- `negative_questions`: 反例问题数组(可选)
- `answers`: 答案数组(必填)
- `tag_id`: 标签ID可选
- `is_enabled`: 是否启用可选默认true
**请求**: 同上 `FAQEntryPayload``standard_question` 必填)。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entry' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"standard_question": "如何联系客服?",
"similar_questions": ["客服电话", "在线客服"],
"answers": ["您可以通过拨打400-xxx-xxxx联系我们的客服。"],
"tag_id": "tag-00000001",
"tag_id": 1,
"is_enabled": true
}'
```
@@ -159,16 +229,19 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/en
```json
{
"data": {
"id": "faq-00000001",
"id": 1,
"chunk_id": "chunk-00000001",
"knowledge_id": "knowledge-00000001",
"knowledge_base_id": "kb-00000001",
"tag_id": "tag-00000001",
"tag_id": 1,
"tag_name": "客服",
"is_enabled": true,
"is_recommended": false,
"standard_question": "如何联系客服?",
"similar_questions": ["客服电话", "在线客服"],
"negative_questions": [],
"answers": ["您可以通过拨打400-xxx-xxxx联系我们的客服。"],
"answer_strategy": "all",
"index_mode": "hybrid",
"chunk_type": "faq",
"created_at": "2025-08-12T10:00:00+08:00",
@@ -190,13 +263,15 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/en
}
```
## PUT `/knowledge-bases/:id/faq/entries/:entry_id` - 更新单个FAQ条目
## PUT `/knowledge-bases/:id/faq/entries/:entry_id` - 更新单个 FAQ 条目
`seq_id` 更新单条 FAQ 条目,请求体同 `FAQEntryPayload`
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries/faq-00000001' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries/1' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"standard_question": "如何重置账户密码?",
@@ -206,107 +281,61 @@ curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-0
}'
```
**响应**:
**响应**: 返回更新后的 FAQ 条目,结构同创建接口。
```json
{
"success": true
}
```
## POST `/knowledge-bases/:id/faq/entries/:entry_id/similar-questions` - 追加相似问
## GET `/knowledge-bases/:id/faq/entries/:entry_id` - 获取单个FAQ条目
向指定 FAQ 条目(`seq_id`)追加相似问。
根据 seq_id 获取单个 FAQ 条目的详细信息。
**请求体**:
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries/1' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'Content-Type: application/json'
```
**响应**:
```json
{
"data": {
"id": "faq-00000001",
"seq_id": 1,
"chunk_id": "chunk-00000001",
"knowledge_id": "knowledge-00000001",
"knowledge_base_id": "kb-00000001",
"tag_id": "tag-00000001",
"is_enabled": true,
"standard_question": "如何重置密码?",
"similar_questions": ["忘记密码怎么办", "密码找回"],
"negative_questions": [],
"answers": ["您可以通过点击登录页面的'忘记密码'链接来重置密码。"],
"index_mode": "hybrid",
"chunk_type": "faq",
"created_at": "2025-08-12T10:00:00+08:00",
"updated_at": "2025-08-12T10:00:00+08:00"
},
"success": true
}
```
## POST `/knowledge-bases/:id/faq/entries/:entry_id/similar-questions` - 添加相似问题
为指定的 FAQ 条目追加相似问法。
**请求参数**:
- `similar_questions`: 要追加的相似问题数组(必填)
| 字段 | 类型 | 必填 | 说明 |
| ----------------- | -------- | ---- | --------------------- |
| similar_questions | string[] | 是 | 要追加的相似问数组 |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries/1/similar-questions' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"similar_questions": ["怎样修改密码", "密码重置方法"]
}'
```
**响应**:
**响应**: 返回追加后的完整 FAQ 条目。
```json
{
"data": {
"id": "faq-00000001",
"seq_id": 1,
"standard_question": "如何重置密码?",
"similar_questions": ["忘记密码怎么办", "密码找回", "怎样修改密码", "密码重置方法"],
"answers": ["您可以通过点击登录页面的'忘记密码'链接来重置密码。"],
"is_enabled": true,
"chunk_type": "faq",
"created_at": "2025-08-12T10:00:00+08:00",
"updated_at": "2025-08-12T11:00:00+08:00"
},
"success": true
}
```
## PUT `/knowledge-bases/:id/faq/entries/fields` - 批量更新字段
## PUT `/knowledge-bases/:id/faq/entries/fields` - 批量更新FAQ字段
**统一**的批量字段更新接口,支持同时更新 `is_enabled` / `is_recommended` / `tag_id`,并支持两种作用域:
支持按条目ID或按标签ID批量更新 FAQ 条目的多个字段(启用状态、推荐状态、标签等)
- **按条目 ID** (`by_id`):键为条目 `seq_id`,值为该条目要更新的字段
- **按标签 ID** (`by_tag`):键为标签 `seq_id`,对该标签下的所有条目应用相同的字段更新;可配合 `exclude_ids` 排除部分条目。
**请求参数**:
- `by_id`: 按条目 seq_id 更新(可选),键为 seq_id值为要更新的字段
- `by_tag`: 按标签 seq_id 更新(可选),键为 tag_seq_id值为要更新的字段
- `exclude_ids`: 排除的条目 seq_id 列表(与 by_tag 配合使用,可选)
`by_id``by_tag` 至少传一项;二者可同时使用。
每个更新对象支持的字段:
- `is_enabled`: 是否启用(可选)
- `is_recommended`: 是否推荐(可选)
- `tag_id`: 标签ID可选
**请求体(`types.FAQEntryFieldsBatchUpdate`**:
| 字段 | 类型 | 必填 | 说明 |
| ----------- | --------------------------------- | ---- | ------------------------------------------ |
| by_id | `map[int64]FAQEntryFieldsUpdate` | 否 | 按条目 `seq_id` 更新 |
| by_tag | `map[int64]FAQEntryFieldsUpdate` | 否 | 按标签 `seq_id` 对该标签下所有条目更新 |
| exclude_ids | `int64[]` | 否 | 与 `by_tag` 配合使用,排除指定条目 `seq_id` |
`FAQEntryFieldsUpdate` 字段(全部可选,仅传入的字段会被更新):
| 字段 | 类型 | 说明 |
| -------------- | ------- | -------------- |
| is_enabled | boolean | 是否启用 |
| is_recommended | boolean | 是否推荐 |
| tag_id | int64 | 标签 `seq_id` |
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries/fields' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"by_id": {
@@ -314,7 +343,7 @@ curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-0
"2": {"is_enabled": false}
},
"by_tag": {
"100": {"is_enabled": true}
"100": {"is_recommended": true}
},
"exclude_ids": [3, 4]
}'
@@ -323,76 +352,92 @@ curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-0
**响应**:
```json
{
"success": true
}
{ "success": true }
```
## PUT `/knowledge-bases/:id/faq/entries/tags` - 批量更新FAQ标签
## PUT `/knowledge-bases/:id/faq/entries/tags` - 批量更新标签
仅更新标签关联。键为条目 `seq_id`,值为目标标签 `seq_id`;值传 `null` 表示清除标签。
**请求体**:
| 字段 | 类型 | 必填 | 说明 |
| ------- | --------------------- | ---- | -------------------------------------------- |
| updates | `map[int64]int64?` | 是 | 键:条目 `seq_id`;值:标签 `seq_id``null` |
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries/tags' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"updates": {
"faq-00000001": "tag-00000001",
"faq-00000002": "tag-00000002",
"faq-00000003": null
"1": 10,
"2": 11,
"3": null
}
}'
```
注:设置为 `null` 可清除标签关联。
**响应**:
```json
{
"success": true
}
{ "success": true }
```
## DELETE `/knowledge-bases/:id/faq/entries` - 批量删除FAQ条目
## DELETE `/knowledge-bases/:id/faq/entries` - 批量删除
**请求体**:
| 字段 | 类型 | 必填 | 说明 |
| ---- | --------- | ---- | --------------------------------- |
| ids | `int64[]` | 是 | 要删除的 FAQ 条目 `seq_id` 列表 |
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"ids": ["faq-00000001", "faq-00000002"]
"ids": [1, 2, 3]
}'
```
**响应**:
```json
{
"success": true
}
{ "success": true }
```
## POST `/knowledge-bases/:id/faq/search` - 混合搜索FAQ
## POST `/knowledge-bases/:id/faq/search` - FAQ 混合搜索
**请求参数**:
- `query_text`: 搜索查询文本
- `vector_threshold`: 向量相似度阈值0-1
- `match_count`: 返回结果数量最大200
向量 + 关键字混合检索,支持两级优先级标签召回。
**请求体(`types.FAQSearchRequest`**:
| 字段 | 类型 | 必填 | 说明 |
| ----------------------- | --------- | ---- | ----------------------------------------------------------------------------------- |
| query_text | string | 是 | 搜索文本 |
| vector_threshold | float | 否 | 向量相似度阈值01 |
| match_count | int | 否 | 返回数量,默认 10最大 200 |
| first_priority_tag_ids | `int64[]` | 否 | 第一优先级标签 `seq_id` 列表(最高优先召回范围) |
| second_priority_tag_ids | `int64[]` | 否 | 第二优先级标签 `seq_id` 列表 |
| only_recommended | boolean | 否 | 是否仅返回 `is_recommended=true` 的条目 |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/search' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"query_text": "如何重置密码",
"vector_threshold": 0.5,
"match_count": 10
"match_count": 10,
"first_priority_tag_ids": [12],
"only_recommended": false
}'
```
@@ -402,18 +447,22 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/se
{
"data": [
{
"id": "faq-00000001",
"id": 1,
"chunk_id": "chunk-00000001",
"knowledge_id": "knowledge-00000001",
"knowledge_base_id": "kb-00000001",
"tag_id": "tag-00000001",
"tag_id": 12,
"tag_name": "账户",
"is_enabled": true,
"is_recommended": false,
"standard_question": "如何重置密码?",
"similar_questions": ["忘记密码怎么办", "密码找回"],
"answers": ["您可以通过点击登录页面的'忘记密码'链接来重置密码。"],
"answer_strategy": "all",
"chunk_type": "faq",
"score": 0.95,
"match_type": "vector",
"matched_question": "忘记密码怎么办",
"created_at": "2025-08-12T10:00:00+08:00",
"updated_at": "2025-08-12T10:00:00+08:00"
}
@@ -422,81 +471,92 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/se
}
```
## GET `/knowledge-bases/:id/faq/entries/export` - 导出FAQ条目
## PUT `/knowledge-bases/:id/faq/import/last-result/display` - 更新上次导入结果显示状态
将知识库下的所有 FAQ 条目导出为 CSV 文件
控制上次导入完成后,前端结果卡片的显示/隐藏
**请求**:
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/entries/export' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--output faq_export.csv
```
**响应**:
CSV 文件下载Content-Type: text/csv
## GET `/faq/import/progress/:task_id` - 获取FAQ导入进度
查询异步 FAQ 导入任务的执行进度。任务 ID 由批量导入接口返回。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/faq/import/progress/task-00000001' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'Content-Type: application/json'
```
**响应**:
```json
{
"data": {
"task_id": "task-00000001",
"status": "completed",
"total": 100,
"success_count": 98,
"failed_count": 2,
"failed_entries": [
{
"index": 5,
"standard_question": "重复的问题",
"error": "标准问与已有FAQ重复"
}
],
"success_entries": []
},
"success": true
}
```
注:`status` 可能的值为 `pending``processing``completed``failed`
## PUT `/knowledge-bases/:id/faq/import/last-result/display` - 更新导入结果显示状态
更新上一次 FAQ 导入结果的显示状态,用于控制前端是否展示导入结果提示。
**请求参数**:
- `display_status`: 显示状态(如 `"dismissed"`
| 字段 | 类型 | 必填 | 说明 |
| -------------- | ------ | ---- | --------------------- |
| display_status | string | 是 | `open``close` |
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/faq/import/last-result/display' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"display_status": "dismissed"
"display_status": "close"
}'
```
**响应**:
```json
{ "success": true }
```
## GET `/faq/import/progress/:task_id` - 查询 FAQ 导入进度
> **注意**:此接口**不在** `/knowledge-bases/:id/faq` 分组下,路径直接以 `/faq/import/progress/:task_id` 开头。任务 ID 由 `POST /knowledge-bases/:id/faq/entries` 返回。
**路径参数**:
| 参数 | 类型 | 说明 |
| ------- | ------ | -------------- |
| task_id | string | 导入任务的 ID |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/faq/import/progress/task-00000001' \
--header 'X-API-Key: sk-xxxxx'
```
**响应**(节选关键字段):
```json
{
"data": {
"task_id": "task-00000001",
"kb_id": "kb-00000001",
"knowledge_id": "knowledge-00000001",
"status": "completed",
"progress": 100,
"total": 100,
"processed": 100,
"success_count": 95,
"failed_count": 3,
"partial_failed_count": 2,
"skipped_count": 0,
"failed_entries": [
{
"index": 5,
"reason": "标准问与已有FAQ重复",
"standard_question": "重复的问题"
}
],
"success_entries": [
{ "index": 0, "seq_id": 101, "standard_question": "如何联系客服?" }
],
"message": "",
"error": "",
"created_at": 1736582400,
"updated_at": 1736582460,
"dry_run": false,
"import_mode": "append",
"imported_at": "2025-08-12T10:01:00+08:00",
"display_status": "open",
"processing_time": 60000
},
"success": true
}
```
`status` 可能取值:`pending` / `processing` / `completed` / `failed`
当失败条目过多时,`failed_entries` 可能不直接返回,而通过 `failed_entries_url` 提供 CSV 下载地址。
`dry_run=true` 模式下的任务同样通过此接口查询,`success_entries` 中的 `seq_id` 不会真正写入。

View File

@@ -7,29 +7,49 @@
- 知识库类型 `type``document`(文档)或 `faq`FAQ默认 `document`
- JSON 中对象存储相关字段:**`storage_config`** 为序列化字段名(对应数据库列 `cos_config`,兼容旧数据)。旧客户端若仍发送或接收 `cos_config`,服务端会兼容解析;新集成请使用 **`storage_config`**。
- **`storage_provider_config`** 为新版存储提供者选择(如 `{"provider": "local"}`),与租户级存储引擎凭证配合使用;无配置时可为 `null`
- 嵌套配置对象:`chunking_config``image_processing_config``vlm_config``asr_config``extract_config``faq_config``question_generation_config`。其中 `extract_config``faq_config``question_generation_config` 允许为 `null`
| 方法 | 路径 | 描述 |
| ------ | ------------------------------------ | ------------------------ |
| POST | `/knowledge-bases` | 创建知识库 |
| GET | `/knowledge-bases` | 获取知识库列表 |
| GET | `/knowledge-bases/:id` | 获取知识库详情 |
| PUT | `/knowledge-bases/:id` | 更新知识库 |
| DELETE | `/knowledge-bases/:id` | 删除知识库 |
| POST | `/knowledge-bases/copy` | 拷贝知识库 |
| GET | `/knowledge-bases/copy/progress/:task_id` | 获取拷贝进度 |
| GET | `/knowledge-bases/:id/hybrid-search` | 混合搜索(向量+关键词) |
| PUT | `/knowledge-bases/:id/pin` | 置顶/取消置顶知识库 |
| GET | `/knowledge-bases/:id/move-targets` | 获取可迁移目标知识库列表 |
| 方法 | 路径 | 描述 |
| ------ | ----------------------------------------- | ------------------------ |
| POST | `/knowledge-bases` | 创建知识库 |
| GET | `/knowledge-bases` | 获取知识库列表 |
| GET | `/knowledge-bases/:id` | 获取知识库详情 |
| PUT | `/knowledge-bases/:id` | 更新知识库 |
| DELETE | `/knowledge-bases/:id` | 删除知识库 |
| PUT | `/knowledge-bases/:id/pin` | 置顶/取消置顶知识库 |
| GET | `/knowledge-bases/:id/hybrid-search` | 混合搜索(向量+关键词) |
| POST | `/knowledge-bases/copy` | 拷贝知识库(异步任务) |
| GET | `/knowledge-bases/copy/progress/:task_id` | 获取拷贝进度 |
| GET | `/knowledge-bases/:id/move-targets` | 获取可迁移目标知识库列表 |
## POST `/knowledge-bases` - 创建知识库
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------------------------- | ------- | ---- | --------------------------------------------------------------- |
| name | string | 是 | 知识库名称 |
| description | string | 否 | 知识库描述 |
| type | string | 否 | 知识库类型:`document`(默认)或 `faq` |
| is_temporary | boolean | 否 | 是否为临时知识库(默认 `false`,临时库通常不在 UI 列表中显示) |
| chunking_config | object | 否 | 分块配置(见下方示例) |
| image_processing_config | object | 否 | 图片处理配置 |
| embedding_model_id | string | 否 | Embedding 模型 ID |
| summary_model_id | string | 否 | 摘要模型 ID |
| vlm_config | object | 否 | VLM视觉模型配置 |
| asr_config | object | 否 | ASR语音识别配置 |
| storage_provider_config | object | 否 | 存储提供者选择,如 `{"provider": "local"}` |
| storage_config | object | 否 | 旧版 COS 存储凭证(兼容字段,新集成留空即可) |
| extract_config | object | 否 | 图谱抽取配置;`enabled=true` 时需提供 `text`/`tags`/`nodes`/`relations` |
| faq_config | object | 否 | FAQ 配置(仅 FAQ 类型知识库需要) |
| question_generation_config | object | 否 | 问题生成配置 |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--data '{
"name": "weknora",
"description": "weknora description",
@@ -160,180 +180,74 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases' \
## GET `/knowledge-bases` - 获取知识库列表
返回当前租户拥有的全部知识库。当传入 `agent_id` 时,校验调用者对该共享智能体的访问权限后,返回该智能体配置可见的知识库范围(用于 `@` 提及)。
**Query 参数**:
| 字段 | 类型 | 必填 | 说明 |
| -------- | ------ | ---- | ---------------------------------------------------------- |
| agent_id | string | 否 | 共享智能体 ID传入时按智能体配置`all` / `selected` / `none`)过滤可见知识库 |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
```json
{
"data": [
{
"id": "kb-00000001",
"name": "Default Knowledge Base",
"description": "System Default Knowledge Base",
"type": "document",
"is_temporary": false,
"tenant_id": 1,
"chunking_config": {
"chunk_size": 1000,
"chunk_overlap": 200,
"separators": [
"\n\n",
"\n",
"。",
"",
"",
";",
""
],
"enable_multimodal": true,
"parser_engine_rules": [],
"enable_parent_child": false,
"parent_chunk_size": 4096,
"child_chunk_size": 384
},
"image_processing_config": {
"model_id": ""
},
"embedding_model_id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3",
"summary_model_id": "8aea788c-bb30-4898-809e-e40c14ffb48c",
"vlm_config": {
"enabled": true,
"model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e"
},
"asr_config": {
"enabled": false,
"model_id": "",
"language": ""
},
"storage_provider_config": {
"provider": "local"
},
"storage_config": {
"secret_id": "",
"secret_key": "",
"region": "",
"bucket_name": "",
"app_id": "",
"path_prefix": ""
},
"extract_config": null,
"faq_config": null,
"question_generation_config": null,
"is_pinned": false,
"pinned_at": null,
"knowledge_count": 12,
"chunk_count": 340,
"processing_count": 0,
"created_at": "2025-08-11T20:10:41.817794+08:00",
"updated_at": "2025-08-12T11:23:00.593097+08:00",
"deleted_at": null
}
],
"success": true
}
```
**响应**: `data` 为数组,每个元素的字段结构同 `POST /knowledge-bases` 响应,并额外携带 `knowledge_count` / `chunk_count` / `processing_count` / `share_count` / `is_pinned` / `pinned_at` 这些聚合与状态字段。
## GET `/knowledge-bases/:id` - 获取知识库详情
根据 ID 获取知识库详情。当通过共享智能体访问时,可传 `agent_id` 进行权限校验;此时返回对象会附加 `my_permission` 字段以指示当前用户对该知识库的角色(如 `viewer`)。
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | --------- |
| id | string | 知识库 ID |
**Query 参数**:
| 字段 | 类型 | 必填 | 说明 |
| -------- | ------ | ---- | ------------------------------------------ |
| agent_id | string | 否 | 共享智能体 ID用于校验该智能体是否有权访问 |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
```json
{
"data": {
"id": "kb-00000001",
"name": "Default Knowledge Base",
"description": "System Default Knowledge Base",
"type": "document",
"is_temporary": false,
"tenant_id": 1,
"chunking_config": {
"chunk_size": 1000,
"chunk_overlap": 200,
"separators": [
"\n\n",
"\n",
"。",
"",
"",
";",
""
],
"enable_multimodal": true,
"parser_engine_rules": [],
"enable_parent_child": false,
"parent_chunk_size": 4096,
"child_chunk_size": 384
},
"image_processing_config": {
"model_id": ""
},
"embedding_model_id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3",
"summary_model_id": "8aea788c-bb30-4898-809e-e40c14ffb48c",
"vlm_config": {
"enabled": true,
"model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e"
},
"asr_config": {
"enabled": false,
"model_id": "",
"language": ""
},
"storage_provider_config": {
"provider": "local"
},
"storage_config": {
"secret_id": "",
"secret_key": "",
"region": "",
"bucket_name": "",
"app_id": "",
"path_prefix": ""
},
"extract_config": {
"enabled": false,
"text": "",
"tags": [],
"nodes": [],
"relations": []
},
"faq_config": null,
"question_generation_config": null,
"is_pinned": false,
"pinned_at": null,
"knowledge_count": 12,
"chunk_count": 340,
"processing_count": 0,
"created_at": "2025-08-11T20:10:41.817794+08:00",
"updated_at": "2025-08-12T11:23:00.593097+08:00",
"deleted_at": null
},
"success": true
}
```
**响应**: 字段结构同 `POST /knowledge-bases` 响应,并附 `is_pinned` / `pinned_at` / `knowledge_count` / `chunk_count` / `processing_count` 状态字段。通过共享智能体访问时还会附加 `my_permission`
## PUT `/knowledge-bases/:id` - 更新知识库
仅知识库 owneradmin或具备 `editor` 权限的用户可调用。注意:**`vector_store_id` 在创建后不可修改**,更新接口不接收该字段。
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | --------- |
| id | string | 知识库 ID |
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------- | ------ | ---- | ------------------------------------------------------------- |
| name | string | 是 | 知识库名称 |
| description | string | 否 | 知识库描述 |
| config | object | 否 | 更新配置;包含 `chunking_config` / `image_processing_config` / `faq_config` / `wiki_config` / `indexing_strategy` |
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/b5829e4a-3845-4624-a7fb-ea3b35e843b0' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--data '{
"name": "weknora new",
"description": "weknora description new",
@@ -368,89 +282,24 @@ curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/b582
}'
```
**响应**:
```json
{
"data": {
"id": "b5829e4a-3845-4624-a7fb-ea3b35e843b0",
"name": "weknora new",
"description": "weknora description new",
"type": "document",
"is_temporary": false,
"tenant_id": 1,
"chunking_config": {
"chunk_size": 1000,
"chunk_overlap": 200,
"separators": [
"\n\n",
"\n",
"。",
"",
"",
";",
""
],
"enable_multimodal": true,
"parser_engine_rules": [
{
"file_types": [".md", ".txt"],
"engine": "builtin"
}
],
"enable_parent_child": true,
"parent_chunk_size": 4096,
"child_chunk_size": 384
},
"image_processing_config": {
"model_id": ""
},
"embedding_model_id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3",
"summary_model_id": "8aea788c-bb30-4898-809e-e40c14ffb48c",
"vlm_config": {
"enabled": true,
"model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e"
},
"asr_config": {
"enabled": false,
"model_id": "",
"language": ""
},
"storage_provider_config": {
"provider": "local"
},
"storage_config": {
"secret_id": "",
"secret_key": "",
"region": "",
"bucket_name": "",
"app_id": "",
"path_prefix": ""
},
"extract_config": null,
"faq_config": null,
"question_generation_config": null,
"is_pinned": false,
"pinned_at": null,
"knowledge_count": 3,
"chunk_count": 48,
"processing_count": 1,
"created_at": "2025-08-12T11:30:09.206238+08:00",
"updated_at": "2025-08-12T11:36:09.083577609+08:00",
"deleted_at": null
},
"success": true
}
```
**响应**: 字段结构同 `POST /knowledge-bases` 响应(返回更新后的完整知识库对象)。
## DELETE `/knowledge-bases/:id` - 删除知识库
仅知识库 owner与 owning tenant 匹配的 admin可调用删除将级联清理知识库下所有知识与切片。
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | --------- |
| id | string | 知识库 ID |
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/knowledge-bases/b5829e4a-3845-4624-a7fb-ea3b35e843b0' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ'
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
@@ -462,87 +311,59 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/knowledge-bases/b
}
```
## POST `/knowledge-bases/copy` - 拷贝知识库
## PUT `/knowledge-bases/:id/pin` - 置顶/取消置顶知识库
异步拷贝一个知识库包括知识库配置和所有知识内容。返回任务ID用于查询拷贝进度
切换知识库的置顶状态。无需请求体,每次调用会自动反转当前 `is_pinned`。置顶时会同步写入 `pinned_at` 时间戳
**请求参数**:
- `source_id`: 源知识库ID必填
- `name`: 新知识库名称(可选,默认使用原名称加"(副本)"后缀)
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | --------- |
| id | string | 知识库 ID |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/copy' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'Content-Type: application/json' \
--data '{
"source_id": "kb-00000001",
"name": "知识库副本"
}'
```
**响应**:
```json
{
"data": {
"task_id": "task-copy-00000001",
"target_id": "kb-00000002"
},
"success": true
}
```
## GET `/knowledge-bases/copy/progress/:task_id` - 获取拷贝进度
查询知识库拷贝任务的执行进度。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/copy/progress/task-copy-00000001' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/pin' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**响应**:
```json
{
"data": {
"task_id": "task-copy-00000001",
"status": "completed",
"total": 10,
"finished": 10,
"source_id": "kb-00000001",
"target_id": "kb-00000002"
},
"success": true
}
```
注:`status` 可能的值为 `pending``processing``completed``failed`
**响应**: 字段结构同 `POST /knowledge-bases` 响应,本接口操作后 `is_pinned` 翻转、`pinned_at` 同步更新。
## GET `/knowledge-bases/:id/hybrid-search` - 混合搜索
执行向量搜索和关键词搜索的混合检索。
在指定知识库内执行向量召回 + 关键词召回的混合检索。
**注意**:此接口使用 GET 方法但需要 JSON 请求体。
**注意**:此接口使用 `GET` 方法但 **需要 JSON 请求体**`SearchParams`),并非通过 query string 传参
**请求参数**
- `query_text`: 搜索查询文本(必填)
- `vector_threshold`: 向量相似度阈值0-1可选
- `keyword_threshold`: 关键词匹配阈值(可选)
- `match_count`: 返回结果数量(可选)
- `disable_keywords_match`: 是否禁用关键词匹配(可选)
- `disable_vector_match`: 是否禁用向量匹配(可选)
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | --------- |
| id | string | 知识库 ID |
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ------------------------ | -------- | ---- | ---------------------------------------------------------------- |
| query_text | string | 是 | 查询文本 |
| vector_threshold | number | 否 | 向量相似度阈值0-1 |
| keyword_threshold | number | 否 | 关键词匹配阈值 |
| match_count | integer | 否 | 返回结果数量上限 |
| disable_keywords_match | boolean | 否 | 关闭关键词召回 |
| disable_vector_match | boolean | 否 | 关闭向量召回 |
| knowledge_ids | string[] | 否 | 仅在指定的知识 ID 范围内召回 |
| tag_ids | string[] | 否 | 标签过滤FAQ 类型常用于优先级过滤) |
| only_recommended | boolean | 否 | 仅返回标记为推荐的内容 |
| knowledge_base_ids | string[] | 否 | 跨知识库召回(需共享相同 embedding 模型),优先级高于路径中的 `:id` |
| skip_context_enrichment | boolean | 否 | 跳过父子片段/相邻片段的上下文补全chat 流程使用) |
**请求**:
```curl
curl --location --request GET 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/hybrid-search' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"query_text": "如何使用知识库",
@@ -577,15 +398,76 @@ curl --location --request GET 'http://localhost:8080/api/v1/knowledge-bases/kb-0
}
```
## PUT `/knowledge-bases/:id/pin` - 置顶/取消置顶知识库
## POST `/knowledge-bases/copy` - 拷贝知识库
切换知识库的置顶状态。无需请求体,每次调用会自动切换当前置顶状态
异步拷贝整个知识库(配置 + 全部知识内容)。请求会被入队到 Asynq 后台任务(队列 `default`,最多重试 3 次),并立即返回 `task_id` 供轮询进度
**约束**:源知识库 `source_id` 必须属于调用者所在租户;若指定 `target_id`,目标知识库同样必须属于调用者租户,否则返回 `403 Forbidden`
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | ------------------------------------------------------------- |
| source_id | string | 是 | 源知识库 ID必须属于当前租户 |
| target_id | string | 否 | 目标知识库 ID若复用已存在知识库同样必须属于当前租户 |
| task_id | string | 否 | 自定义任务 ID不传则由服务端生成基于租户、源 ID、时间戳 |
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/pin' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
curl --location 'http://localhost:8080/api/v1/knowledge-bases/copy' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"source_id": "kb-00000001"
}'
```
**响应**:
```json
{
"data": {
"task_id": "kb_clone_1_kb-00000001_1736582400",
"source_id": "kb-00000001",
"target_id": "",
"message": "Knowledge base copy task started"
},
"success": true
}
```
## GET `/knowledge-bases/copy/progress/:task_id` - 获取拷贝进度
查询拷贝任务的当前状态与进度(数据由 worker 写入 Redis
**路径参数**:
| 字段 | 类型 | 说明 |
| ------- | ------ | ------------------------------------------------- |
| task_id | string | 由 `POST /knowledge-bases/copy` 返回的任务 ID |
**响应字段(`data`**:
| 字段 | 类型 | 说明 |
| ---------- | ------- | ------------------------------------------------------------ |
| task_id | string | 任务 ID |
| source_id | string | 源知识库 ID |
| target_id | string | 目标知识库 ID任务开始后填入 |
| status | string | `pending` / `processing` / `completed` / `failed` |
| progress | integer | 进度百分比 0100 |
| total | integer | 计划拷贝的知识总数 |
| processed | integer | 已处理的知识数 |
| message | string | 当前状态描述 |
| error | string | 失败时的错误信息 |
| created_at | integer | 任务创建时间Unix 秒) |
| updated_at | integer | 最后更新时间Unix 秒) |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/copy/progress/kb_clone_1_kb-00000001_1736582400' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
@@ -594,58 +476,17 @@ curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-0
```json
{
"data": {
"id": "kb-00000001",
"name": "Default Knowledge Base",
"description": "System Default Knowledge Base",
"type": "document",
"is_temporary": false,
"tenant_id": 1,
"chunking_config": {
"chunk_size": 1000,
"chunk_overlap": 200,
"separators": ["\n\n", "\n", "。", "", "", ";", ""],
"enable_multimodal": true,
"parser_engine_rules": [],
"enable_parent_child": false,
"parent_chunk_size": 4096,
"child_chunk_size": 384
},
"image_processing_config": {
"model_id": ""
},
"embedding_model_id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3",
"summary_model_id": "8aea788c-bb30-4898-809e-e40c14ffb48c",
"vlm_config": {
"enabled": true,
"model_id": "f2083ad7-63e3-486d-a610-e6c56e58d72e"
},
"asr_config": {
"enabled": false,
"model_id": "",
"language": ""
},
"storage_provider_config": {
"provider": "local"
},
"storage_config": {
"secret_id": "",
"secret_key": "",
"region": "",
"bucket_name": "",
"app_id": "",
"path_prefix": ""
},
"extract_config": null,
"faq_config": null,
"question_generation_config": null,
"is_pinned": true,
"pinned_at": "2025-08-12T15:00:00.000000+08:00",
"knowledge_count": 12,
"chunk_count": 340,
"processing_count": 0,
"created_at": "2025-08-11T20:10:41.817794+08:00",
"updated_at": "2025-08-12T15:00:00.000000+08:00",
"deleted_at": null
"task_id": "kb_clone_1_kb-00000001_1736582400",
"source_id": "kb-00000001",
"target_id": "kb-00000002",
"status": "completed",
"progress": 100,
"total": 10,
"processed": 10,
"message": "Task completed successfully",
"error": "",
"created_at": 1736582400,
"updated_at": 1736582460
},
"success": true
}
@@ -653,13 +494,25 @@ curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-0
## GET `/knowledge-bases/:id/move-targets` - 获取可迁移目标知识库列表
获取当前知识库可以迁移知识到的目标知识库列表。返回结果会排除当前知识库本身。
返回当前知识库的内容**可以迁移到**的目标知识库列表。筛选规则:
- 与源知识库 `type` 相同
- 与源知识库 `embedding_model_id` 相同
- 非临时知识库(`is_temporary = false`
- 不包含源知识库自身
- 仅同租户的知识库
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | ------------- |
| id | string | 源知识库 ID |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/move-targets' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```

View File

@@ -10,18 +10,23 @@
在知识库中搜索相关内容(不使用 LLM 总结),直接返回检索结果。
**请求参数**:
- `query`: 搜索查询文本(必填)
- `knowledge_base_id`: 单个知识库ID向后兼容
- `knowledge_base_ids`: 知识库ID列表支持多知识库搜索
- `knowledge_ids`: 指定知识文件ID列表
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ------------------- | -------- | ---- | ---------------------------------------------------------- |
| query | string | 是 | 搜索查询文本 |
| knowledge_base_id | string | 否 | 单个知识库 ID向后兼容`knowledge_base_ids` 互斥 |
| knowledge_base_ids | string[] | 否 | 多个知识库 ID 列表,跨知识库搜索 |
| knowledge_ids | string[] | 否 | 进一步限定到指定知识(文件);不传则在整库范围内搜索 |
> 必须指定 `knowledge_base_id` 或 `knowledge_base_ids` 中的至少一个。
**请求**:
```curl
# 搜索单个知识库
curl --location 'http://localhost:8080/api/v1/knowledge-search' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"query": "如何使用知识库",
@@ -30,7 +35,7 @@ curl --location 'http://localhost:8080/api/v1/knowledge-search' \
# 搜索多个知识库
curl --location 'http://localhost:8080/api/v1/knowledge-search' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"query": "如何使用知识库",
@@ -39,7 +44,7 @@ curl --location 'http://localhost:8080/api/v1/knowledge-search' \
# 搜索指定文件
curl --location 'http://localhost:8080/api/v1/knowledge-search' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"query": "如何使用知识库",
@@ -72,3 +77,21 @@ curl --location 'http://localhost:8080/api/v1/knowledge-search' \
"success": true
}
```
**响应字段说明data[]**:
| 字段 | 类型 | 说明 |
| ------------------ | ------- | ------------------------------------- |
| id | string | 分块 ID |
| content | string | 命中的分块文本 |
| knowledge_id | string | 该分块所属的知识 ID |
| chunk_index | int | 分块在知识中的序号 |
| knowledge_title | string | 来源知识标题 |
| start_at / end_at | int | 分块在源文档中的字符偏移 |
| seq | int | 命中排序号 |
| score | number | 相似度rerank 后归一化后的最终得分) |
| chunk_type | string | 分块类型(`text` / `image` / ... |
| image_info | string | 图像分块的额外信息JSON 字符串) |
| metadata | object | 自定义元数据 |
| knowledge_filename | string | 来源文件名 |
| knowledge_source | string | 来源类型(`file` / `url` / `manual` |

File diff suppressed because it is too large Load Diff

View File

@@ -2,29 +2,38 @@
[返回目录](./README.md)
| 方法 | 路径 | 描述 |
| ------ | --------------------------------- | ---------------------- |
| POST | `/mcp-services` | 创建 MCP 服务 |
| GET | `/mcp-services` | 获取 MCP 服务列表 |
| GET | `/mcp-services/:id` | 获取 MCP 服务详情 |
| PUT | `/mcp-services/:id` | 更新 MCP 服务 |
| DELETE | `/mcp-services/:id` | 删除 MCP 服务 |
| POST | `/mcp-services/:id/test` | 测试 MCP 服务连接 |
| GET | `/mcp-services/:id/tools` | 获取 MCP 服务工具列表 |
| GET | `/mcp-services/:id/resources` | 获取 MCP 服务资源列表 |
MCPModel Context Protocol服务管理接口提供 MCP 服务的 CRUD、连通性测试、工具/资源发现,以及工具人工审批策略配置。
| 方法 | 路径 | 描述 |
| ------ | ------------------------------------------------- | --------------------------------------------- |
| POST | `/mcp-services` | 创建 MCP 服务 |
| GET | `/mcp-services` | 获取当前租户的 MCP 服务列表 |
| GET | `/mcp-services/:id` | 获取 MCP 服务详情 |
| PUT | `/mcp-services/:id` | 更新 MCP 服务(部分字段更新) |
| DELETE | `/mcp-services/:id` | 删除 MCP 服务 |
| POST | `/mcp-services/:id/test` | 测试 MCP 服务连通性 |
| GET | `/mcp-services/:id/tools` | 获取 MCP 服务工具列表 |
| GET | `/mcp-services/:id/resources` | 获取 MCP 服务资源列表 |
| GET | `/mcp-services/:id/tool-approvals` | 列出该服务下各工具的人工审批策略 |
| PUT | `/mcp-services/:id/tool-approvals/:tool_name` | 设置/更新某工具的人工审批策略 |
| POST | `/agent/tool-approvals/:pending_id` | 处理 Agent 工具调用待审批请求 |
## POST `/mcp-services` - 创建 MCP 服务
**请求参数**:
- `name`: 服务名称(必填)
- `description`: 服务描述(可选)
- `transport_type`: 传输类型,可选值:`sse``http-streamable``stdio`(必填)
- `url`: 服务地址,当 transport_type 为 `sse``http-streamable` 时必填
- `headers`: 自定义请求头(可选)
- `auth_config`: 认证配置(可选),包含 `api_key``token``custom_headers`
- `advanced_config`: 高级配置(可选),包含 `timeout``retry_count``retry_delay`
- `stdio_config`: stdio 传输配置(可选),包含 `command``args`
- `env_vars`: 环境变量(可选)
| 字段 | 类型 | 必填 | 说明 |
| ---------------- | ------- | ---- | --------------------------------------------------------------------------------------------- |
| name | string | 是 | 服务名称 |
| description | string | 否 | 服务描述 |
| transport_type | string | 是 | 传输类型,可选:`sse``http-streamable``stdio` |
| url | string | 条件 | 服务地址;当 `transport_type``sse` / `http-streamable` 时必填(受 SSRF 安全校验约束) |
| headers | object | 否 | 自定义请求头 |
| auth_config | object | 否 | 认证配置,支持 `api_key``token` |
| advanced_config | object | 否 | 高级配置,支持 `timeout``retry_count``retry_delay` |
| stdio_config | object | 条件 | stdio 传输配置,包含 `command``args`;当 `transport_type``stdio` 时必填 |
| env_vars | object | 否 | 环境变量stdio 场景常用) |
| enabled | boolean | 否 | 是否启用 |
**请求**:
@@ -82,7 +91,7 @@ curl --location 'http://localhost:8080/api/v1/mcp-services' \
}
```
**创建 stdio 类型的 MCP 服务**:
**创建 stdio 类型的 MCP 服务示例**:
```curl
curl --location 'http://localhost:8080/api/v1/mcp-services' \
@@ -104,6 +113,8 @@ curl --location 'http://localhost:8080/api/v1/mcp-services' \
## GET `/mcp-services` - 获取 MCP 服务列表
返回当前租户已配置的所有 MCP 服务。
**请求**:
```curl
@@ -166,6 +177,14 @@ curl --location 'http://localhost:8080/api/v1/mcp-services' \
## GET `/mcp-services/:id` - 获取 MCP 服务详情
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | -------------- |
| id | string | MCP 服务 ID |
> 注:内置(`is_builtin: true`)服务在响应中会隐藏敏感凭证字段。
**请求**:
```curl
@@ -205,6 +224,8 @@ curl --location 'http://localhost:8080/api/v1/mcp-services/mcp-00000001' \
## PUT `/mcp-services/:id` - 更新 MCP 服务
支持部分字段更新,可传入下列任意子集:`name``description``enabled``transport_type``url``stdio_config``env_vars``headers``auth_config``advanced_config`。其中 `url` 若提供,会再次执行 SSRF 安全校验。
**请求**:
```curl
@@ -261,11 +282,14 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/mcp-services/mcp-
```json
{
"success": true
"success": true,
"message": "MCP service deleted successfully"
}
```
## POST `/mcp-services/:id/test` - 测试 MCP 服务连
## POST `/mcp-services/:id/test` - 测试 MCP 服务连通性
后端会以已保存配置建立一次 MCP 连接,返回连接结果及探测到的工具/资源列表。连接失败时 HTTP 仍为 200`data.success``false`,错误原因在 `data.message` 中。
**请求**:
@@ -394,3 +418,139 @@ curl --location 'http://localhost:8080/api/v1/mcp-services/mcp-00000001/resource
"success": true
}
```
## GET `/mcp-services/:id/tool-approvals` - 列出工具人工审批策略
返回该 MCP 服务下各工具持久化的 `require_approval` 标记。仅返回数据库中已显式配置过的工具记录;未出现在列表中的工具默认无需审批。
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | ----------- |
| id | string | MCP 服务 ID |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/mcp-services/mcp-00000001/tool-approvals' \
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
```json
{
"data": [
{
"tool_name": "delete_file",
"require_approval": true,
"updated_at": "2025-09-20T15:30:00+08:00"
},
{
"tool_name": "get_weather",
"require_approval": false,
"updated_at": "2025-09-20T15:31:00+08:00"
}
],
"success": true
}
```
## PUT `/mcp-services/:id/tool-approvals/:tool_name` - 设置工具人工审批策略
为指定 MCP 服务下的某个工具设置/更新人工审批要求。当 `require_approval``true`Agent 在调用该工具前会阻塞并产生一条待审批记录,需要前端调用 `POST /agent/tool-approvals/:pending_id` 完成审批。
**路径参数**:
| 字段 | 类型 | 说明 |
| ---------- | ------ | ------------------------------------------------------------------- |
| id | string | MCP 服务 ID |
| tool_name | string | 工具名(由 Gin 自动 URL 解码,调用方需对名称中的 `%``/` 做 URL 编码) |
**请求体**:
| 字段 | 类型 | 必填 | 说明 |
| ----------------- | ------- | ---- | ----------------------------------- |
| require_approval | boolean | 是 | 是否要求人工审批后才能执行该工具 |
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/mcp-services/mcp-00000001/tool-approvals/delete_file' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"require_approval": true
}'
```
**响应**:
```json
{
"success": true
}
```
## POST `/agent/tool-approvals/:pending_id` - 处理待审批工具调用
用于 Agent 在执行过程中阻塞等待人工审批的场景:当 Agent 命中一个 `require_approval = true` 的工具时会生成一条 `pending_id`,前端拿到这个 ID 后调用此接口将审批结果回传给 AgentAgent 才会继续执行(或终止)。
**鉴权要求**:请求上下文中必须有已认证用户(`user_id`),且该用户必须是当前 pending 会话的所有者;租户与用户两层都会做 fail-close 校验。
**路径参数**:
| 字段 | 类型 | 说明 |
| ----------- | ------ | ------------------- |
| pending_id | string | 待审批记录 ID |
**请求体**:
| 字段 | 类型 | 必填 | 说明 |
| -------------- | ------ | ---- | ----------------------------------------------------------------------------------------------------------------- |
| decision | string | 是 | 审批结论,必须为 `approve``reject` |
| modified_args | object | 否 | 仅在 `approve` 时生效,允许人工修改本次工具调用的参数;必须是非 null 的 JSON 对象,否则返回 400 |
| reason | string | 否 | 审批理由(任意,便于审计) |
**请求(通过)**:
```curl
curl --location --request POST 'http://localhost:8080/api/v1/agent/tool-approvals/pending-abcdef123456' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"decision": "approve",
"modified_args": {
"path": "/tmp/safe-target.txt"
},
"reason": "已确认目标路径安全"
}'
```
**请求(驳回)**:
```curl
curl --location --request POST 'http://localhost:8080/api/v1/agent/tool-approvals/pending-abcdef123456' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"decision": "reject",
"reason": "目标路径在受保护目录"
}'
```
**响应**:
```json
{
"success": true
}
```
**错误码说明**:
| HTTP | 触发条件 |
| ---- | --------------------------------------------------------------------------------------- |
| 400 | `decision` 不是 `approve`/`reject`;或 `modified_args``null`/非对象;或租户/用户错配 |
| 401 | 上下文缺失认证用户(中间件未注入 `user_id` |
| 404 | `pending_id` 不存在或已完成(超时/取消已先一步消费) |

View File

@@ -20,7 +20,7 @@
```curl
curl --location --request GET 'http://localhost:8080/api/v1/messages/ceb9babb-1e30-41d7-817d-fd584954304b/load?limit=3&before_time=2030-08-12T14%3A35%3A42.123456789Z' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"query": "彗尾的形状"
@@ -177,7 +177,7 @@ curl --location --request GET 'http://localhost:8080/api/v1/messages/ceb9babb-1e
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/messages/ceb9babb-1e30-41d7-817d-fd584954304b/9bcafbcf-a758-40af-a9a3-c4d8e0f49439' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
@@ -204,7 +204,7 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/messages/ceb9babb
```curl
curl --location 'http://localhost:8080/api/v1/messages/search' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"query": "彗星的结构",
@@ -245,7 +245,7 @@ curl --location 'http://localhost:8080/api/v1/messages/search' \
```curl
curl --location 'http://localhost:8080/api/v1/messages/chat-history-stats' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```

View File

@@ -2,24 +2,26 @@
[返回目录](./README.md)
| 方法 | 路径 | 描述 |
| ------ | ----------------------- | --------------------- |
| POST | `/models` | 创建模型 |
| GET | `/models` | 获取模型列表 |
| GET | `/models/:id` | 获取模型详情 |
| PUT | `/models/:id` | 更新模型 |
| DELETE | `/models/:id` | 删除模型 |
| GET | `/models/providers` | 获取模型服务商列表 |
模型管理接口用于维护当前租户下可用的 LLM / Embedding / Rerank / VLLM / ASR 模型配置。
| 方法 | 路径 | 描述 |
| ------ | ------------------- | --------------------- |
| GET | `/models/providers` | 获取模型服务商列表 |
| POST | `/models` | 创建模型 |
| GET | `/models` | 获取模型列表 |
| GET | `/models/:id` | 获取模型详情 |
| PUT | `/models/:id` | 更新模型 |
| DELETE | `/models/:id` | 删除模型 |
## 服务商支持 (Provider Support)
WeKnora 支持多种主流 AI 模型服务商,在创建模型时可通过 `provider` 字段指定服务商类型以获得更好的兼容性。
WeKnora 支持多种主流 AI 模型服务商,在创建模型时可通过 `parameters.provider` 字段指定服务商类型以获得更好的兼容性。
### 支持的服务商列表
| 服务商标识 | 名称 | 支持的模型类型 |
| -------------- | ---------------------------- | ------------------------------- |
| `generic` | 自定义 (OpenAI兼容接口) | Chat, Embedding, Rerank, VLLM |
| `generic` | 自定义 (OpenAI 兼容接口) | Chat, Embedding, Rerank, VLLM |
| `openai` | OpenAI | Chat, Embedding, Rerank, VLLM |
| `aliyun` | 阿里云 DashScope | Chat, Embedding, Rerank, VLLM |
| `zhipu` | 智谱 BigModel | Chat, Embedding, Rerank, VLLM |
@@ -39,15 +41,17 @@ WeKnora 支持多种主流 AI 模型服务商,在创建模型时可通过 `pro
| `longcat` | LongCat AI | Chat |
| `gpustack` | GPUStack | Chat, Embedding, Rerank, VLLM |
> 实际可用的服务商以 `GET /models/providers` 返回为准。
## GET `/models/providers` - 获取模型服务商列表
根据模型类型获取支持的服务商列表及配置信息。
根据模型类型获取支持的服务商列表及配置信息(系统级元数据,与租户无关)
**请求参数**:
**查询参数**:
| 参数 | 类型 | 必填 | 描述 |
| ---------- | ------ | ---- | ---------------------------------------------- |
| model_type | string | 否 | 模型类型:`chat`, `embedding`, `rerank`, `vllm` |
| 字段 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | --------------------------------------------------- |
| model_type | string | 否 | 模型类型,可选值`chat` / `embedding` / `rerank` / `vllm` / `asr`;省略则返回全部 |
**请求**:
@@ -95,6 +99,20 @@ curl --location 'http://localhost:8080/api/v1/models/providers?model_type=embedd
## POST `/models` - 创建模型
为当前租户创建一个新的模型配置。
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------- | ------ | ---- | --------------------------------------------------------------- |
| name | string | 是 | 模型名称(远程模型对应服务商的 model id本地模型为 Ollama tag|
| type | string | 是 | 模型类型,可选值:`KnowledgeQA` / `Embedding` / `Rerank` / `VLLM` / `ASR` |
| source | string | 是 | 模型来源,可选值:`local` / `remote` |
| description | string | 否 | 模型描述 |
| parameters | object | 是 | 模型参数,详见下方 [Parameters](#parameters-模型参数) |
> 当 `parameters.base_url` 不为空时,后端会执行 SSRF 校验,校验失败将返回 400。
### 创建对话模型KnowledgeQA
**本地 Ollama 模型**:
@@ -295,6 +313,8 @@ curl --location 'http://localhost:8080/api/v1/models' \
## GET `/models` - 获取模型列表
返回当前租户下的所有模型。内置模型(`is_builtin = true`)的 `base_url``api_key` 会被清空以隐藏敏感信息。
**请求**:
```curl
@@ -303,62 +323,16 @@ curl --location 'http://localhost:8080/api/v1/models' \
--header 'X-API-Key: your_api_key'
```
**响应**:
```json
{
"success": true,
"data": [
{
"id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3",
"tenant_id": 1,
"name": "text-embedding-v3",
"type": "Embedding",
"source": "remote",
"description": "阿里云通义千问 Embedding 模型",
"parameters": {
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"api_key": "sk-***",
"provider": "aliyun",
"embedding_parameters": {
"dimension": 1024,
"truncate_prompt_tokens": 0
}
},
"is_default": true,
"status": "active",
"created_at": "2025-08-11T20:10:41.813832+08:00",
"updated_at": "2025-08-11T20:10:41.822354+08:00",
"deleted_at": null
},
{
"id": "8aea788c-bb30-4898-809e-e40c14ffb48c",
"tenant_id": 1,
"name": "qwen-plus",
"type": "KnowledgeQA",
"source": "remote",
"description": "阿里云 Qwen 大模型",
"parameters": {
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"api_key": "sk-***",
"provider": "aliyun",
"embedding_parameters": {
"dimension": 0,
"truncate_prompt_tokens": 0
}
},
"is_default": true,
"status": "active",
"created_at": "2025-08-11T20:10:41.811761+08:00",
"updated_at": "2025-08-11T20:10:41.825381+08:00",
"deleted_at": null
}
]
}
```
**响应**: `data` 为数组,每个元素的字段结构同 `POST /models` 响应。内置模型的 `base_url``api_key` 字段为空字符串。
## GET `/models/:id` - 获取模型详情
**路径参数**:
| 字段 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | -------- |
| id | string | 是 | 模型 ID |
**请求**:
```curl
@@ -367,38 +341,28 @@ curl --location 'http://localhost:8080/api/v1/models/dff7bc94-7885-4dd1-bfd5-bd9
--header 'X-API-Key: your_api_key'
```
**响应**:
```json
{
"success": true,
"data": {
"id": "dff7bc94-7885-4dd1-bfd5-bd96e4df2fc3",
"tenant_id": 1,
"name": "text-embedding-v3",
"type": "Embedding",
"source": "remote",
"description": "阿里云通义千问 Embedding 模型",
"parameters": {
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"api_key": "sk-***",
"provider": "aliyun",
"embedding_parameters": {
"dimension": 1024,
"truncate_prompt_tokens": 0
}
},
"is_default": true,
"status": "active",
"created_at": "2025-08-11T20:10:41.813832+08:00",
"updated_at": "2025-08-11T20:10:41.822354+08:00",
"deleted_at": null
}
}
```
**响应**: 字段结构同 `POST /models` 响应。404 表示模型不存在。
## PUT `/models/:id` - 更新模型
**路径参数**:
| 字段 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | -------- |
| id | string | 是 | 模型 ID |
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------- | ------ | ---- | --------------------------------------------------------------- |
| name | string | 否 | 模型名称(为空字符串时保留原值) |
| description | string | 否 | 模型描述(始终覆盖,传空字符串会清空) |
| type | string | 否 | 模型类型,取值同创建接口 |
| source | string | 否 | 模型来源,取值同创建接口 |
| parameters | object | 否 | 模型参数;`parameter_size` 由后端管理,请求中无需提供;`extra_config` 为空时会沿用旧值 |
> 同样会对 `parameters.base_url` 做 SSRF 校验,失败时返回 400。
**请求**:
```curl
@@ -407,6 +371,8 @@ curl --location --request PUT 'http://localhost:8080/api/v1/models/8fdc464d-8eaa
--header 'X-API-Key: your_api_key' \
--data '{
"name": "gte-rerank-v2",
"type": "Rerank",
"source": "remote",
"description": "阿里云 GTE Rerank 模型 V2",
"parameters": {
"base_url": "https://dashscope.aliyuncs.com/api/v1/services/rerank/text-rerank/text-rerank",
@@ -416,38 +382,16 @@ curl --location --request PUT 'http://localhost:8080/api/v1/models/8fdc464d-8eaa
}'
```
**响应**:
```json
{
"success": true,
"data": {
"id": "8fdc464d-8eaa-44d4-a85b-094b28af5330",
"tenant_id": 1,
"name": "gte-rerank-v2",
"type": "Rerank",
"source": "remote",
"description": "阿里云 GTE Rerank 模型 V2",
"parameters": {
"base_url": "https://dashscope.aliyuncs.com/api/v1/services/rerank/text-rerank/text-rerank",
"api_key": "sk-***",
"provider": "aliyun",
"embedding_parameters": {
"dimension": 0,
"truncate_prompt_tokens": 0
}
},
"is_default": false,
"status": "active",
"created_at": "2025-08-12T10:57:39.512681+08:00",
"updated_at": "2025-08-12T11:00:27.271678+08:00",
"deleted_at": null
}
}
```
**响应**: 字段结构同 `POST /models` 响应,返回更新后的完整模型对象。
## DELETE `/models/:id` - 删除模型
**路径参数**:
| 字段 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | -------- |
| id | string | 是 | 模型 ID |
**请求**:
```curl
@@ -465,37 +409,46 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/models/8fdc464d-8
}
```
404 表示模型不存在。
## 参数说明
### ModelType (模型类型)
| 值 | 说明 | 用途 |
| ------------ | ------------ | ------------------------------ |
| KnowledgeQA | 对话模型 | 知识库问答、对话生成 |
| Embedding | 嵌入模型 | 文本向量化、知识库检索 |
| Rerank | 排序模型 | 检索结果重排序、相关性优化 |
| VLLM | 视觉语言模型 | 多模态分析、图文理解 |
| 值 | 前端别名 | 说明 | 用途 |
| ----------- | ----------- | ------------ | ------------------------------ |
| KnowledgeQA | `chat` | 对话模型 | 知识库问答、对话生成 |
| Embedding | `embedding` | 嵌入模型 | 文本向量化、知识库检索 |
| Rerank | `rerank` | 排序模型 | 检索结果重排序、相关性优化 |
| VLLM | `vllm` | 视觉语言模型 | 多模态分析、图文理解 |
| ASR | `asr` | 语音识别模型 | 音频转写 |
> 创建/更新接口请求体的 `type` 字段使用第一列的后端枚举值(如 `KnowledgeQA``GET /models/providers?model_type=` 查询参数使用第二列的前端别名(如 `chat`)。
### ModelSource (模型来源)
| 值 | 说明 | 配置要求 |
| -------- | ---------- | ------------------------------ |
| local | 本地模型 | 需要已安装 Ollama 并拉取模型 |
| 值 | 说明 | 配置要求 |
| -------- | ---------- | -------------------------------- |
| local | 本地模型 | 需要已安装 Ollama 并拉取模型 |
| remote | 远程 API | 需要提供 `base_url``api_key` |
### Parameters (模型参数)
| 字段 | 类型 | 说明 |
| -------------------- | ------ | -------------------------------------------- |
| base_url | string | API 服务地址远程模型必填 |
| api_key | string | API 密钥远程模型必填 |
| provider | string | 服务商标识(可选,用于选择特定的 API 适配器|
| embedding_parameters | object | Embedding 模型专用参数 |
| extra_config | object | 服务商特定的额外配置 |
| 字段 | 类型 | 必填 | 说明 |
| -------------------- | ----------------- | ---- | ---------------------------------------------------------- |
| base_url | string | 否 | API 服务地址远程模型必填,会经过 SSRF 校验 |
| api_key | string | 否 | API 密钥远程模型必填,存储时使用 AES-256 加密 |
| provider | string | 否 | 服务商标识(见上方支持列表),用于选择特定的 API 适配器 |
| interface_type | string | 否 | 接口风格标识OpenAI 兼容请留空) |
| embedding_parameters | object | 否 | Embedding 模型专用参数,见下方 |
| parameter_size | string | 否 | 模型参数规模(如 `7B`/`13B`/`70B`),通常由后端写入 |
| extra_config | object<string,string> | 否 | 服务商特定的额外配置 |
| custom_headers | object<string,string> | 否 | 调用上游 API 时附加的自定义 HTTP 头;保留头会被忽略 |
| supports_vision | bool | 否 | 模型是否支持图像/多模态输入 |
### EmbeddingParameters (嵌入参数)
| 字段 | 类型 | 说明 |
| ---------------------- | ---- | -------------------------- |
| dimension | int | 向量维度(如768, 1024 |
| truncate_prompt_tokens | int | 截断 Token 数0 表示不截断)|
| 字段 | 类型 | 必填 | 说明 |
| ---------------------- | ---- | ---- | ------------------------------- |
| dimension | int | 否 | 向量维度(如 7681024 |
| truncate_prompt_tokens | int | 否 | 截断 Token 数0 表示不截断) |

File diff suppressed because it is too large Load Diff

View File

@@ -2,20 +2,24 @@
[返回目录](./README.md)
| 方法 | 路径 | 描述 |
| ------ | --------------------------------------- | --------------------- |
| POST | `/sessions` | 创建会话 |
| GET | `/sessions/:id` | 获取会话详情 |
| GET | `/sessions` | 获取租户的会话列表 |
| PUT | `/sessions/:id` | 更新会话 |
| DELETE | `/sessions/:id` | 删除会话 |
| DELETE | `/sessions/:id/messages` | 清空会话消息 |
| DELETE | `/sessions/batch` | 批量删除会话 |
| POST | `/sessions/:session_id/generate_title` | 生成会话标题 |
| POST | `/sessions/:session_id/stop` | 停止生成 |
| GET | `/sessions/continue-stream/:session_id` | 继续未完成的流式响应 |
会话Session是纯粹的对话容器仅存储基础信息标题、描述、置顶状态等。所有与知识库、模型、检索策略相关的配置均在查询时由 Custom Agent 提供,不再存储在会话中。
> **说明**会话Session是纯粹的对话容器仅存储基础信息标题、描述。所有与知识库、模型、检索策略相关的配置均在查询时由 Custom Agent 提供,不再存储在会话中。
| 方法 | 路径 | 描述 |
| ------ | ------------------------------------------ | ----------------------------- |
| POST | `/sessions` | 创建会话 |
| DELETE | `/sessions/batch` | 批量删除会话 |
| GET | `/sessions/:id` | 获取会话详情 |
| GET | `/sessions` | 获取当前租户的会话列表 |
| PUT | `/sessions/:id` | 更新会话 |
| DELETE | `/sessions/:id` | 删除会话 |
| DELETE | `/sessions/:id/messages` | 清空会话消息 |
| POST | `/sessions/:session_id/generate_title` | 生成会话标题 |
| POST | `/sessions/:session_id/stop` | 停止生成 |
| POST | `/sessions/:session_id/pin` | 置顶会话 |
| DELETE | `/sessions/:id/pin` | 取消置顶会话 |
| GET | `/sessions/continue-stream/:session_id` | 继续未完成的流式响应 |
> **路由命名说明**:置顶接口的 POST 与 DELETE 使用了不同的路径参数名POST 用 `:session_id`DELETE 用 `:id`)。这是由于 gin 路由器为每个 HTTP 方法维护独立的 radix tree且既有树中的通配符命名不同必须保留以避免注册时的 `wildcard conflicts` panic。两者语义上都指会话 ID。
## POST `/sessions` - 创建会话
@@ -33,122 +37,6 @@ curl --location 'http://localhost:8080/api/v1/sessions' \
**请求参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------- | ------ | ---- | ---------- |
| `title` | string | 否 | 会话标题 |
| `description` | string | 否 | 会话描述 |
**响应**:
```json
{
"success": true,
"data": {
"id": "411d6b70-9a85-4d03-bb74-aab0fd8bd12f",
"title": "我的新对话",
"description": "关于 AI 的讨论",
"tenant_id": 1,
"created_at": "2026-03-27T12:26:19.611616+08:00",
"updated_at": "2026-03-27T12:26:19.611616+08:00",
"deleted_at": null
}
}
```
## GET `/sessions/:id` - 获取会话详情
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/sessions/ceb9babb-1e30-41d7-817d-fd584954304b' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ---- | ------ | ---- | ------ |
| `id` | string | 是 | 会话ID |
**响应**:
```json
{
"success": true,
"data": {
"id": "ceb9babb-1e30-41d7-817d-fd584954304b",
"title": "模型优化策略",
"description": "",
"tenant_id": 1,
"created_at": "2026-03-27T10:24:38.308596+08:00",
"updated_at": "2026-03-27T10:25:41.317761+08:00",
"deleted_at": null
}
}
```
## GET `/sessions?page=&page_size=` - 获取租户的会话列表
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/sessions?page=1&page_size=10' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**查询参数**:
| 字段 | 类型 | 必填 | 描述 |
| ----------- | ---- | ---- | -------------------- |
| `page` | int | 否 | 页码(默认 1 |
| `page_size` | int | 否 | 每页数量(默认 10 |
**响应**:
```json
{
"success": true,
"data": [
{
"id": "411d6b70-9a85-4d03-bb74-aab0fd8bd12f",
"title": "我的新对话",
"description": "",
"tenant_id": 1,
"created_at": "2026-03-27T12:26:19.611616+08:00",
"updated_at": "2026-03-27T12:26:19.611616+08:00",
"deleted_at": null
}
],
"total": 1,
"page": 1,
"page_size": 10
}
```
## PUT `/sessions/:id` - 更新会话
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/sessions/411d6b70-9a85-4d03-bb74-aab0fd8bd12f' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"title": "WeKnora 技术讨论",
"description": "关于 WeKnora 架构的讨论"
}'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ---- | ------ | ---- | ------ |
| `id` | string | 是 | 会话ID |
**请求参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------- | ------ | ---- | -------- |
| `title` | string | 否 | 会话标题 |
@@ -161,67 +49,19 @@ curl --location --request PUT 'http://localhost:8080/api/v1/sessions/411d6b70-9a
"success": true,
"data": {
"id": "411d6b70-9a85-4d03-bb74-aab0fd8bd12f",
"title": "WeKnora 技术讨论",
"description": "关于 WeKnora 架构的讨论",
"title": "我的新对话",
"description": "关于 AI 的讨论",
"tenant_id": 1,
"user_id": "u-001",
"is_pinned": false,
"created_at": "2026-03-27T12:26:19.611616+08:00",
"updated_at": "2026-03-27T14:20:56.738424+08:00",
"updated_at": "2026-03-27T12:26:19.611616+08:00",
"deleted_at": null
}
}
```
## DELETE `/sessions/:id` - 删除会话
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/sessions/411d6b70-9a85-4d03-bb74-aab0fd8bd12f' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ---- | ------ | ---- | ------ |
| `id` | string | 是 | 会话ID |
**响应**:
```json
{
"success": true,
"message": "Session deleted successfully"
}
```
## DELETE `/sessions/:id/messages` - 清空会话消息
删除会话中的所有消息,同时清除 LLM 上下文和聊天历史知识库条目。会话本身保留。
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/sessions/ceb9babb-1e30-41d7-817d-fd584954304b/messages' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ---- | ------ | ---- | ------ |
| `id` | string | 是 | 会话ID |
**响应**:
```json
{
"success": true,
"message": "Session messages cleared successfully"
}
```
> 通过 API-Key 调用时 `user_id` 可能为空,此时会话以租户级可见。
## DELETE `/sessions/batch` - 批量删除会话
@@ -254,10 +94,10 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/sessions/batch' \
**请求参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------ | -------- | ---- | -------------------------------------------------------- |
| `ids` | string[] | 否 | 要删除的会话 ID 列表(`delete_all` 为 false 时必填) |
| `delete_all` | bool | 否 | 设为 `true` 时删除当前租户的所有会话,忽略 `ids` 字段 |
| 字段 | 类型 | 必填 | 描述 |
| ------------ | -------- | ---- | ---------------------------------------------------------- |
| `ids` | string[] | 否 | 要删除的会话 ID 列表(`delete_all``false` 时必填) |
| `delete_all` | bool | 否 | 设为 `true` 时删除当前租户的所有会话,忽略 `ids` 字段 |
**响应**:
@@ -268,6 +108,198 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/sessions/batch' \
}
```
`delete_all=true``message``"All sessions deleted successfully"`
## GET `/sessions/:id` - 获取会话详情
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/sessions/ceb9babb-1e30-41d7-817d-fd584954304b' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ---- | ------ | ---- | ------- |
| `id` | string | 是 | 会话 ID |
**响应**:
```json
{
"success": true,
"data": {
"id": "ceb9babb-1e30-41d7-817d-fd584954304b",
"title": "模型优化策略",
"description": "",
"tenant_id": 1,
"user_id": "u-001",
"is_pinned": true,
"pinned_at": "2026-04-01T09:12:33.123456+08:00",
"created_at": "2026-03-27T10:24:38.308596+08:00",
"updated_at": "2026-03-27T10:25:41.317761+08:00",
"deleted_at": null
}
}
```
会话不存在时返回 `404`
## GET `/sessions` - 获取当前租户的会话列表
获取当前租户的会话列表,支持分页、关键字搜索、按来源 / Agent 过滤。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/sessions?page=1&page_size=10&keyword=AI&source=web' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**查询参数**:
| 字段 | 类型 | 必填 | 描述 |
| ----------- | ------ | ---- | ----------------------------------------------------------------- |
| `page` | int | 否 | 页码(默认 1 |
| `page_size` | int | 否 | 每页数量(默认 10 |
| `keyword` | string | 否 | 按标题模糊匹配ILIKE `%keyword%` |
| `source` | string | 否 | 来源过滤:`web`(无 IM 映射)或 IM 平台名,如 `feishu``wechat``slack` |
| `agent_id` | string | 否 | 按 Agent 过滤(仅对 IM 会话生效) |
**响应**:
```json
{
"success": true,
"data": [
{
"id": "411d6b70-9a85-4d03-bb74-aab0fd8bd12f",
"title": "我的新对话",
"description": "",
"tenant_id": 1,
"user_id": "u-001",
"is_pinned": true,
"pinned_at": "2026-04-01T09:12:33.123456+08:00",
"created_at": "2026-03-27T12:26:19.611616+08:00",
"updated_at": "2026-03-27T12:26:19.611616+08:00",
"deleted_at": null,
"im_platform": "feishu",
"im_chat_id": "oc_xxx",
"im_agent_id": "agent-001"
}
],
"total": 1,
"page": 1,
"page_size": 10
}
```
> 列表项始终包含置顶状态字段IM 来源相关字段(`im_platform`、`im_chat_id`、`im_thread_id`、`im_user_id`、`im_agent_id`、`im_channel_id`)仅对 IM 创建的会话填充Web 会话省略。
## PUT `/sessions/:id` - 更新会话
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/sessions/411d6b70-9a85-4d03-bb74-aab0fd8bd12f' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"title": "WeKnora 技术讨论",
"description": "关于 WeKnora 架构的讨论"
}'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ---- | ------ | ---- | ------- |
| `id` | string | 是 | 会话 ID |
**请求参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------- | ------ | ---- | -------- |
| `title` | string | 否 | 会话标题 |
| `description` | string | 否 | 会话描述 |
**响应**:
```json
{
"success": true,
"data": {
"id": "411d6b70-9a85-4d03-bb74-aab0fd8bd12f",
"title": "WeKnora 技术讨论",
"description": "关于 WeKnora 架构的讨论",
"tenant_id": 1,
"user_id": "u-001",
"is_pinned": false,
"created_at": "2026-03-27T12:26:19.611616+08:00",
"updated_at": "2026-03-27T14:20:56.738424+08:00",
"deleted_at": null
}
}
```
会话不存在时返回 `404`
## DELETE `/sessions/:id` - 删除会话
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/sessions/411d6b70-9a85-4d03-bb74-aab0fd8bd12f' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ---- | ------ | ---- | ------- |
| `id` | string | 是 | 会话 ID |
**响应**:
```json
{
"success": true,
"message": "Session deleted successfully"
}
```
## DELETE `/sessions/:id/messages` - 清空会话消息
删除会话中的所有消息,同时清除 LLM 上下文和聊天历史知识库条目。会话本身保留。
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/sessions/ceb9babb-1e30-41d7-817d-fd584954304b/messages' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ---- | ------ | ---- | ------- |
| `id` | string | 是 | 会话 ID |
**响应**:
```json
{
"success": true,
"message": "Session messages cleared successfully"
}
```
## POST `/sessions/:session_id/generate_title` - 生成会话标题
根据消息内容自动生成会话标题。
@@ -294,9 +326,9 @@ curl --location 'http://localhost:8080/api/v1/sessions/ceb9babb-1e30-41d7-817d-f
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ------ |
| `session_id` | string | 是 | 会话ID |
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ------- |
| `session_id` | string | 是 | 会话 ID |
**请求参数**:
@@ -315,7 +347,7 @@ curl --location 'http://localhost:8080/api/v1/sessions/ceb9babb-1e30-41d7-817d-f
## POST `/sessions/:session_id/stop` - 停止生成
停止当前正在进行的生成任务
停止当前正在进行的助手回复生成任务。后端会向流中追加一条 `stop` 事件,由活跃的 SSE 处理协程感知并发起取消
**请求**:
@@ -330,15 +362,15 @@ curl --location 'http://localhost:8080/api/v1/sessions/7c966c74-610e-4516-8d5b-0
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ------ |
| `session_id` | string | 是 | 会话ID |
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ------- |
| `session_id` | string | 是 | 会话 ID |
**请求参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ------------------------ |
| `message_id` | string | 是 | 要停止生成的助手消息 ID |
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ----------------------- |
| `message_id` | string | 是 | 要停止生成的助手消息 ID |
**响应**:
@@ -349,14 +381,87 @@ curl --location 'http://localhost:8080/api/v1/sessions/7c966c74-610e-4516-8d5b-0
}
```
若消息已完成(无需停止):
```json
{
"success": true,
"message": "Message already completed"
}
```
> 消息不属于当前会话返回 `403`;消息或会话不存在返回 `404`。
## POST `/sessions/:session_id/pin` - 置顶会话
将指定会话置顶(用户维度)。
**请求**:
```curl
curl --location --request POST 'http://localhost:8080/api/v1/sessions/ceb9babb-1e30-41d7-817d-fd584954304b/pin' \
--header 'X-API-Key: sk-xxxxx'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ------- |
| `session_id` | string | 是 | 会话 ID |
**响应**:
```json
{
"success": true,
"is_pinned": true
}
```
会话不存在或对当前用户不可见时返回 `404`
## DELETE `/sessions/:id/pin` - 取消置顶会话
取消指定会话的置顶。
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/sessions/ceb9babb-1e30-41d7-817d-fd584954304b/pin' \
--header 'X-API-Key: sk-xxxxx'
```
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ---- | ------ | ---- | ------- |
| `id` | string | 是 | 会话 ID |
**响应**:
```json
{
"success": true,
"is_pinned": false
}
```
> 同上,`POST /pin` 与 `DELETE /pin` 路径参数名不同,但语义上都是会话 ID。
## GET `/sessions/continue-stream/:session_id` - 继续未完成的流式响应
重新连接正在进行的流式响应先回放已有事件,再继续接收新事件
用于在 SSE 连接断开后重新连接正在进行的流式响应先回放该消息已产生的所有事件,再继续推送后续事件,直至 `complete`
**路径参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ------- |
| `session_id` | string | 是 | 会话 ID |
**查询参数**:
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ------------------------------------------------------------------------- |
| 字段 | 类型 | 必填 | 描述 |
| ------------ | ------ | ---- | ------------------------------------------------------------------------------- |
| `message_id` | string | 是 | 从 `/messages/:session_id/load` 接口中获取的 `is_completed``false` 的消息 ID |
**请求**:
@@ -369,4 +474,4 @@ curl --location 'http://localhost:8080/api/v1/sessions/continue-stream/ceb9babb-
**响应格式**:
服务器端事件流Server-Sent Events`/knowledge-chat/:session_id` 返回结果一致
服务器端事件流Server-Sent Events事件结构`/knowledge-chat/:session_id``/agent-chat/:session_id` 返回结果一致。若该消息当前在流中已无事件返回 `404 No stream events found`;若消息记录不存在返回 `404 Incomplete message not found`

View File

@@ -10,7 +10,6 @@
| POST | `/system/docreader/reconnect` | 重连文档解析服务 |
| GET | `/system/storage-engine-status` | 获取存储引擎状态 |
| POST | `/system/storage-engine-check` | 检查存储引擎连通性 |
| GET | `/system/minio/buckets` | 获取 MinIO 桶列表 |
## GET `/system/info` - 获取系统信息
@@ -201,34 +200,4 @@ curl --location 'http://localhost:8080/api/v1/system/storage-engine-check' \
}
```
## GET `/system/minio/buckets` - 获取 MinIO 桶列表
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/system/minio/buckets' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**响应**:
```json
{
"data": {
"buckets": [
{
"name": "weknora",
"policy": "read-write",
"created_at": "2025-08-01T10:00:00+08:00"
},
{
"name": "weknora-backup",
"policy": "read-only",
"created_at": "2025-08-05T14:00:00+08:00"
}
]
},
"success": true
}
```

View File

@@ -20,7 +20,7 @@
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/tags?page=1&page_size=10' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
@@ -65,11 +65,25 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/tags?p
## POST `/knowledge-bases/:id/tags` - 创建标签
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | ----------- |
| id | string | 知识库 ID |
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | ------------------------ |
| name | string | 是 | 标签名(同库内唯一) |
| color | string | 否 | 标签颜色CSS 颜色字符串) |
| sort_order | int | 否 | 排序值(数值越小越靠前) |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/tags' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"name": "产品手册",
@@ -98,11 +112,20 @@ curl --location 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/tags'
## PUT `/knowledge-bases/:id/tags/:tag_id` - 更新标签
**路径参数**:
| 字段 | 类型 | 说明 |
| ------ | ------ | ----------- |
| id | string | 知识库 ID |
| tag_id | string | 标签 ID |
**参数说明(请求体)**: 同创建接口,所有字段均可选;未传则保留原值。
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/tags/tag-00000003' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"name": "产品手册更新",
@@ -130,14 +153,24 @@ curl --location --request PUT 'http://localhost:8080/api/v1/knowledge-bases/kb-0
## DELETE `/knowledge-bases/:id/tags/:tag_id` - 删除标签
**路径参数**:
| 字段 | 类型 | 说明 |
| ------ | ------ | -------- |
| id | string | 知识库 ID |
| tag_id | string | 标签 ID |
**查询参数**:
- `force`: 设置为 `true` 时强制删除(即使标签被引用)
| 字段 | 类型 | 默认 | 说明 |
| ----- | ------- | ----- | --------------------------------------------- |
| force | boolean | false | 设置为 `true` 时强制删除(即使标签被引用) |
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/knowledge-bases/kb-00000001/tags/tag-00000003?force=true' \
--header 'X-API-Key: sk-vQHV2NZI_LK5W7wHQvH3yGYExX8YnhaHwZipUYbiZKCYJbBQ' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```

View File

@@ -2,249 +2,23 @@
[返回目录](./README.md)
| 方法 | 路径 | 描述 |
| ------ | -------------- | --------------------- |
| POST | `/tenants` | 创建新租户 |
| GET | `/tenants/:id` | 获取指定租户信息 |
| PUT | `/tenants/:id` | 更新租户信息 |
| DELETE | `/tenants/:id` | 删除租户 |
| GET | `/tenants` | 获取租户列表 |
| GET | `/tenants/all` | 获取所有租户列表(需跨租户权限) |
| GET | `/tenants/search` | 搜索租户(需跨租户权限) |
| GET | `/tenants/kv/:key` | 获取租户KV配置 |
| PUT | `/tenants/kv/:key` | 更新租户KV配置 |
包含两组接口:
- 租户 CRUD`/tenants``/tenants/:id``/tenants/:id/api-key`):当前认证用户对自己所属租户进行管理;跨租户访问需要管理员权限。
- 跨租户接口(`/tenants/all``/tenants/search`**需要服务端启用 `EnableCrossTenantAccess` 且当前用户具备 `CanAccessAllTenants` 权限**,否则返回 403。
- 租户 KV 配置(`/tenants/kv/:key`):当前租户级别的通用配置项,**`tenant_id` 从认证上下文中获取,不在 URL 中传入**。
## POST `/tenants` - 创建新租户
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/tenants' \
--header 'Content-Type: application/json' \
--data '{
"name": "weknora",
"description": "weknora tenants",
"business": "wechat",
"retriever_engines": {
"engines": [
{
"retriever_type": "keywords",
"retriever_engine_type": "postgres"
},
{
"retriever_type": "vector",
"retriever_engine_type": "postgres"
}
]
}
}'
```
**响应**:
```json
{
"data": {
"id": 10000,
"name": "weknora",
"description": "weknora tenants",
"api_key": "sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240,
"storage_used": 0,
"created_at": "2025-08-11T20:37:28.396980093+08:00",
"updated_at": "2025-08-11T20:37:28.396980301+08:00",
"deleted_at": null
},
"success": true
}
```
## GET `/tenants/:id` - 获取指定租户信息
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/tenants/10000' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG'
```
**响应**:
```json
{
"data": {
"id": 10000,
"name": "weknora",
"description": "weknora tenants",
"api_key": "sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240,
"storage_used": 0,
"created_at": "2025-08-11T20:37:28.39698+08:00",
"updated_at": "2025-08-11T20:37:28.405693+08:00",
"deleted_at": null
},
"success": true
}
```
## PUT `/tenants/:id` - 更新租户信息
注意 API Key 会变更
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/tenants/10000' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-KREi84yPtahKxMtIMOW-Cxx2dxb9xROpUuDSpi3vbiC1QVDe' \
--data '{
"name": "weknora new",
"description": "weknora tenants new",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240
}'
```
**响应**:
```json
{
"data": {
"id": 10000,
"name": "weknora new",
"description": "weknora tenants new",
"api_key": "sk-IKtd9JGV4-aPGQ6RiL8YJu9Vzb3-ae4lgFkjFJZmhvUn2mLu",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240,
"storage_used": 0,
"created_at": "0001-01-01T00:00:00Z",
"updated_at": "2025-08-11T20:49:02.13421034+08:00",
"deleted_at": null
},
"success": true
}
```
## DELETE `/tenants/:id` - 删除租户
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/tenants/10000' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-IKtd9JGV4-aPGQ6RiL8YJu9Vzb3-ae4lgFkjFJZmhvUn2mLu'
```
**响应**:
```json
{
"message": "Tenant deleted successfully",
"success": true
}
```
## GET `/tenants` - 获取租户列表
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/tenants' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-An7_t_izCKFIJ4iht9Xjcjnj_MC48ILvwezEDki9ScfIa7KA'
```
**响应**:
```json
{
"data": {
"items": [
{
"id": 10002,
"name": "weknora",
"description": "weknora tenants",
"api_key": "sk-An7_t_izCKFIJ4iht9Xjcjnj_MC48ILvwezEDki9ScfIa7KA",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240,
"storage_used": 0,
"created_at": "2025-08-11T20:52:58.05679+08:00",
"updated_at": "2025-08-11T20:52:58.060495+08:00",
"deleted_at": null
}
]
},
"success": true
}
```
| 方法 | 路径 | 描述 |
| ------ | -------------------------- | ------------------------------------------------- |
| GET | `/tenants/all` | 获取所有租户列表(需跨租户权限) |
| GET | `/tenants/search` | 分页搜索租户(需跨租户权限) |
| POST | `/tenants` | 创建新租户 |
| GET | `/tenants/:id` | 获取指定租户信息 |
| PUT | `/tenants/:id` | 更新租户信息 |
| DELETE | `/tenants/:id` | 删除租户 |
| POST | `/tenants/:id/api-key` | 重置租户 API Key |
| GET | `/tenants` | 获取当前用户可见的租户列表 |
| GET | `/tenants/kv/:key` | 获取当前租户的 KV 配置tenant 由认证上下文确定) |
| PUT | `/tenants/kv/:key` | 更新当前租户的 KV 配置tenant 由认证上下文确定) |
## GET `/tenants/all` - 获取所有租户列表
@@ -330,56 +104,41 @@ curl --location 'http://localhost:8080/api/v1/tenants/search?keyword=weknora&pag
}
```
## GET `/tenants/kv/:key` - 获取租户KV配置
## POST `/tenants` - 创建新租户
获取指定键名的租户配置项
创建一个新的租户,服务端会自动生成租户 ID 与 API Key
**支持的 key 值**:
- `agent-config`: Agent 配置
- `web-search-config`: 网页搜索配置
- `conversation-config`: 对话配置
- `prompt-templates`: 提示词模板
- `parser-engine-config`: 解析引擎配置
- `storage-engine-config`: 存储引擎配置
- `chat-history-config`: 聊天历史配置
- `retrieval-config`: 检索配置
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------------- | ------ | ---- | ------------------------------------------------------ |
| name | string | 是 | 租户名称 |
| description | string | 否 | 租户描述 |
| business | string | 否 | 业务标识(如 `wechat` |
| retriever_engines | object | 否 | 检索引擎组合配置(`engines` 数组:每项含 `retriever_type``retriever_engine_type` |
| storage_quota | int | 否 | 存储配额(字节) |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/tenants/kv/agent-config' \
curl --location 'http://localhost:8080/api/v1/tenants' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-An7_t_izCKFIJ4iht9Xjcjnj_MC48ILvwezEDki9ScfIa7KA'
```
**响应**:
```json
{
"data": {
"key": "agent-config",
"value": {
"enabled": true,
"max_iterations": 10
}
},
"success": true
}
```
## PUT `/tenants/kv/:key` - 更新租户KV配置
更新指定键名的租户配置项。请求体内容根据不同的 key 值而有所不同。
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/tenants/kv/agent-config' \
--header 'Content-Type: application/json' \
--header 'X-API-Key: sk-An7_t_izCKFIJ4iht9Xjcjnj_MC48ILvwezEDki9ScfIa7KA' \
--data '{
"enabled": true,
"max_iterations": 20
"name": "weknora",
"description": "weknora tenants",
"business": "wechat",
"retriever_engines": {
"engines": [
{
"retriever_type": "keywords",
"retriever_engine_type": "postgres"
},
{
"retriever_type": "vector",
"retriever_engine_type": "postgres"
}
]
}
}'
```
@@ -388,12 +147,364 @@ curl --location --request PUT 'http://localhost:8080/api/v1/tenants/kv/agent-con
```json
{
"data": {
"key": "agent-config",
"value": {
"enabled": true,
"max_iterations": 20
}
"id": 10000,
"name": "weknora",
"description": "weknora tenants",
"api_key": "sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240,
"storage_used": 0,
"created_at": "2025-08-11T20:37:28.396980093+08:00",
"updated_at": "2025-08-11T20:37:28.396980301+08:00",
"deleted_at": null
},
"success": true
}
```
## GET `/tenants/:id` - 获取指定租户信息
获取指定 ID 的租户详情。只能访问自己所属租户;访问其他租户需要跨租户权限,否则返回 403。
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ---- | ------- |
| id | int | 租户 ID |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/tenants/10000' \
--header 'X-API-Key: sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG' \
--header 'Content-Type: application/json'
```
**响应**:
```json
{
"data": {
"id": 10000,
"name": "weknora",
"description": "weknora tenants",
"api_key": "sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240,
"storage_used": 0,
"created_at": "2025-08-11T20:37:28.39698+08:00",
"updated_at": "2025-08-11T20:37:28.405693+08:00",
"deleted_at": null
},
"success": true
}
```
## PUT `/tenants/:id` - 更新租户信息
更新指定租户的基础信息。访问规则同 `GET /tenants/:id`
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ---- | ------- |
| id | int | 租户 ID |
**参数说明(请求体)**: 与 `POST /tenants` 相同字段;未传字段保持原值。
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/tenants/10000' \
--header 'X-API-Key: sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG' \
--header 'Content-Type: application/json' \
--data '{
"name": "weknora new",
"description": "weknora tenants new",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240
}'
```
**响应**:
```json
{
"data": {
"id": 10000,
"name": "weknora new",
"description": "weknora tenants new",
"api_key": "sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240,
"storage_used": 0,
"created_at": "2025-08-11T20:37:28.39698+08:00",
"updated_at": "2025-08-11T20:49:02.13421034+08:00",
"deleted_at": null
},
"success": true
}
```
## DELETE `/tenants/:id` - 删除租户
删除指定租户。访问规则同 `GET /tenants/:id`
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ---- | ------- |
| id | int | 租户 ID |
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/tenants/10000' \
--header 'X-API-Key: sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG' \
--header 'Content-Type: application/json'
```
**响应**:
```json
{
"message": "Tenant deleted successfully",
"success": true
}
```
## POST `/tenants/:id/api-key` - 重置租户 API Key
为指定租户生成新的 API Key旧 Key 立即失效。访问规则同 `GET /tenants/:id`
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ---- | ------- |
| id | int | 租户 ID |
**请求**:
```curl
curl --location --request POST 'http://localhost:8080/api/v1/tenants/10000/api-key' \
--header 'X-API-Key: sk-aaLRAgvCRJcmtiL2vLMeB1FB5UV0Q-qB7DlTE1pJ9KA93XZG' \
--header 'Content-Type: application/json'
```
**响应**:
```json
{
"data": {
"api_key": "sk-IKtd9JGV4-aPGQ6RiL8YJu9Vzb3-ae4lgFkjFJZmhvUn2mLu"
},
"success": true
}
```
## GET `/tenants` - 获取租户列表
返回当前认证上下文对应的租户(普通用户为单条;管理员仍只返回自身租户)。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/tenants' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**响应**:
```json
{
"data": {
"items": [
{
"id": 10002,
"name": "weknora",
"description": "weknora tenants",
"api_key": "sk-An7_t_izCKFIJ4iht9Xjcjnj_MC48ILvwezEDki9ScfIa7KA",
"status": "active",
"retriever_engines": {
"engines": [
{
"retriever_engine_type": "postgres",
"retriever_type": "keywords"
},
{
"retriever_engine_type": "postgres",
"retriever_type": "vector"
}
]
},
"business": "wechat",
"storage_quota": 10737418240,
"storage_used": 0,
"created_at": "2025-08-11T20:52:58.05679+08:00",
"updated_at": "2025-08-11T20:52:58.060495+08:00",
"deleted_at": null
}
]
},
"success": true
}
```
## GET `/tenants/kv/:key` - 获取租户 KV 配置
获取当前租户的 KV 配置项。**租户 ID 从认证上下文中获取**(即由 `X-API-Key` / Bearer Token 对应的租户决定URL 中不需要也不接受 tenant_id。
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | ---------------------------------------------- |
| key | string | 配置键名(见下方支持的 key 列表,不支持的键返回 400 |
**支持的 key 值**:
| key | 说明 |
| ---------------------- | ----------------------------- |
| `agent-config` | Agent 配置最大迭代次数、温度、System Prompt、可用工具等 |
| `web-search-config` | 网页搜索配置 |
| `conversation-config` | 普通模式会话/对话配置 |
| `prompt-templates` | 系统提示词模板(只读,按用户语言本地化) |
| `parser-engine-config` | 解析引擎配置(如 MinerU |
| `storage-engine-config`| 存储引擎配置Local/MinIO/COS |
| `chat-history-config` | 聊天历史索引配置 |
| `retrieval-config` | 全局检索配置 |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/tenants/kv/agent-config' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json'
```
**响应(以 `agent-config` 为例)**:
```json
{
"data": {
"max_iterations": 10,
"allowed_tools": ["knowledge_search", "web_search"],
"temperature": 0.3,
"system_prompt": "...",
"use_custom_system_prompt": false,
"available_tools": [
{ "name": "knowledge_search", "label": "知识库检索", "description": "..." }
],
"available_placeholders": [
{ "name": "web_search_status", "label": "联网搜索状态", "description": "..." }
]
},
"success": true
}
```
失败时(不支持的键):
```json
{ "success": false, "error": "unsupported key" }
```
## PUT `/tenants/kv/:key` - 更新租户 KV 配置
更新当前租户的 KV 配置项。**租户 ID 从认证上下文中获取**,请求体结构按 `key` 不同而异。`prompt-templates` 为只读,不支持 PUT。
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | ----------------------------- |
| key | string | 配置键名(见 GET 接口的支持列表,`prompt-templates` 除外) |
**请求(以 `agent-config` 为例)**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/tenants/kv/agent-config' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"max_iterations": 20,
"temperature": 0.3,
"system_prompt": ""
}'
```
**响应**:
```json
{
"data": {
"max_iterations": 20,
"allowed_tools": ["knowledge_search", "web_search"],
"temperature": 0.3,
"system_prompt": "",
"use_custom_system_prompt": false
},
"message": "Agent configuration updated successfully",
"success": true
}
```
**约束**:
- `agent-config`: `max_iterations` 取值范围 `(0, 30]``temperature` 取值范围 `[0, 2]`
- `web-search-config`: `max_results` 取值范围 `[1, 50]`
- `conversation-config`: 包含多项阈值校验(如 `keyword_threshold` / `vector_threshold``[0, 1]``rerank_threshold``[-10, 10]``temperature``[0, 2]``max_completion_tokens``[1, 100000]` 等)。
- `retrieval-config`: `embedding_top_k` / `rerank_top_k``[0, 200]`;阈值范围同上。
- `storage-engine-config`: `default_provider` 必须在 `STORAGE_ALLOW_LIST` 允许的列表内。
- `chat-history-config`: 启用且设置了 `embedding_model_id` 而尚未关联知识库时,会自动创建一个隐藏知识库并将其 ID 写入配置。

View File

@@ -2,24 +2,22 @@
[返回目录](./README.md)
向量存储VectorStoreAPI 用于管理向量数据库连接配置支持 Elasticsearch、PostgreSQL、Qdrant、Milvus、Weaviate、Tencent VectorDB、SQLite 七种引擎类型
向量存储VectorStoreAPI 用于管理租户的向量数据库连接配置支持 Elasticsearch、PostgreSQL、Qdrant、Milvus、Weaviate、Tencent VectorDB、SQLite 等引擎。接口同时管理用户在 DB 中创建的配置(`source: "user"`)以及通过 `RETRIEVE_DRIVER` 环境变量配置的虚拟存储(`source: "env"`,只读)
| 方法 | 路径 | 描述 |
| ------ | ---------------------------- | ------------------------------ |
| GET | `/vector-stores/types` | 获取支持的引擎类型及配置字段 |
| POST | `/vector-stores/test` | 使用原始凭据测试连接(不保存) |
| POST | `/vector-stores` | 创建向量存储 |
| GET | `/vector-stores` | 获取向量存储列表 |
| GET | `/vector-stores/:id` | 获取向量存储详情 |
| PUT | `/vector-stores/:id` | 更新向量存储(仅名称可改) |
| DELETE | `/vector-stores/:id` | 删除向量存储(软删除) |
| POST | `/vector-stores/:id/test` | 测试已保存的向量存储连接 |
---
| 方法 | 路径 | 描述 |
| ------ | ---------------------------- | -------------------------------- |
| GET | `/vector-stores/types` | 获取支持的引擎类型及字段元数据 |
| POST | `/vector-stores/test` | 使用原始凭据测试连接(不落库) |
| POST | `/vector-stores` | 创建向量存储 |
| GET | `/vector-stores` | 获取向量存储列表 |
| GET | `/vector-stores/:id` | 获取向量存储详情 |
| PUT | `/vector-stores/:id` | 更新向量存储(仅名称可改) |
| DELETE | `/vector-stores/:id` | 删除向量存储(软删除) |
| POST | `/vector-stores/:id/test` | 测试已保存或环境变量存储的连通性 |
## GET `/vector-stores/types` - 获取支持的引擎类型
返回所有支持的引擎类型,包含连接配置索引配置字段定义,可用于前端表单生成。
返回所有支持的引擎类型及其连接配置字段、索引配置字段定义,可用于前端动态表单生成。系统级元数据,无需鉴权感知,但仍需 `X-API-Key`
**请求**:
@@ -38,40 +36,45 @@ curl --location 'http://localhost:8080/api/v1/vector-stores/types' \
"type": "elasticsearch",
"display_name": "Elasticsearch (Keywords + Vector)",
"connection_fields": [
{"name": "addr", "type": "string", "required": true, "description": "Elasticsearch URL (e.g., http://localhost:9200)"},
{"name": "username", "type": "string", "required": false},
{"name": "password", "type": "string", "required": false, "sensitive": true}
{ "name": "addr", "type": "string", "required": true, "description": "Elasticsearch URL (e.g., http://localhost:9200)" },
{ "name": "username", "type": "string", "required": false },
{ "name": "password", "type": "string", "required": false, "sensitive": true }
],
"index_fields": [
{"name": "index_name", "type": "string", "required": false, "default": "xwrag_default"},
{"name": "number_of_shards", "type": "number", "required": false},
{"name": "number_of_replicas", "type": "number", "required": false}
{ "name": "index_name", "type": "string", "required": false, "default": "xwrag_default" },
{ "name": "number_of_shards", "type": "number", "required": false },
{ "name": "number_of_replicas", "type": "number", "required": false }
]
},
{
"type": "postgres",
"display_name": "PostgreSQL (Keywords + Vector)",
"connection_fields": [
{"name": "use_default_connection", "type": "boolean", "required": false, "default": true, "description": "Use the application's default database connection"},
{"name": "addr", "type": "string", "required": false, "description": "PostgreSQL connection string (required if use_default_connection is false)"},
{"name": "username", "type": "string", "required": false},
{"name": "password", "type": "string", "required": false, "sensitive": true}
{ "name": "use_default_connection", "type": "boolean", "required": false, "default": true, "description": "Use the application's default database connection" },
{ "name": "addr", "type": "string", "required": false, "description": "PostgreSQL connection string (required if use_default_connection is false)" },
{ "name": "username", "type": "string", "required": false },
{ "name": "password", "type": "string", "required": false, "sensitive": true }
]
}
]
}
```
---
## POST `/vector-stores/test` - 使用原始凭据测试连接
## POST `/vector-stores/test` - 测试原始凭据连接
用前端表单中尚未保存的凭据执行一次连通性测试,不会写入数据库。成功时返回自动检测到的服务器版本(如 ES 版本号);某些引擎(如 Milvus、SQLite无法检测版本`version` 会返回空字符串。
使用提供的凭据执行连接测试,不保存任何数据。成功时返回自动检测到的服务器版本。
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------------- | ------ | ---- | ------------------------------------------------------------- |
| engine_type | string | 是 | 引擎类型,取自 `/vector-stores/types``type` |
| connection_config | object | 是 | 该引擎对应的连接配置字段(与 `connection_fields` 对应) |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/vector-stores/test' \
curl --location --request POST 'http://localhost:8080/api/v1/vector-stores/test' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
@@ -93,8 +96,6 @@ curl --location 'http://localhost:8080/api/v1/vector-stores/test' \
}
```
> `version` 字段包含自动检测到的服务器版本。如果无法检测(如 Milvus、SQLite则为空字符串。
**响应(失败)**:
```json
@@ -104,13 +105,22 @@ curl --location 'http://localhost:8080/api/v1/vector-stores/test' \
}
```
---
> 注意:测试失败时 HTTP 状态码仍为 `200`,错误信息通过 `success: false` + `error` 字段返回。
## POST `/vector-stores` - 创建向量存储
创建一个新的向量存储配置。同一 endpoint + index 组合不允许重复注册(包括环境变量配置的存储)。
为当前租户创建一个新的向量存储配置。同一 endpoint + index 组合在租户内不允许重复(与环境变量配置的存储也会冲突)。
Tencent VectorDB 使用 `engine_type: "tencent_vectordb"``connection_config``addr``username``api_key` 为必填,`database` 可选;`index_config.collection_name` 表示集合名前缀,实际集合会按向量维度追加后缀,例如 `weknora_embeddings_768`。Tencent VectorDB 适配器同时支持向量检索和基于 BM25 sparse vector 的关键词检索;旧版本已创建且没有 `sparse_vector` 索引的集合,需要重建并重新导入数据后才能启用关键词检索。
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------------- | ------ | ---- | --------------------------------------------------------------- |
| name | string | 是 | 存储显示名(租户内友好名) |
| engine_type | string | 是 | 引擎类型,取自 `/vector-stores/types` |
| connection_config | object | 是 | 连接配置(与所选引擎的 `connection_fields` 对应) |
| index_config | object | 否 | 索引配置(与所选引擎的 `index_fields` 对应) |
> Tencent VectorDB 使用 `engine_type: "tencent_vectordb"`。`connection_config` 中 `addr`、`username`、`api_key` 必填,`database` 可选;`index_config.collection_name` 表示集合名前缀,实际集合会按向量维度追加后缀(例如 `weknora_embeddings_768`)。该适配器同时支持向量检索和基于 BM25 sparse vector 的关键词检索;旧版本已创建且没有 `sparse_vector` 索引的集合需要重建并重新导入数据后才能启用关键词检索。
**请求**:
@@ -178,14 +188,11 @@ curl --location 'http://localhost:8080/api/v1/vector-stores' \
}
```
> **注意**: 响应中的敏感字段(`password`、`api_key`)会被掩码为 `"***"`。
> `connection_config.version` 字段在连接测试成功后自动填充(如 `"7.10.1"`),创建时为空。
---
> 响应中的敏感字段(`password`、`api_key`)会被掩码为 `"***"`。`connection_config.version` 字段在连接测试成功后才会自动填充,创建时为空。
## GET `/vector-stores` - 获取向量存储列表
返回当前租户的所有向量存储,包含环境变量配置的存储(`source: "env"`)和用户创建的存储(`source: "user"`)。环境变量存储排列在前。
返回当前租户的所有向量存储,包含 `RETRIEVE_DRIVER` 环境变量配置的虚拟存储(`source: "env"``readonly: true`)和用户在 DB 中创建的存储(`source: "user"``readonly: false`)。环境变量存储排列在前。
**请求**:
@@ -226,11 +233,15 @@ curl --location 'http://localhost:8080/api/v1/vector-stores' \
}
```
---
## GET `/vector-stores/:id` - 获取向量存储详情
根据 ID 获取单个向量存储详情。支持 `__env_*` 式的环境变量存储 ID。
根据 ID 获取单个向量存储。支持 DB 存储 UUID 和 `__env_*` 式的环境变量存储 ID(例如 `__env_postgres__`
**路径参数**:
| 字段 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | --------------------------------------------------- |
| id | string | 是 | 向量存储 IDDB UUID 或 `__env_{driver}__` |
**请求**:
@@ -265,11 +276,21 @@ curl --location 'http://localhost:8080/api/v1/vector-stores/550e8400-e29b-41d4-a
}
```
---
## PUT `/vector-stores/:id` - 更新向量存储
更新向量存储的名称`engine_type``connection_config``index_config` 创建后不可变更环境变量存储不可修改(返回 400
仅支持更新 `name``engine_type``connection_config``index_config` 创建后不可变更环境变量存储不可修改(返回 `400`)。
**路径参数**:
| 字段 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | -------------- |
| id | string | 是 | 向量存储 ID |
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | ----------------- |
| name | string | 是 | 新的存储显示名 |
**请求**:
@@ -307,11 +328,15 @@ curl --location --request PUT 'http://localhost:8080/api/v1/vector-stores/550e84
}
```
---
## DELETE `/vector-stores/:id` - 删除向量存储
软删除向量存储。环境变量存储不可删除(返回 400
对 DB 中的存储执行软删除。环境变量存储不可删除(返回 `400`)。
**路径参数**:
| 字段 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | -------------- |
| id | string | 是 | 向量存储 ID |
**请求**:
@@ -328,11 +353,15 @@ curl --location --request DELETE 'http://localhost:8080/api/v1/vector-stores/550
}
```
---
## POST `/vector-stores/:id/test` - 测试已保存或环境变量存储的连接
## POST `/vector-stores/:id/test` - 测试已保存的向量存储连接
对已保存的 DB 存储或环境变量虚拟存储执行一次连接测试。成功时返回检测到的服务器版本;对 DB 存储,检测到的版本会被自动写回 `connection_config.version`,环境变量存储不会更新。
对已保存的向量存储或环境变量存储执行连接测试。成功时返回检测到的服务器版本,并自动更新存储记录中的 `connection_config.version` 字段。
**路径参数**:
| 字段 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | --------------------------------------------------- |
| id | string | 是 | 向量存储 IDDB UUID 或 `__env_{driver}__` |
**请求**:
@@ -350,8 +379,6 @@ curl --location --request POST 'http://localhost:8080/api/v1/vector-stores/550e8
}
```
> 对于已保存的存储(非环境变量存储),检测到的版本会自动保存到 `connection_config.version` 中。
**响应(失败)**:
```json
@@ -361,24 +388,24 @@ curl --location --request POST 'http://localhost:8080/api/v1/vector-stores/550e8
}
```
---
> 与 `/vector-stores/test` 一致,测试失败时 HTTP 状态码仍为 `200`,错误通过 `success: false` + `error` 返回。
## 环境变量存储
通过 `RETRIEVE_DRIVER` 环境变量配置的向量存储以虚拟条目形式出现在列表中。这些条目的特征:
通过 `RETRIEVE_DRIVER` 环境变量配置的向量存储以虚拟条目形式出现在列表和详情中。这些条目的特征:
- **ID 格式**: `__env_{driver}__`(如 `__env_postgres__``__env_elasticsearch_v8__`
- **source**: `"env"`
- **readonly**: `true`
- **不可修改/删除**: PUT 和 DELETE 返回 400
- **可测试连接**: POST `/:id/test` 正常工作
- **ID 格式**`__env_{driver}__`(如 `__env_postgres__``__env_elasticsearch_v8__`
- **source**`"env"`
- **readonly**`true`
- **不可修改/删除**`PUT``DELETE` 返回 `400`
- **可测试连通性**`POST /vector-stores/:id/test` 正常工作
## 错误码
| HTTP 状态码 | 含义 |
|-------------|------|
| 400 | 请求参数错误、验失败、尝试修改环境变量存储 |
| 401 | 未认证 |
| 404 | 向量存储不存在 |
| 409 | 同一 endpoint + index 组合已存在 |
| 500 | 内部服务器错误 |
| HTTP 状态码 | 含义 |
| ----------- | --------------------------------------------------- |
| 400 | 请求参数错误、验失败、尝试修改环境变量存储 |
| 401 | 未认证(缺少租户上下文或 API Key |
| 404 | 向量存储不存在 |
| 409 | 同一 endpoint + index 组合已存在 |
| 500 | 内部服务器错误 |

View File

@@ -2,13 +2,25 @@
[返回目录](./README.md)
| 方法 | 路径 | 描述 |
| ---- | ------------------------ | ---------------------- |
| GET | `/web-search/providers` | 获取网络搜索服务商列表 |
包含两组接口:
- `/web-search/providers`:返回**可用的 provider 类型**(只读元数据)
- `/web-search-providers/*`:当前租户**自定义保存**的 provider CRUD 与连通性测试
## GET `/web-search/providers` - 获取网络搜索服务商列表
| 方法 | 路径 | 描述 |
| ------ | ------------------------------------- | ----------------------------------- |
| GET | `/web-search/providers` | 获取网络搜索服务商类型列表 |
| GET | `/web-search-providers/types` | 获取 Provider 类型元数据(含参数定义) |
| POST | `/web-search-providers/test` | 使用原始凭证测试连通性(不落库) |
| POST | `/web-search-providers` | 创建租户级 Provider 配置 |
| GET | `/web-search-providers` | 获取当前租户已保存的 Provider 列表 |
| GET | `/web-search-providers/:id` | 获取指定 Provider 详情 |
| PUT | `/web-search-providers/:id` | 更新 Provider |
| DELETE | `/web-search-providers/:id` | 删除 Provider |
| POST | `/web-search-providers/:id/test` | 使用已保存凭证测试连通性 |
获取系统中可用的网络搜索服务商列表。
## GET `/web-search/providers` - 获取网络搜索服务商类型列表
获取系统中可用的网络搜索服务商列表(系统级元数据,与租户无关)。
**请求**:
@@ -45,3 +57,201 @@ curl --location 'http://localhost:8080/api/v1/web-search/providers' \
"success": true
}
```
## GET `/web-search-providers/types` - 获取 Provider 类型元数据
返回 UI 表单需要的所有 provider 类型及参数定义(每种 provider 需要哪些字段、类型、是否必填)。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/web-search-providers/types' \
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
```json
{
"data": [
{
"provider": "google",
"label": "Google Search",
"description": "...",
"parameter_schema": [
{ "name": "api_key", "label": "API Key", "type": "string", "required": true },
{ "name": "cx", "label": "Search Engine ID", "type": "string", "required": true }
]
}
],
"success": true
}
```
## POST `/web-search-providers/test` - 使用原始凭证测试连通性
前端表单"测试连接"按钮使用:用尚未保存的凭证发起一次样本搜索。
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | --------------------------------- |
| provider | string | 是 | provider 类型(如 `google``bing` |
| parameters | object | 是 | 该 provider 所需凭证与参数(与 `/types``parameter_schema` 对应) |
**请求**:
```curl
curl --location --request POST 'http://localhost:8080/api/v1/web-search-providers/test' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"provider": "google",
"parameters": {
"api_key": "AIza...",
"cx": "0123456789:abcdefg"
}
}'
```
**响应**:
```json
{ "success": true }
```
失败时:
```json
{ "success": false, "error": "google api: 403 forbidden" }
```
## POST `/web-search-providers` - 创建 Provider
**参数说明(请求体)**:
| 字段 | 类型 | 必填 | 说明 |
| ----------- | ------- | ---- | ------------------------------------------ |
| name | string | 是 | Provider 显示名(在租户内唯一友好名) |
| provider | string | 是 | Provider 类型(来自 `/web-search-providers/types` |
| description | string | 否 | 备注 |
| parameters | object | 否 | 凭证与参数 |
| is_default | boolean | 否 | 是否设为当前租户默认 Provider |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/web-search-providers' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"name": "公司 Google CSE",
"provider": "google",
"description": "用于内网搜索",
"parameters": {
"api_key": "AIza...",
"cx": "0123456789:abcdefg"
},
"is_default": true
}'
```
**响应**:
```json
{
"data": {
"id": "wsp-...",
"tenant_id": 1,
"name": "公司 Google CSE",
"provider": "google",
"is_default": true,
"parameters": { "api_key": "***", "cx": "0123456789:abcdefg" }
},
"success": true
}
```
## GET `/web-search-providers` - 获取 Provider 列表
返回当前租户已保存的所有 Provider。
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/web-search-providers' \
--header 'X-API-Key: sk-xxxxx'
```
**响应**:
```json
{
"data": [
{ "id": "wsp-001", "name": "公司 Google CSE", "provider": "google", "is_default": true }
],
"success": true
}
```
## GET `/web-search-providers/:id` - 获取 Provider 详情
**路径参数**:
| 字段 | 类型 | 说明 |
| ---- | ------ | ----------- |
| id | string | Provider ID |
**请求**:
```curl
curl --location 'http://localhost:8080/api/v1/web-search-providers/wsp-001' \
--header 'X-API-Key: sk-xxxxx'
```
**响应**: 同创建接口。404 表示不存在。
## PUT `/web-search-providers/:id` - 更新 Provider
**说明**`provider` 字段(类型)创建后不可修改,仅支持更新 `name` / `description` / `parameters` / `is_default`
**参数说明(请求体)**: 同创建接口,但不包含 `provider`
**请求**:
```curl
curl --location --request PUT 'http://localhost:8080/api/v1/web-search-providers/wsp-001' \
--header 'X-API-Key: sk-xxxxx' \
--header 'Content-Type: application/json' \
--data '{
"name": "公司 Google CSE (v2)",
"parameters": { "api_key": "NEW...", "cx": "0123456789:abcdefg" },
"is_default": false
}'
```
**响应**: `{ "data": {...更新后实体...}, "success": true }`
## DELETE `/web-search-providers/:id` - 删除 Provider
**请求**:
```curl
curl --location --request DELETE 'http://localhost:8080/api/v1/web-search-providers/wsp-001' \
--header 'X-API-Key: sk-xxxxx'
```
**响应**: `{ "success": true }`
## POST `/web-search-providers/:id/test` - 测试已保存的 Provider
使用数据库中已保存的凭证发起一次样本搜索。
**请求**:
```curl
curl --location --request POST 'http://localhost:8080/api/v1/web-search-providers/wsp-001/test' \
--header 'X-API-Key: sk-xxxxx'
```
**响应**: 同 `POST /web-search-providers/test`