UNPKG

@langchain/community

Version:
1 lines • 8.6 kB
{"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"}