feat(server): add doc meta for semantic search (#13174)

fix AI-339
This commit is contained in:
DarkSky
2025-07-11 18:36:21 +08:00
committed by GitHub
parent 93f13e9e01
commit 847ef00a75
2 changed files with 28 additions and 5 deletions

View File

@@ -141,6 +141,7 @@ export abstract class CopilotProvider<C = any> {
this.logger.debug(`getTools: ${JSON.stringify(options.tools)}`); this.logger.debug(`getTools: ${JSON.stringify(options.tools)}`);
const ac = this.moduleRef.get(AccessController, { strict: false }); const ac = this.moduleRef.get(AccessController, { strict: false });
const docReader = this.moduleRef.get(DocReader, { strict: false }); const docReader = this.moduleRef.get(DocReader, { strict: false });
const models = this.moduleRef.get(Models, { strict: false });
const prompt = this.moduleRef.get(PromptService, { const prompt = this.moduleRef.get(PromptService, {
strict: false, strict: false,
}); });
@@ -182,7 +183,12 @@ export abstract class CopilotProvider<C = any> {
const docContext = options.session const docContext = options.session
? await context.getBySessionId(options.session) ? await context.getBySessionId(options.session)
: null; : null;
const searchDocs = buildDocSearchGetter(ac, context, docContext); const searchDocs = buildDocSearchGetter(
ac,
context,
docContext,
models
);
tools.doc_semantic_search = createDocSemanticSearchTool( tools.doc_semantic_search = createDocSemanticSearchTool(
searchDocs.bind(null, options) searchDocs.bind(null, options)
); );
@@ -204,7 +210,6 @@ export abstract class CopilotProvider<C = any> {
break; break;
} }
case 'docRead': { case 'docRead': {
const models = this.moduleRef.get(Models, { strict: false });
const getDoc = buildDocContentGetter(ac, docReader, models); const getDoc = buildDocContentGetter(ac, docReader, models);
tools.doc_read = createDocReadTool(getDoc.bind(null, options)); tools.doc_read = createDocReadTool(getDoc.bind(null, options));
break; break;

View File

@@ -2,7 +2,7 @@ import { tool } from 'ai';
import { z } from 'zod'; import { z } from 'zod';
import type { AccessController } from '../../../core/permission'; import type { AccessController } from '../../../core/permission';
import type { ChunkSimilarity } from '../../../models'; import type { ChunkSimilarity, Models } from '../../../models';
import type { CopilotContextService } from '../context'; import type { CopilotContextService } from '../context';
import type { ContextSession } from '../context/session'; import type { ContextSession } from '../context/session';
import type { CopilotChatOptions } from '../providers'; import type { CopilotChatOptions } from '../providers';
@@ -11,7 +11,8 @@ import { toolError } from './error';
export const buildDocSearchGetter = ( export const buildDocSearchGetter = (
ac: AccessController, ac: AccessController,
context: CopilotContextService, context: CopilotContextService,
docContext: ContextSession | null docContext: ContextSession | null,
models: Models
) => { ) => {
const searchDocs = async ( const searchDocs = async (
options: CopilotChatOptions, options: CopilotChatOptions,
@@ -45,7 +46,24 @@ export const buildDocSearchGetter = (
} }
if (!docChunks.length && !fileChunks.length) if (!docChunks.length && !fileChunks.length)
return `No results found for "${query}".`; return `No results found for "${query}".`;
return [...fileChunks, ...docChunks];
const docMetas = await models.doc
.findAuthors(
docChunks.map(c => ({
// oxlint-disable-next-line no-non-null-assertion
workspaceId: options.workspace!,
docId: c.docId,
}))
)
.then(docs => new Map(docs.filter(d => !!d).map(doc => [doc.id, doc])));
return [
...fileChunks,
...docChunks.map(c => ({
...c,
...docMetas.get(c.docId),
})),
] as ChunkSimilarity[];
}; };
return searchDocs; return searchDocs;
}; };