ffb-vector.service.ts 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import { Injectable, OnModuleInit } from '@nestjs/common';
  2. import { MongoCoreService } from 'src/mongo/mongo-core.service';
  3. import { FFBProductionRepository } from 'src/FFB/mongo-ffb-production.repository';
  4. import { FFBProduction } from '../ffb-production.schema';
  5. import { GeminiEmbeddingService } from '../gemini-embedding.service';
  6. @Injectable()
  7. export class FFBVectorService implements OnModuleInit {
  8. private repo: FFBProductionRepository;
  9. constructor(
  10. private readonly mongoCore: MongoCoreService,
  11. private readonly embeddingService: GeminiEmbeddingService
  12. ) { }
  13. async onModuleInit() {
  14. // Initialize Mongo repository
  15. const db = await this.mongoCore.getDb();
  16. this.repo = new FFBProductionRepository(db);
  17. await this.repo.init();
  18. console.log('✅ Gemini embedding service ready. Repository initialized.');
  19. }
  20. /** Convert a record to a string suitable for embedding */
  21. private recordToText(record: FFBProduction): string {
  22. return `Production on ${new Date(record.productionDate).toISOString()} at ${record.site} in ${record.phase} ${record.block} produced ${record.quantity} ${record.quantityUom} with a total weight of ${record.weight} ${record.weightUom}.`;
  23. }
  24. /** Insert a single record with embedding vector */
  25. async insertWithVector(record: FFBProduction) {
  26. const text = this.recordToText(record);
  27. const vector = await this.embeddingService.embedText(text);
  28. const data: FFBProduction & { vector: number[] } = { ...record, vector };
  29. return this.repo.create(data);
  30. }
  31. /** Search for top-k similar records using a text query */
  32. async vectorSearch(query: string, k = 5, filter: Record<string, any> = {}) {
  33. if (!query) throw new Error('Query string cannot be empty');
  34. const vector = await this.embeddingService.embedText(query);
  35. const results = await this.repo.vectorSearch(vector, k, 50, filter);
  36. return results.map((r) => ({
  37. ...r,
  38. _id: r._id.toString(),
  39. score: r.score,
  40. }));
  41. }
  42. /* For traditional operation that requires arithematic operations. */
  43. async aggregate(pipeline: Array<Record<string, any>>): Promise<any[]> {
  44. return this.repo.aggregate(pipeline);
  45. }
  46. }