forked from langchain-ai/langchainjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support combining multiple output parsers (langchain-ai#618)
* Create multiparser.ts * Update CombiningParser + example * formatting examples * Update examples/src/prompts/combining_parser.ts * Fix CI * Format --------- Co-authored-by: Nuno Campos <[email protected]>
- Loading branch information
Showing
3 changed files
with
112 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { OpenAI } from "langchain/llms/openai"; | ||
import { PromptTemplate } from "langchain/prompts"; | ||
import { | ||
StructuredOutputParser, | ||
RegexParser, | ||
CombiningOutputParser, | ||
} from "langchain/output_parsers"; | ||
|
||
export const run = async () => { | ||
const answerParser = StructuredOutputParser.fromNamesAndDescriptions({ | ||
answer: "answer to the user's question", | ||
source: "source used to answer the user's question, should be a website.", | ||
}); | ||
|
||
const confidenceParser = new RegexParser( | ||
/Confidence: (A|B|C), Explanation: (.*)/, | ||
["confidence", "explanation"], | ||
"noConfidence" | ||
); | ||
|
||
const parser = new CombiningOutputParser(answerParser, confidenceParser); | ||
const formatInstructions = parser.getFormatInstructions(); | ||
|
||
const prompt = new PromptTemplate({ | ||
template: | ||
"Answer the users question as best as possible.\n{format_instructions}\n{question}", | ||
inputVariables: ["question"], | ||
partialVariables: { format_instructions: formatInstructions }, | ||
}); | ||
|
||
const model = new OpenAI({ temperature: 0 }); | ||
|
||
const input = await prompt.format({ | ||
question: "What is the capital of France?", | ||
}); | ||
const response = await model.call(input); | ||
|
||
console.log(input); | ||
/* | ||
Answer the users question as best as possible. | ||
For your first output: The output should be a markdown code snippet formatted in the following schema: | ||
```json | ||
{ | ||
"answer": string // answer to the user's question | ||
"source": string // source used to answer the user's question, should be a website. | ||
} | ||
``` | ||
Complete that output fully. Then produce another output: Your response should match the following regex: //Confidence: (A|B|C), Explanation: (.*)// | ||
What is the capital of France? | ||
*/ | ||
|
||
console.log(response); | ||
/* | ||
```json | ||
{ | ||
"answer": "Paris", | ||
"source": "https://en.wikipedia.org/wiki/France" | ||
} | ||
``` | ||
//Confidence: A, Explanation: Paris is the capital of France according to Wikipedia.// | ||
*/ | ||
|
||
console.log(await parser.parse(response)); | ||
/* | ||
{ | ||
answer: 'Paris', | ||
source: 'https://en.wikipedia.org/wiki/France', | ||
confidence: 'A', | ||
explanation: 'Paris is the capital of France according to Wikipedia.//' | ||
} | ||
*/ | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { BaseOutputParser } from "../schema/index.js"; | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export type CombinedOutput = Record<string, any>; | ||
|
||
/** | ||
* Class to combine multiple output parsers | ||
* @augments BaseOutputParser | ||
*/ | ||
export class CombiningOutputParser extends BaseOutputParser { | ||
parsers: BaseOutputParser[]; | ||
|
||
constructor(...parsers: BaseOutputParser[]) { | ||
super(); | ||
this.parsers = parsers; | ||
} | ||
|
||
async parse(input: string): Promise<CombinedOutput> { | ||
const ret: CombinedOutput = {}; | ||
for (const p of this.parsers) { | ||
Object.assign(ret, await p.parse(input)); | ||
} | ||
return ret; | ||
} | ||
|
||
getFormatInstructions(): string { | ||
const initial = `For your first output: ${this?.parsers?.[0]?.getFormatInstructions()}`; | ||
const subsequent = this.parsers | ||
.slice(1) | ||
.map( | ||
(p) => | ||
`Complete that output fully. Then produce another output: ${p.getFormatInstructions()}` | ||
) | ||
.join("\n"); | ||
return `${initial}\n${subsequent}`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters