- 新增多轮 GraphRAG 检索功能,支持流式进度输出(SSE) - 新增用户管理界面,可查看所有用户图谱统计并快速导航 - 新增多 Agent 任务拆解与执行服务,支持复杂任务协作处理 - 改进 embedding 和 rerank 服务的容错机制,支持备用模型和端点 - 更新前端样式遵循 Acmetone 设计规范,优化视觉一致性 - 新增流式分析接口,支持并行处理和专家评审选项
124 lines
5.0 KiB
JavaScript
124 lines
5.0 KiB
JavaScript
/**
|
|
* 统一服务层异常处理并输出标准响应结构。
|
|
*/
|
|
const sendServiceResult = async (reply, action) => {
|
|
try {
|
|
const data = await action();
|
|
return reply.send(data);
|
|
} catch (error) {
|
|
const statusCode = Number(error?.statusCode) || 500;
|
|
return reply.code(statusCode).send({
|
|
ok: false,
|
|
error: error?.message ?? "internal error"
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* GraphRAG 控制器:负责请求转发与响应封装。
|
|
*/
|
|
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',
|
|
request.body.queryType || 'all',
|
|
request.body.limit || 20
|
|
)),
|
|
getAdvice: async (request, reply) =>
|
|
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))
|
|
});
|