{"version":3,"file":"cypher.cjs","names":["BaseChain","props: GraphCypherQAChainInput","props: FromLLMInput","CYPHER_QA_PROMPT","CYPHER_GENERATION_PROMPT","LLMChain","text: string","values: ChainValues","runManager?: CallbackManagerForChainRun","chainResult: ChainValues"],"sources":["../../../src/chains/graph_qa/cypher.ts"],"sourcesContent":["import type { BaseLanguageModelInterface } from \"@langchain/core/language_models/base\";\nimport { ChainValues } from \"@langchain/core/utils/types\";\nimport { BasePromptTemplate } from \"@langchain/core/prompts\";\nimport { CallbackManagerForChainRun } from \"@langchain/core/callbacks/manager\";\nimport { LLMChain, BaseChain, ChainInputs } from \"@langchain/classic/chains\";\nimport { Neo4jGraph } from \"../../graphs/neo4j_graph.js\";\nimport { CYPHER_GENERATION_PROMPT, CYPHER_QA_PROMPT } from \"./prompts.js\";\n\nexport const INTERMEDIATE_STEPS_KEY = \"intermediateSteps\";\n\nexport interface GraphCypherQAChainInput extends ChainInputs {\n  graph: Neo4jGraph;\n  cypherGenerationChain: LLMChain;\n  qaChain: LLMChain;\n  inputKey?: string;\n  outputKey?: string;\n  topK?: number;\n  returnIntermediateSteps?: boolean;\n  returnDirect?: boolean;\n}\n\nexport interface FromLLMInput {\n  graph: Neo4jGraph;\n  llm?: BaseLanguageModelInterface;\n  cypherLLM?: BaseLanguageModelInterface;\n  qaLLM?: BaseLanguageModelInterface;\n  qaPrompt?: BasePromptTemplate;\n  cypherPrompt?: BasePromptTemplate;\n  returnIntermediateSteps?: boolean;\n  returnDirect?: boolean;\n}\n\n/**\n * Chain for question-answering against a graph by generating Cypher statements.\n *\n * @example\n * ```typescript\n * const chain = new GraphCypherQAChain({\n *   llm: new ChatOpenAI({ model: \"gpt-4o-mini\", temperature: 0 }),\n *   graph: new Neo4jGraph(),\n * });\n * const res = await chain.invoke(\"Who played in Pulp Fiction?\");\n * ```\n *\n * @security\n * This chain will execute Cypher statements against the provided database.\n * Make sure that the database connection uses credentials\n * that are narrowly-scoped to only include necessary permissions.\n * Failure to do so may result in data corruption or loss, since the calling code\n * may attempt commands that would result in deletion, mutation of data\n * if appropriately prompted or reading sensitive data if such data is present in the database.\n * The best way to guard against such negative outcomes is to (as appropriate) limit the\n * permissions granted to the credentials used with this tool.\n *\n * See https://js.langchain.com/docs/security for more information.\n */\nexport class GraphCypherQAChain extends BaseChain {\n  private graph: Neo4jGraph;\n\n  private cypherGenerationChain: LLMChain;\n\n  private qaChain: LLMChain;\n\n  private inputKey = \"query\";\n\n  private outputKey = \"result\";\n\n  private topK = 10;\n\n  private returnDirect = false;\n\n  private returnIntermediateSteps = false;\n\n  constructor(props: GraphCypherQAChainInput) {\n    super(props);\n    const {\n      graph,\n      cypherGenerationChain,\n      qaChain,\n      inputKey,\n      outputKey,\n      topK,\n      returnIntermediateSteps,\n      returnDirect,\n    } = props;\n\n    this.graph = graph;\n    this.cypherGenerationChain = cypherGenerationChain;\n    this.qaChain = qaChain;\n\n    if (inputKey) {\n      this.inputKey = inputKey;\n    }\n    if (outputKey) {\n      this.outputKey = outputKey;\n    }\n    if (topK) {\n      this.topK = topK;\n    }\n    if (returnIntermediateSteps) {\n      this.returnIntermediateSteps = returnIntermediateSteps;\n    }\n    if (returnDirect) {\n      this.returnDirect = returnDirect;\n    }\n  }\n\n  _chainType() {\n    return \"graph_cypher_chain\" as const;\n  }\n\n  get inputKeys(): string[] {\n    return [this.inputKey];\n  }\n\n  get outputKeys(): string[] {\n    return [this.outputKey];\n  }\n\n  static fromLLM(props: FromLLMInput): GraphCypherQAChain {\n    const {\n      graph,\n      qaPrompt = CYPHER_QA_PROMPT,\n      cypherPrompt = CYPHER_GENERATION_PROMPT,\n      llm,\n      cypherLLM,\n      qaLLM,\n      returnIntermediateSteps = false,\n      returnDirect = false,\n    } = props;\n\n    if (!cypherLLM && !llm) {\n      throw new Error(\n        \"Either 'llm' or 'cypherLLM' parameters must be provided\"\n      );\n    }\n\n    if (!qaLLM && !llm) {\n      throw new Error(\"Either 'llm' or 'qaLLM' parameters must be provided\");\n    }\n\n    if (cypherLLM && qaLLM && llm) {\n      throw new Error(\n        \"You can specify up to two of 'cypherLLM', 'qaLLM', and 'llm', but not all three simultaneously.\"\n      );\n    }\n\n    const qaChain = new LLMChain({\n      llm: (qaLLM || llm) as BaseLanguageModelInterface,\n      prompt: qaPrompt,\n    });\n\n    const cypherGenerationChain = new LLMChain({\n      llm: (cypherLLM || llm) as BaseLanguageModelInterface,\n      prompt: cypherPrompt,\n    });\n\n    return new GraphCypherQAChain({\n      cypherGenerationChain,\n      qaChain,\n      graph,\n      returnIntermediateSteps,\n      returnDirect,\n    });\n  }\n\n  private extractCypher(text: string): string {\n    const pattern = /```(.*?)```/s;\n    const matches = text.match(pattern);\n    return matches ? matches[1] : text;\n  }\n\n  async _call(\n    values: ChainValues,\n    runManager?: CallbackManagerForChainRun\n  ): Promise<ChainValues> {\n    const callbacks = runManager?.getChild();\n    const question = values[this.inputKey];\n\n    const intermediateSteps = [];\n\n    const generatedCypher = await this.cypherGenerationChain.call(\n      { question, schema: this.graph.getSchema() },\n      callbacks\n    );\n\n    const extractedCypher = this.extractCypher(generatedCypher.text);\n\n    await runManager?.handleText(`Generated Cypher:\\n`);\n    await runManager?.handleText(`${extractedCypher} green\\n`);\n\n    intermediateSteps.push({ query: extractedCypher });\n\n    let chainResult: ChainValues;\n    const context = await this.graph.query(extractedCypher, {\n      topK: this.topK,\n    });\n\n    if (this.returnDirect) {\n      chainResult = { [this.outputKey]: context };\n    } else {\n      await runManager?.handleText(\"Full Context:\\n\");\n      await runManager?.handleText(`${context} green\\n`);\n\n      intermediateSteps.push({ context });\n\n      const result = await this.qaChain.call(\n        { question, context: JSON.stringify(context) },\n        callbacks\n      );\n\n      chainResult = {\n        [this.outputKey]: result[this.qaChain.outputKey],\n      };\n    }\n\n    if (this.returnIntermediateSteps) {\n      chainResult[INTERMEDIATE_STEPS_KEY] = intermediateSteps;\n    }\n\n    return chainResult;\n  }\n}\n"],"mappings":";;;;;;;;;;AAQA,MAAa,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;AAgDtC,IAAa,qBAAb,MAAa,2BAA2BA,qCAAU;CAChD,AAAQ;CAER,AAAQ;CAER,AAAQ;CAER,AAAQ,WAAW;CAEnB,AAAQ,YAAY;CAEpB,AAAQ,OAAO;CAEf,AAAQ,eAAe;CAEvB,AAAQ,0BAA0B;CAElC,YAAYC,OAAgC;EAC1C,MAAM,MAAM;EACZ,MAAM,EACJ,OACA,uBACA,SACA,UACA,WACA,MACA,yBACA,cACD,GAAG;EAEJ,KAAK,QAAQ;EACb,KAAK,wBAAwB;EAC7B,KAAK,UAAU;AAEf,MAAI,UACF,KAAK,WAAW;AAElB,MAAI,WACF,KAAK,YAAY;AAEnB,MAAI,MACF,KAAK,OAAO;AAEd,MAAI,yBACF,KAAK,0BAA0B;AAEjC,MAAI,cACF,KAAK,eAAe;CAEvB;CAED,aAAa;AACX,SAAO;CACR;CAED,IAAI,YAAsB;AACxB,SAAO,CAAC,KAAK,QAAS;CACvB;CAED,IAAI,aAAuB;AACzB,SAAO,CAAC,KAAK,SAAU;CACxB;CAED,OAAO,QAAQC,OAAyC;EACtD,MAAM,EACJ,OACA,WAAWC,kCACX,eAAeC,0CACf,KACA,WACA,OACA,0BAA0B,OAC1B,eAAe,OAChB,GAAG;AAEJ,MAAI,CAAC,aAAa,CAAC,IACjB,OAAM,IAAI,MACR;AAIJ,MAAI,CAAC,SAAS,CAAC,IACb,OAAM,IAAI,MAAM;AAGlB,MAAI,aAAa,SAAS,IACxB,OAAM,IAAI,MACR;EAIJ,MAAM,UAAU,IAAIC,oCAAS;GAC3B,KAAM,SAAS;GACf,QAAQ;EACT;EAED,MAAM,wBAAwB,IAAIA,oCAAS;GACzC,KAAM,aAAa;GACnB,QAAQ;EACT;AAED,SAAO,IAAI,mBAAmB;GAC5B;GACA;GACA;GACA;GACA;EACD;CACF;CAED,AAAQ,cAAcC,MAAsB;EAC1C,MAAM,UAAU;EAChB,MAAM,UAAU,KAAK,MAAM,QAAQ;AACnC,SAAO,UAAU,QAAQ,KAAK;CAC/B;CAED,MAAM,MACJC,QACAC,YACsB;EACtB,MAAM,YAAY,YAAY,UAAU;EACxC,MAAM,WAAW,OAAO,KAAK;EAE7B,MAAM,oBAAoB,CAAE;EAE5B,MAAM,kBAAkB,MAAM,KAAK,sBAAsB,KACvD;GAAE;GAAU,QAAQ,KAAK,MAAM,WAAW;EAAE,GAC5C,UACD;EAED,MAAM,kBAAkB,KAAK,cAAc,gBAAgB,KAAK;EAEhE,MAAM,YAAY,WAAW,CAAC,mBAAmB,CAAC,CAAC;EACnD,MAAM,YAAY,WAAW,GAAG,gBAAgB,QAAQ,CAAC,CAAC;EAE1D,kBAAkB,KAAK,EAAE,OAAO,gBAAiB,EAAC;EAElD,IAAIC;EACJ,MAAM,UAAU,MAAM,KAAK,MAAM,MAAM,iBAAiB,EACtD,MAAM,KAAK,KACZ,EAAC;AAEF,MAAI,KAAK,cACP,cAAc,GAAG,KAAK,YAAY,QAAS;OACtC;GACL,MAAM,YAAY,WAAW,kBAAkB;GAC/C,MAAM,YAAY,WAAW,GAAG,QAAQ,QAAQ,CAAC,CAAC;GAElD,kBAAkB,KAAK,EAAE,QAAS,EAAC;GAEnC,MAAM,SAAS,MAAM,KAAK,QAAQ,KAChC;IAAE;IAAU,SAAS,KAAK,UAAU,QAAQ;GAAE,GAC9C,UACD;GAED,cAAc,GACX,KAAK,YAAY,OAAO,KAAK,QAAQ,WACvC;EACF;AAED,MAAI,KAAK,yBACP,YAAY,0BAA0B;AAGxC,SAAO;CACR;AACF"}