import localforage from "localforage"; import { similarity } from "ml-distance"; import { globalFetch } from "src/ts/storage/globalApi"; export class HypaProcesser{ oaikey:string vectors:memoryVector[] forage:LocalForage constructor(){ this.forage = localforage.createInstance({ name: "hypaVector" }) this.vectors = [] } async embedDocuments(texts: string[]): Promise { const subPrompts = chunkArray(texts,512); const embeddings: number[][] = []; for (let i = 0; i < subPrompts.length; i += 1) { const input = subPrompts[i]; const data = await this.getEmbeds(input) embeddings.push(...data); } return embeddings; } async getEmbeds(input:string[]|string) { const gf = await globalFetch("https://api.openai.com/v1/embeddings", { headers: { "Authorization": "Bearer " + this.oaikey }, body: { "input": input, "model": "text-embedding-ada-002" } }) const data = gf.data if(!gf.ok){ throw gf.data } const result:number[][] = [] for(let i=0;i { for(let i=0;i ({ content: texts[idx], embedding })); for(let i=0;i result[0]); } async similaritySearchVectorWithScore( query: number[], ): Promise<[string, number][]> { const memoryVectors = this.vectors const searches = memoryVectors .map((vector, index) => ({ similarity: similarity.cosine(query, vector.embedding), index, })) .sort((a, b) => (a.similarity > b.similarity ? -1 : 0)) const result: [string, number][] = searches.map((search) => [ memoryVectors[search.index].content, search.similarity, ]); return result; } } type memoryVector = { embedding:number[] content:string, alreadySaved?:boolean } const chunkArray = (arr: T[], chunkSize: number) => arr.reduce((chunks, elem, index) => { const chunkIndex = Math.floor(index / chunkSize); const chunk = chunks[chunkIndex] || []; chunks[chunkIndex] = chunk.concat([elem]); return chunks; }, [] as T[][]);