docs(fix): 修正引用跳转文档错误及修复 fix_image_paths 脚本
- 修正 preview 接口路径(去掉多余的 /api 前缀) - 修正响应示例中 chunk id 格式(文件名_序号,非 UUID) - 补充 preview 响应中 status、version 字段 - 明确前端引用匹配方式为 chunk_id 查找而非数组下标 - fix_image_paths.py 改为遍历知识库子目录,避免生成空 chroma.sqlite3
This commit is contained in:
@@ -71,7 +71,7 @@ SSE 流结束时,`finish` 事件的 `citations` 字段是一个数组,每个
|
|||||||
### 三、文档预览接口
|
### 三、文档预览接口
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /api/documents/{collection}/{source}/preview?chunk_index={N}&context={K}
|
GET /documents/{collection}/{source}/preview?chunk_index={N}&context={K}
|
||||||
```
|
```
|
||||||
|
|
||||||
**参数:**
|
**参数:**
|
||||||
@@ -94,7 +94,7 @@ GET /api/documents/{collection}/{source}/preview?chunk_index={N}&context={K}
|
|||||||
"target_index": 5, // 请求的 chunk_index
|
"target_index": 5, // 请求的 chunk_index
|
||||||
"chunks": [
|
"chunks": [
|
||||||
{
|
{
|
||||||
"id": "uuid-xxx",
|
"id": "三峡公报.pdf_3", // 切片 ID(文件名_序号格式,序号 = chunk_index)
|
||||||
"document": "完整切片正文...", // 完整内容(不截断)
|
"document": "完整切片正文...", // 完整内容(不截断)
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"chunk_index": 3,
|
"chunk_index": 3,
|
||||||
@@ -104,12 +104,16 @@ GET /api/documents/{collection}/{source}/preview?chunk_index={N}&context={K}
|
|||||||
"doc_type": "pdf",
|
"doc_type": "pdf",
|
||||||
...
|
...
|
||||||
},
|
},
|
||||||
|
"status": "active", // 文档状态
|
||||||
|
"version": "v1", // 版本号
|
||||||
"is_target": false // 是否为目标切片
|
"is_target": false // 是否为目标切片
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "uuid-yyy",
|
"id": "三峡公报.pdf_5",
|
||||||
"document": "目标切片的完整正文...",
|
"document": "目标切片的完整正文...",
|
||||||
"metadata": { "chunk_index": 5, "page": 3, ... },
|
"metadata": { "chunk_index": 5, "page": 3, ... },
|
||||||
|
"status": "active",
|
||||||
|
"version": "v1",
|
||||||
"is_target": true // ← 这是用户点击的那个切片
|
"is_target": true // ← 这是用户点击的那个切片
|
||||||
},
|
},
|
||||||
// ... 上下文切片
|
// ... 上下文切片
|
||||||
@@ -126,7 +130,7 @@ GET /api/documents/{collection}/{source}/preview?chunk_index={N}&context={K}
|
|||||||
```
|
```
|
||||||
1. 从 finish 事件取 answer(回答全文)和 citations(引用数组)
|
1. 从 finish 事件取 answer(回答全文)和 citations(引用数组)
|
||||||
2. 用正则 /\[ref:([^\]]+)\]/g 从 answer 中按出现顺序提取所有 chunk_id
|
2. 用正则 /\[ref:([^\]]+)\]/g 从 answer 中按出现顺序提取所有 chunk_id
|
||||||
3. 与 citations 数组匹配,建立 chunk_id → 显示序号 [1] [2] ... 的映射
|
3. 以 chunk_id 为键从 citations 数组中查找对应的引用信息(注意:是按 chunk_id 匹配,不是按数组下标),建立 chunk_id → 显示序号 [1] [2] ... 的映射
|
||||||
4. 渲染回答时,将 [ref:xxx] 替换为可点击的上标元素
|
4. 渲染回答时,将 [ref:xxx] 替换为可点击的上标元素
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -17,24 +17,45 @@ import sys
|
|||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
import chromadb
|
import chromadb
|
||||||
|
from config import CHROMA_DB_PATH
|
||||||
|
|
||||||
|
|
||||||
def fix_image_paths(dry_run: bool = False):
|
def fix_image_paths(dry_run: bool = False):
|
||||||
"""
|
"""
|
||||||
修复向量库中的图片路径格式
|
修复向量库中的图片路径格式
|
||||||
|
|
||||||
|
多向量库模式下,遍历 chroma/ 下的每个知识库子目录,
|
||||||
|
分别创建 PersistentClient 处理各自的集合。
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
dry_run: 仅预览,不实际修改
|
dry_run: 仅预览,不实际修改
|
||||||
"""
|
"""
|
||||||
chroma_path = "knowledge/vector_store/chroma"
|
# 扫描知识库子目录(每个子目录是一个独立的向量库)
|
||||||
client = chromadb.PersistentClient(path=chroma_path)
|
kb_dirs = []
|
||||||
|
if os.path.exists(CHROMA_DB_PATH):
|
||||||
|
for item in os.listdir(CHROMA_DB_PATH):
|
||||||
|
item_path = os.path.join(CHROMA_DB_PATH, item)
|
||||||
|
if os.path.isdir(item_path) and not item.startswith('.'):
|
||||||
|
if os.path.exists(os.path.join(item_path, 'chroma.sqlite3')):
|
||||||
|
kb_dirs.append(item)
|
||||||
|
|
||||||
|
if not kb_dirs:
|
||||||
|
print("未找到任何知识库子目录")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"发现 {len(kb_dirs)} 个知识库: {kb_dirs}\n")
|
||||||
|
|
||||||
|
for kb_name in kb_dirs:
|
||||||
|
kb_path = os.path.join(CHROMA_DB_PATH, kb_name)
|
||||||
|
print(f"处理知识库: {kb_name}")
|
||||||
|
client = chromadb.PersistentClient(path=kb_path)
|
||||||
|
|
||||||
# 获取所有集合
|
# 获取所有集合
|
||||||
collections = client.list_collections()
|
collections = client.list_collections()
|
||||||
print(f"找到 {len(collections)} 个集合")
|
print(f" 找到 {len(collections)} 个集合")
|
||||||
|
|
||||||
for collection in collections:
|
for collection in collections:
|
||||||
print(f"\n处理集合: {collection.name}")
|
print(f"\n 处理集合: {collection.name}")
|
||||||
|
|
||||||
# 获取所有图片类型的切片
|
# 获取所有图片类型的切片
|
||||||
try:
|
try:
|
||||||
@@ -98,6 +119,8 @@ def fix_image_paths(dry_run: bool = False):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" 处理集合 {collection.name} 时出错: {e}")
|
print(f" 处理集合 {collection.name} 时出错: {e}")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="修复向量库中的图片路径格式")
|
parser = argparse.ArgumentParser(description="修复向量库中的图片路径格式")
|
||||||
|
|||||||
Reference in New Issue
Block a user