feat(graphrag): 新增多轮检索流式问答与用户管理界面
- 新增多轮 GraphRAG 检索功能,支持流式进度输出(SSE) - 新增用户管理界面,可查看所有用户图谱统计并快速导航 - 新增多 Agent 任务拆解与执行服务,支持复杂任务协作处理 - 改进 embedding 和 rerank 服务的容错机制,支持备用模型和端点 - 更新前端样式遵循 Acmetone 设计规范,优化视觉一致性 - 新增流式分析接口,支持并行处理和专家评审选项
This commit is contained in:
@@ -17,18 +17,97 @@ const sendServiceResult = async (reply, action) => {
|
||||
/**
|
||||
* GraphRAG 控制器:负责请求转发与响应封装。
|
||||
*/
|
||||
export const createGraphRagController = (service) => ({
|
||||
export const createGraphRagController = (service, multiAgentService) => ({
|
||||
health: async (_request, reply) => reply.send({ ok: true }),
|
||||
ready: async (_request, reply) => sendServiceResult(reply, () => service.ready()),
|
||||
bootstrap: async (_request, reply) => sendServiceResult(reply, () => service.bootstrap()),
|
||||
listUsers: async (request, reply) => sendServiceResult(reply, () => service.listUsers(request.query.limit || 200)),
|
||||
getGraphStats: async (request, reply) => sendServiceResult(reply, () => service.getGraphStats(request.query.userId || 'default')),
|
||||
ingest: async (request, reply) => sendServiceResult(reply, () => service.ingest(request.body)),
|
||||
queryTimeline: async (request, reply) =>
|
||||
sendServiceResult(reply, () => service.queryTimeline(request.body)),
|
||||
queryGraphRag: async (request, reply) =>
|
||||
sendServiceResult(reply, () => service.queryGraphRag(request.body)),
|
||||
queryGraphRagMultiRound: async (request, reply) =>
|
||||
sendServiceResult(reply, () => service.queryGraphRagMultiRound(request.body)),
|
||||
queryGraphRagMultiRoundStream: async (request, reply) => {
|
||||
reply.hijack();
|
||||
const raw = reply.raw;
|
||||
const requestOrigin = request.headers.origin;
|
||||
raw.setHeader('Access-Control-Allow-Origin', requestOrigin || '*');
|
||||
raw.setHeader('Vary', 'Origin');
|
||||
raw.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
||||
raw.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
||||
raw.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
|
||||
raw.setHeader('Cache-Control', 'no-cache, no-transform');
|
||||
raw.setHeader('Connection', 'keep-alive');
|
||||
raw.setHeader('X-Accel-Buffering', 'no');
|
||||
raw.flushHeaders?.();
|
||||
const push = (event, data) => {
|
||||
raw.write(`event: ${event}\n`);
|
||||
raw.write(`data: ${JSON.stringify(data)}\n\n`);
|
||||
};
|
||||
try {
|
||||
const result = await service.queryGraphRagMultiRound(request.body, {
|
||||
onProgress: (event) => push('progress', event)
|
||||
});
|
||||
push('done', result);
|
||||
} catch (error) {
|
||||
push('error', {
|
||||
ok: false,
|
||||
statusCode: Number(error?.statusCode) || 500,
|
||||
message: error?.message || 'internal error'
|
||||
});
|
||||
} finally {
|
||||
raw.end();
|
||||
}
|
||||
},
|
||||
analyzeAndIngest: async (request, reply) =>
|
||||
sendServiceResult(reply, () => service.incrementalUpdate(request.body.text, request.body.userId || 'default')),
|
||||
reindexUserVectors: async (request, reply) =>
|
||||
sendServiceResult(reply, () => service.reindexUserVectors({
|
||||
userId: request.body.userId || 'default',
|
||||
limit: request.body.limit
|
||||
})),
|
||||
analyzeAndIngestStream: async (request, reply) => {
|
||||
reply.hijack();
|
||||
const raw = reply.raw;
|
||||
const requestOrigin = request.headers.origin;
|
||||
raw.setHeader('Access-Control-Allow-Origin', requestOrigin || '*');
|
||||
raw.setHeader('Vary', 'Origin');
|
||||
raw.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
||||
raw.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
||||
raw.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
|
||||
raw.setHeader('Cache-Control', 'no-cache, no-transform');
|
||||
raw.setHeader('Connection', 'keep-alive');
|
||||
raw.setHeader('X-Accel-Buffering', 'no');
|
||||
raw.flushHeaders?.();
|
||||
const push = (event, data) => {
|
||||
raw.write(`event: ${event}\n`);
|
||||
raw.write(`data: ${JSON.stringify(data)}\n\n`);
|
||||
};
|
||||
try {
|
||||
push('progress', { stage: 'start' });
|
||||
const result = await service.incrementalUpdate(
|
||||
request.body.text,
|
||||
request.body.userId || 'default',
|
||||
{
|
||||
parallelism: request.body.parallelism,
|
||||
expertReview: request.body.expertReview,
|
||||
onProgress: (event) => push('progress', event)
|
||||
}
|
||||
);
|
||||
push('done', result);
|
||||
} catch (error) {
|
||||
push('error', {
|
||||
ok: false,
|
||||
statusCode: Number(error?.statusCode) || 500,
|
||||
message: error?.message || 'internal error'
|
||||
});
|
||||
} finally {
|
||||
raw.end();
|
||||
}
|
||||
},
|
||||
queryHistory: async (request, reply) =>
|
||||
sendServiceResult(reply, () => service.queryRelationshipHistory(
|
||||
request.body.userId || 'default',
|
||||
@@ -36,5 +115,9 @@ export const createGraphRagController = (service) => ({
|
||||
request.body.limit || 20
|
||||
)),
|
||||
getAdvice: async (request, reply) =>
|
||||
sendServiceResult(reply, () => service.getRelationshipAdvice(request.body.userId || 'default'))
|
||||
sendServiceResult(reply, () => service.getRelationshipAdvice(request.body.userId || 'default')),
|
||||
decomposeMultiAgentTask: async (request, reply) =>
|
||||
sendServiceResult(reply, () => multiAgentService.decomposeTask(request.body)),
|
||||
executeMultiAgentTask: async (request, reply) =>
|
||||
sendServiceResult(reply, () => multiAgentService.executeTaskWorkflow(request.body))
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user