feat: 添加知识库检索功能和改进模型路由错误处理

- 在ChatRequest中添加Citation事件类型,支持引用来源展示
- 实现聊天上下文准备服务,构建带源元数据的受限聊天上下文
- 添加ThreadedProcess类以支持Windows平台的子进程操作
- 改进检索引擎中的错误处理和向量搜索逻辑
- 实现严格的嵌入模型验证和索引重建机制
- 添加前端聊天界面的知识库检索开关
- 实现搜索历史记录功能和错误降级处理
- 更新模型路由设置提示信息以反映索引重建需求
This commit is contained in:
2026-09-04 13:02:08 +08:00
parent 8c644d0aae
commit 6eb97bf9ab
20 changed files with 448 additions and 26 deletions
+65
View File
@@ -0,0 +1,65 @@
"""Pipe adapter for event loops without asyncio subprocess support (Windows reload)."""
from __future__ import annotations
import asyncio
import subprocess
class _Input:
def __init__(self, pipe):
self.pipe = pipe
self.pending = bytearray()
def write(self, data):
self.pending.extend(data)
async def drain(self):
data = bytes(self.pending)
self.pending.clear()
def send():
self.pipe.write(data)
self.pipe.flush()
await asyncio.to_thread(send)
def close(self):
self.pipe.close()
class _Output:
def __init__(self, pipe, limit):
self.pipe = pipe
self.limit = limit
async def readline(self):
# Bound allocations even when the worker produces a malformed line.
return await asyncio.to_thread(self.pipe.readline, self.limit + 1)
class ThreadedProcess:
def __init__(self, args, *, env, limit, creationflags=0):
# Spawn synchronously so cancellation cannot leave an unowned process.
# Blocking pipe I/O and reaping run in threads, never on the server loop.
self.process = subprocess.Popen(
args, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL, env=env, creationflags=creationflags,
)
self.stdin = _Input(self.process.stdin)
self.stdout = _Output(self.process.stdout, limit)
@property
def returncode(self):
return self.process.poll()
def kill(self):
self.process.kill()
async def wait(self):
return await asyncio.to_thread(self.process.wait)
async def close(self):
def close_pipes():
self.process.stdin.close()
self.process.stdout.close()
await asyncio.to_thread(close_pipes)