feat: M2-05 — Vector integration contracts + citation context assembler
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 38s
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 38s
- integration-types.ts: IndexableChunk, CitationContext, RetrievalRequest/Response - VectorService.buildCitationContexts() for RAG citation assembly - Defines Ingestion↔Vector↔RAG interface contracts Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
9520d1f549
commit
68540b0d67
54
src/modules/vector/integration-types.ts
Normal file
54
src/modules/vector/integration-types.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Shared types for Ingestion ↔ Vector ↔ RAG integration
|
||||||
|
|
||||||
|
/** Ingestion → Vector: chunk with embedding ready for upsert */
|
||||||
|
export interface IndexableChunk {
|
||||||
|
id: string;
|
||||||
|
sourceId: string;
|
||||||
|
knowledgeBaseId: string;
|
||||||
|
userId: string;
|
||||||
|
content: string;
|
||||||
|
chunkIndex: number;
|
||||||
|
pageNumber?: number;
|
||||||
|
sectionTitle?: string;
|
||||||
|
tokenCount: number;
|
||||||
|
embedding: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Vector → RAG: search result with source info for citation */
|
||||||
|
export interface CitationContext {
|
||||||
|
chunkId: string;
|
||||||
|
sourceId: string;
|
||||||
|
sourceTitle: string;
|
||||||
|
content: string;
|
||||||
|
pageNumber?: number;
|
||||||
|
sectionTitle?: string;
|
||||||
|
score: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** RAG → Vector: search request parameters */
|
||||||
|
export interface RetrievalRequest {
|
||||||
|
queryEmbedding: number[];
|
||||||
|
knowledgeBaseId?: string;
|
||||||
|
userId?: string;
|
||||||
|
topK?: number;
|
||||||
|
enableRerank?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** RAG → Vector: complete retrieval response */
|
||||||
|
export interface RetrievalResponse {
|
||||||
|
results: CitationContext[];
|
||||||
|
queryTimeMs: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Batch upsert result */
|
||||||
|
export interface BatchUpsertResult {
|
||||||
|
upserted: number;
|
||||||
|
failed: number;
|
||||||
|
errors?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Cleanup trigger when import fails or source is deleted */
|
||||||
|
export interface VectorCleanupRequest {
|
||||||
|
sourceId: string;
|
||||||
|
reason: 'import_failed' | 'source_deleted' | 'reparse';
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ import { Injectable, Logger, OnModuleInit, Optional } from '@nestjs/common';
|
|||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { QdrantClient } from '@qdrant/js-client-rest';
|
import { QdrantClient } from '@qdrant/js-client-rest';
|
||||||
import { AiGatewayService } from '../ai/gateway/ai-gateway.service';
|
import { AiGatewayService } from '../ai/gateway/ai-gateway.service';
|
||||||
|
import type { CitationContext } from './integration-types';
|
||||||
|
|
||||||
export interface VectorPoint {
|
export interface VectorPoint {
|
||||||
id: string;
|
id: string;
|
||||||
@ -191,4 +192,17 @@ export class VectorService implements OnModuleInit {
|
|||||||
const result = await this.client.count(COLLECTION_NAME);
|
const result = await this.client.count(COLLECTION_NAME);
|
||||||
return result.count;
|
return result.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Build citation context from search results */
|
||||||
|
async buildCitationContexts(results: SearchResult[]): Promise<CitationContext[]> {
|
||||||
|
return results.map(r => ({
|
||||||
|
chunkId: r.id,
|
||||||
|
sourceId: r.payload?.sourceId || 'unknown',
|
||||||
|
sourceTitle: r.payload?.sourceTitle || 'Untitled',
|
||||||
|
content: r.payload?.text || '',
|
||||||
|
pageNumber: r.payload?.pageNumber,
|
||||||
|
sectionTitle: r.payload?.sectionTitle,
|
||||||
|
score: r.score,
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -233,4 +233,30 @@ describe('M2 E2E Tests', () => {
|
|||||||
expect(res.body.success).toBe(true);
|
expect(res.body.success).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════
|
||||||
|
// M2-05: Vector & Retrieval 对接
|
||||||
|
// ══════════════════════════════════════════════
|
||||||
|
describe('M2-05 Vector Integration', () => {
|
||||||
|
let token: string;
|
||||||
|
beforeAll(async () => { token = await loginAdmin(); });
|
||||||
|
|
||||||
|
it('VectorService collection accessible', async () => {
|
||||||
|
if (!token) return;
|
||||||
|
const res = await request(app.getHttpServer())
|
||||||
|
.get('/admin-api/vector/collection')
|
||||||
|
.set('Authorization', `Bearer ${token}`)
|
||||||
|
.expect(200);
|
||||||
|
expect(res.body.data).toHaveProperty('name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('VectorService count accessible', async () => {
|
||||||
|
if (!token) return;
|
||||||
|
const res = await request(app.getHttpServer())
|
||||||
|
.get('/admin-api/vector/count')
|
||||||
|
.set('Authorization', `Bearer ${token}`)
|
||||||
|
.expect(200);
|
||||||
|
expect(res.body.data).toHaveProperty('count');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user