chore(server): improve semantic search (#12838)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Updated document-related tools in chat prompts, including new options
for document keyword and semantic search.

- **Refactor**
- Renamed and reorganized document search tools for improved clarity in
tool selection and results display.

- **Bug Fixes**
- Ensured tool identifiers and results are consistent across chat and
search features.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2025-06-17 15:01:02 +08:00
committed by GitHub
parent a4d929b19c
commit 09c3aa0a92
6 changed files with 34 additions and 24 deletions

View File

@@ -1792,11 +1792,11 @@ Below is the user's query. Please respond in the user's preferred language witho
],
config: {
tools: [
'readDoc',
'editDoc',
'docRead',
'docEdit',
'docKeywordSearch',
'docSemanticSearch',
'webSearch',
'keywordSearch',
'semanticSearch',
],
},
};

View File

@@ -13,9 +13,9 @@ import { AccessController } from '../../../core/permission';
import { CopilotContextService } from '../context';
import {
buildDocSearchGetter,
createDocSemanticSearchTool,
createExaCrawlTool,
createExaSearchTool,
createSemanticSearchTool,
} from '../tools';
import { CopilotProviderFactory } from './factory';
import {
@@ -131,20 +131,21 @@ export abstract class CopilotProvider<C = any> {
continue;
}
switch (tool) {
case 'webSearch': {
tools.web_search_exa = createExaSearchTool(this.AFFiNEConfig);
tools.web_crawl_exa = createExaCrawlTool(this.AFFiNEConfig);
break;
}
case 'semanticSearch': {
case 'docSemanticSearch': {
const ac = this.moduleRef.get(AccessController, { strict: false });
const context = this.moduleRef.get(CopilotContextService, {
strict: false,
});
const searchDocs = buildDocSearchGetter(ac, context);
tools.semantic_search = createSemanticSearchTool(
tools.doc_semantic_search = createDocSemanticSearchTool(
searchDocs.bind(null, options)
);
break;
}
case 'webSearch': {
tools.web_search_exa = createExaSearchTool(this.AFFiNEConfig);
tools.web_crawl_exa = createExaCrawlTool(this.AFFiNEConfig);
break;
}
}
}

View File

@@ -60,14 +60,14 @@ export const PromptConfigStrictSchema = z.object({
tools: z
.enum([
// work with morph
'editDoc',
'docEdit',
// work with indexer
'docRead',
'docKeywordSearch',
// work with embeddings
'docSemanticSearch',
// work with exa/model internal tools
'webSearch',
// work with indexer
'readDoc',
'keywordSearch',
// work with embeddings
'semanticSearch',
])
.array()
.nullable()

View File

@@ -10,9 +10,9 @@ import {
import { ZodType } from 'zod';
import {
createDocSemanticSearchTool,
createExaCrawlTool,
createExaSearchTool,
createSemanticSearchTool,
} from '../tools';
import { PromptMessage } from './types';
@@ -380,9 +380,9 @@ export class CitationParser {
}
export interface CustomAITools extends ToolSet {
doc_semantic_search: ReturnType<typeof createDocSemanticSearchTool>;
web_search_exa: ReturnType<typeof createExaSearchTool>;
web_crawl_exa: ReturnType<typeof createExaCrawlTool>;
semantic_search: ReturnType<typeof createSemanticSearchTool>;
}
type ChunkType = TextStreamPart<CustomAITools>['type'];
@@ -429,7 +429,7 @@ export class TextStreamParser {
case 'tool-result': {
result = this.addPrefix(result);
switch (chunk.toolName) {
case 'semantic_search': {
case 'doc_semantic_search': {
if (Array.isArray(chunk.result)) {
result += `\nFound ${chunk.result.length} document${chunk.result.length !== 1 ? 's' : ''} related to “${chunk.args.query}”.\n`;
}

View File

@@ -20,12 +20,21 @@ export const buildDocSearchGetter = (
.can('Workspace.Read');
if (!canAccess) return undefined;
const chunks = await context.matchWorkspaceAll(options.workspace, query);
return chunks || undefined;
const docChunks = await ac
.user(options.user)
.workspace(options.workspace)
.docs(
chunks.filter(c => 'docId' in c),
'Doc.Read'
);
const fileChunks = chunks.filter(c => 'fileId' in c);
if (!docChunks.length && !fileChunks.length) return undefined;
return [...fileChunks, ...docChunks];
};
return searchDocs;
};
export const createSemanticSearchTool = (
export const createDocSemanticSearchTool = (
searchDocs: (query: string) => Promise<ChunkSimilarity[] | undefined>
) => {
return tool({

View File

@@ -1,2 +1,2 @@
export * from './semantic-search';
export * from './doc-semantic-search';
export * from './web-search';