{"version":3,"file":"ensemble.cjs","names":["BaseRetriever"],"sources":["../../src/retrievers/ensemble.ts"],"sourcesContent":["import { BaseRetriever, BaseRetrieverInput } from \"@langchain/core/retrievers\";\nimport { Document, DocumentInterface } from \"@langchain/core/documents\";\nimport { CallbackManagerForRetrieverRun } from \"@langchain/core/callbacks/manager\";\n\nexport interface EnsembleRetrieverInput extends BaseRetrieverInput {\n  /** A list of retrievers to ensemble. */\n  retrievers: BaseRetriever[];\n  /**\n   * A list of weights corresponding to the retrievers. Defaults to equal\n   * weighting for all retrievers.\n   */\n  weights?: number[];\n  /**\n   * A constant added to the rank, controlling the balance between the importance\n   * of high-ranked items and the consideration given to lower-ranked items.\n   * Default is 60.\n   */\n  c?: number;\n}\n\n/**\n * Ensemble retriever that aggregates and orders the results of\n * multiple retrievers by using weighted Reciprocal Rank Fusion.\n */\nexport class EnsembleRetriever extends BaseRetriever {\n  static lc_name() {\n    return \"EnsembleRetriever\";\n  }\n\n  lc_namespace = [\"langchain\", \"retrievers\", \"ensemble_retriever\"];\n\n  retrievers: BaseRetriever[];\n\n  weights: number[];\n\n  c = 60;\n\n  constructor(args: EnsembleRetrieverInput) {\n    super(args);\n    this.retrievers = args.retrievers;\n    this.weights =\n      args.weights ||\n      new Array(args.retrievers.length).fill(1 / args.retrievers.length);\n    this.c = args.c || 60;\n  }\n\n  async _getRelevantDocuments(\n    query: string,\n    runManager?: CallbackManagerForRetrieverRun\n  ) {\n    return this._rankFusion(query, runManager);\n  }\n\n  async _rankFusion(\n    query: string,\n    runManager?: CallbackManagerForRetrieverRun\n  ) {\n    const retrieverDocs = await Promise.all(\n      this.retrievers.map((retriever, i) =>\n        retriever.invoke(query, {\n          callbacks: runManager?.getChild(`retriever_${i + 1}`),\n        })\n      )\n    );\n\n    const fusedDocs = await this._weightedReciprocalRank(retrieverDocs);\n    return fusedDocs;\n  }\n\n  async _weightedReciprocalRank(docList: DocumentInterface[][]) {\n    if (docList.length !== this.weights.length) {\n      throw new Error(\n        \"Number of retrieved document lists must be equal to the number of weights.\"\n      );\n    }\n\n    const rrfScoreDict = docList.reduce(\n      (rffScore: Record<string, number>, retrieverDoc, idx) => {\n        let rank = 1;\n        const weight = this.weights[idx];\n        while (rank <= retrieverDoc.length) {\n          const { pageContent } = retrieverDoc[rank - 1];\n          if (!rffScore[pageContent]) {\n            rffScore[pageContent] = 0;\n          }\n          rffScore[pageContent] += weight / (rank + this.c);\n          rank += 1;\n        }\n\n        return rffScore;\n      },\n      {}\n    );\n\n    const uniqueDocs = this._uniqueUnion(docList.flat());\n    const sortedDocs = Array.from(uniqueDocs).sort(\n      (a, b) => rrfScoreDict[b.pageContent] - rrfScoreDict[a.pageContent]\n    );\n\n    return sortedDocs;\n  }\n\n  private _uniqueUnion(documents: Document[]): Document[] {\n    const documentSet = new Set();\n    const result = [];\n\n    for (const doc of documents) {\n      const key = doc.pageContent;\n      if (!documentSet.has(key)) {\n        documentSet.add(key);\n        result.push(doc);\n      }\n    }\n\n    return result;\n  }\n}\n"],"mappings":";;;;;;;;;AAwBA,IAAa,oBAAb,cAAuCA,2BAAAA,cAAc;CACnD,OAAO,UAAU;AACf,SAAO;;CAGT,eAAe;EAAC;EAAa;EAAc;EAAqB;CAEhE;CAEA;CAEA,IAAI;CAEJ,YAAY,MAA8B;AACxC,QAAM,KAAK;AACX,OAAK,aAAa,KAAK;AACvB,OAAK,UACH,KAAK,WACL,IAAI,MAAM,KAAK,WAAW,OAAO,CAAC,KAAK,IAAI,KAAK,WAAW,OAAO;AACpE,OAAK,IAAI,KAAK,KAAK;;CAGrB,MAAM,sBACJ,OACA,YACA;AACA,SAAO,KAAK,YAAY,OAAO,WAAW;;CAG5C,MAAM,YACJ,OACA,YACA;EACA,MAAM,gBAAgB,MAAM,QAAQ,IAClC,KAAK,WAAW,KAAK,WAAW,MAC9B,UAAU,OAAO,OAAO,EACtB,WAAW,YAAY,SAAS,aAAa,IAAI,IAAI,EACtD,CAAC,CACH,CACF;AAGD,SADkB,MAAM,KAAK,wBAAwB,cAAc;;CAIrE,MAAM,wBAAwB,SAAgC;AAC5D,MAAI,QAAQ,WAAW,KAAK,QAAQ,OAClC,OAAM,IAAI,MACR,6EACD;EAGH,MAAM,eAAe,QAAQ,QAC1B,UAAkC,cAAc,QAAQ;GACvD,IAAI,OAAO;GACX,MAAM,SAAS,KAAK,QAAQ;AAC5B,UAAO,QAAQ,aAAa,QAAQ;IAClC,MAAM,EAAE,gBAAgB,aAAa,OAAO;AAC5C,QAAI,CAAC,SAAS,aACZ,UAAS,eAAe;AAE1B,aAAS,gBAAgB,UAAU,OAAO,KAAK;AAC/C,YAAQ;;AAGV,UAAO;KAET,EAAE,CACH;EAED,MAAM,aAAa,KAAK,aAAa,QAAQ,MAAM,CAAC;AAKpD,SAJmB,MAAM,KAAK,WAAW,CAAC,MACvC,GAAG,MAAM,aAAa,EAAE,eAAe,aAAa,EAAE,aACxD;;CAKH,aAAqB,WAAmC;EACtD,MAAM,8BAAc,IAAI,KAAK;EAC7B,MAAM,SAAS,EAAE;AAEjB,OAAK,MAAM,OAAO,WAAW;GAC3B,MAAM,MAAM,IAAI;AAChB,OAAI,CAAC,YAAY,IAAI,IAAI,EAAE;AACzB,gBAAY,IAAI,IAAI;AACpB,WAAO,KAAK,IAAI;;;AAIpB,SAAO"}