Skip to content

Commit

Permalink
Support combining multiple output parsers (langchain-ai#618)
Browse files Browse the repository at this point in the history
* 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
jmandel and nfcampos authored Apr 11, 2023
1 parent 883ddec commit 47539da
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 0 deletions.
74 changes: 74 additions & 0 deletions examples/src/prompts/combining_parser.ts
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.//'
}
*/
};
37 changes: 37 additions & 0 deletions langchain/src/output_parsers/combining.ts
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}`;
}
}
1 change: 1 addition & 0 deletions langchain/src/output_parsers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { ListOutputParser, CommaSeparatedListOutputParser } from "./list.js";
export { RegexParser } from "./regex.js";
export { StructuredOutputParser } from "./structured.js";
export { OutputFixingParser } from "./fix.js";
export { CombiningOutputParser } from "./combining.js";

0 comments on commit 47539da

Please sign in to comment.