From e294d227bce670055f012922da4458e730737bdf Mon Sep 17 00:00:00 2001 From: Vijay Sai Date: Fri, 26 May 2023 13:40:06 +0530 Subject: [PATCH] feature: changes to support ApiChain --- .../nodes/chains/ApiChain/ApiChain.ts | 79 +++++++++++++++++++ .../nodes/chains/ApiChain/apichain.svg | 3 + 2 files changed, 82 insertions(+) create mode 100644 packages/components/nodes/chains/ApiChain/ApiChain.ts create mode 100644 packages/components/nodes/chains/ApiChain/apichain.svg diff --git a/packages/components/nodes/chains/ApiChain/ApiChain.ts b/packages/components/nodes/chains/ApiChain/ApiChain.ts new file mode 100644 index 00000000..96342c55 --- /dev/null +++ b/packages/components/nodes/chains/ApiChain/ApiChain.ts @@ -0,0 +1,79 @@ +import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' +import { APIChain } from 'langchain/chains' +import { CustomChainHandler, getBaseClasses } from '../../../src/utils' +import { BaseLanguageModel } from 'langchain/base_language' +import { Document } from 'langchain/document' +import { PromptTemplate } from 'langchain/prompts' +import { OpenAI } from 'langchain' + +class ApiChain_Chains implements INode { + label: string + name: string + type: string + icon: string + category: string + baseClasses: string[] + description: string + inputs: INodeParams[] + + constructor() { + this.label = 'API Chain' + this.name = 'apiChain' + this.type = 'ApiChain' + this.icon = 'apichain.svg' + this.category = 'Chains' + this.description = 'Chain to run queries against API' + this.baseClasses = [this.type, ...getBaseClasses(APIChain), ...getBaseClasses(OpenAI)] + this.inputs = [ + { + label: 'Language Model', + name: 'model', + type: 'BaseLanguageModel' + }, + { + label: 'Document', + name: 'document', + type: 'Document', + } + ] + } + + async init(nodeData: INodeData): Promise { + const model = nodeData.inputs?.model as BaseLanguageModel + const docs = nodeData.inputs?.document as Document[] + + const chain = await getOpenAPIChain(docs, model) + return chain + } + + async run(nodeData: INodeData, input: string, options: ICommonObject): Promise { + const model = nodeData.inputs?.model as BaseLanguageModel + const docs = nodeData.inputs?.document as Document[] + + const chain = await getOpenAPIChain(docs, model) + if (options.socketIO && options.socketIOClientId) { + const handler = new CustomChainHandler(options.socketIO, options.socketIOClientId) + const res = await chain.run(input, [handler]) + return res + } else { + const res = await chain.run(input) + return res + } + } +} + +const getOpenAPIChain = async (documents: Document[], llm: BaseLanguageModel, options: any = {}) => { + const texts = documents.map(({ pageContent }) => pageContent); + const apiResponsePrompt = new PromptTemplate({ + inputVariables: ["api_docs", "question", "api_url", "api_response"], + template: "Given this {api_response} response for {api_url}. use the given response to answer this {question}", + }); + + const chain = APIChain.fromLLMAndAPIDocs(llm, texts.toString(), { + apiResponsePrompt, + verbose: process.env.DEBUG === 'true' ? true : false, + }) + return chain +} + +module.exports = { nodeClass: ApiChain_Chains } diff --git a/packages/components/nodes/chains/ApiChain/apichain.svg b/packages/components/nodes/chains/ApiChain/apichain.svg new file mode 100644 index 00000000..ef62e168 --- /dev/null +++ b/packages/components/nodes/chains/ApiChain/apichain.svg @@ -0,0 +1,3 @@ + \ No newline at end of file