Files
makemd/server/src/services/CrossTenantEmbeddingAggregator.ts

84 lines
3.0 KiB
TypeScript
Raw Normal View History

import { AIService } from './AIService';
import { logger } from '../utils/logger';
export interface TenantEmbedding {
tenantId: string;
itemId: string;
embedding: number[];
metadata?: any;
}
/**
* [CORE_DEV_14] Embedding (Embedding Aggregator)
* @description
*/
export class CrossTenantEmbeddingAggregator {
private static aggregationBuffer: TenantEmbedding[] = [];
/**
* Embedding
*/
static async ingestTenantEmbedding(tenantId: string, itemId: string, text: string, metadata?: any): Promise<void> {
logger.debug(`[EmbeddingAggregator] Ingesting embedding for tenant: ${tenantId}, item: ${itemId}`);
// 1. 生成语义指纹 (Embedding)
const embedding = await AIService.generateEmbedding(text);
const tenantEmbedding: TenantEmbedding = {
tenantId,
itemId,
embedding,
metadata
};
this.aggregationBuffer.push(tenantEmbedding);
// 实际场景中应异步写入高性能分布式向量索引 (如 Milvus/Pinecone)
logger.debug(`[EmbeddingAggregator] Tenant embedding ingested: ${tenantId}:${itemId}`);
}
/**
*
* @param queryText
* @param tenantFilter ()
*/
static async globalSearch(queryText: string, tenantFilter?: string[], limit: number = 20): Promise<TenantEmbedding[]> {
logger.info(`[EmbeddingAggregator] Performing global semantic search for: ${queryText}`);
const queryEmbedding = await AIService.generateEmbedding(queryText);
// 1. 在内存缓冲区中进行向量相似度排序 (模拟)
// 实际场景应在向量数据库中通过 HNSW/IVF 算法执行
let results = this.aggregationBuffer;
if (tenantFilter && tenantFilter.length > 0) {
results = results.filter(e => tenantFilter.includes(e.tenantId));
}
// 2. 模拟余弦相似度排序并截断
return results.slice(0, limit);
}
/**
*
*/
static async globalClusteringAnalysis(): Promise<{ clusterId: string; count: number; theme: string }[]> {
logger.info(`[EmbeddingAggregator] Running global clustering analysis...`);
// 逻辑:识别跨租户的相似商品或操作行为,用于宏观选品建议或全局欺诈预警
return [
{ clusterId: 'c-001', count: 1540, theme: 'Eco-friendly Outdoor Gear' },
{ clusterId: 'c-002', count: 820, theme: 'Smart Home Security' },
{ clusterId: 'c-003', count: 45, theme: 'Abnormal API Access Patterns (Global)' }
];
}
/**
* (Tenant Data Purge)
*/
static async purgeTenantData(tenantId: string): Promise<void> {
logger.warn(`[EmbeddingAggregator] Purging all embeddings for tenant: ${tenantId}`);
this.aggregationBuffer = this.aggregationBuffer.filter(e => e.tenantId !== tenantId);
}
}