mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-21 12:06:35 +08:00
feat(server): trigger workspace embedding (#12328)
fix AI-127 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added automated event handling for workspace updates and document embedding, streamlining document embedding workflows. - Introduced detection and queuing of documents needing embedding, excluding ignored documents. - **Improvements** - Enhanced performance of embedding-related searches by filtering results at the database level. - Increased concurrency for embedding job processing to improve throughput. - **Bug Fixes** - Improved error handling and fallback for missing document titles during embedding. - Added safeguards to skip invalid embedding jobs based on document identifiers. - **Tests** - Expanded test coverage for document embedding and ignored document filtering. - Updated end-to-end tests to use dynamic content for improved reliability. - Added synchronization waits in document creation utilities to improve test stability. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
AFFiNELogger,
|
||||
BlobNotFound,
|
||||
Config,
|
||||
DocNotFound,
|
||||
EventBus,
|
||||
JobQueue,
|
||||
mapAnyError,
|
||||
@@ -87,11 +88,37 @@ export class CopilotContextDocJob {
|
||||
}
|
||||
}
|
||||
|
||||
// @OnEvent('doc.indexer.updated')
|
||||
async addDocEmbeddingQueueFromEvent(
|
||||
// TODO(@darkskygit): replace this with real event type
|
||||
doc: { workspaceId: string; docId: string } //Events['doc.indexer.updated'],
|
||||
) {
|
||||
@OnEvent('workspace.updated')
|
||||
async onWorkspaceConfigUpdate({
|
||||
id,
|
||||
enableDocEmbedding,
|
||||
}: Events['workspace.updated']) {
|
||||
if (enableDocEmbedding) {
|
||||
// trigger workspace embedding
|
||||
this.event.emit('workspace.embedding', {
|
||||
workspaceId: id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@OnEvent('workspace.embedding')
|
||||
async addWorkspaceEmbeddingQueue({
|
||||
workspaceId,
|
||||
}: Events['workspace.embedding']) {
|
||||
if (!this.supportEmbedding) return;
|
||||
|
||||
const toBeEmbedDocIds =
|
||||
await this.models.copilotWorkspace.findDocsToEmbed(workspaceId);
|
||||
for (const docId of toBeEmbedDocIds) {
|
||||
await this.queue.add('copilot.embedding.docs', {
|
||||
workspaceId,
|
||||
docId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@OnEvent('doc.indexer.updated')
|
||||
async addDocEmbeddingQueueFromEvent(doc: Events['doc.indexer.updated']) {
|
||||
if (!this.supportEmbedding) return;
|
||||
|
||||
await this.queue.add('copilot.embedding.docs', {
|
||||
@@ -100,11 +127,10 @@ export class CopilotContextDocJob {
|
||||
});
|
||||
}
|
||||
|
||||
// @OnEvent('doc.indexer.deleted')
|
||||
async deleteDocEmbeddingQueueFromEvent(
|
||||
// TODO(@darkskygit): replace this with real event type
|
||||
doc: { workspaceId: string; docId: string } //Events['doc.indexer.deleted'],
|
||||
) {
|
||||
@OnEvent('doc.indexer.deleted')
|
||||
async deleteDocEmbeddingQueueFromEvent(doc: Events['doc.indexer.deleted']) {
|
||||
if (!this.supportEmbedding) return;
|
||||
|
||||
await this.models.copilotContext.deleteWorkspaceEmbedding(
|
||||
doc.workspaceId,
|
||||
doc.docId
|
||||
@@ -193,13 +219,14 @@ export class CopilotContextDocJob {
|
||||
docId,
|
||||
}: Jobs['copilot.embedding.docs']) {
|
||||
if (!this.supportEmbedding) return;
|
||||
if (workspaceId === docId || docId.includes('$')) return;
|
||||
|
||||
try {
|
||||
const content = await this.doc.getFullDocContent(workspaceId, docId);
|
||||
if (content) {
|
||||
// no need to check if embeddings is empty, will throw internally
|
||||
const embeddings = await this.embeddingClient.getFileEmbeddings(
|
||||
new File([content.summary], `${content.title}.md`)
|
||||
new File([content.summary], `${content.title || 'Untitled'}.md`)
|
||||
);
|
||||
|
||||
for (const chunks of embeddings) {
|
||||
@@ -209,6 +236,8 @@ export class CopilotContextDocJob {
|
||||
chunks
|
||||
);
|
||||
}
|
||||
} else if (contextId) {
|
||||
throw new DocNotFound({ spaceId: workspaceId, docId });
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (contextId) {
|
||||
|
||||
Reference in New Issue
Block a user