-
Notifications
You must be signed in to change notification settings - Fork 2k
/
outputParser.ts
167 lines (152 loc) Β· 5.96 KB
/
outputParser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import type { BaseLanguageModelInterface } from "@langchain/core/language_models/base";
import { Callbacks } from "@langchain/core/callbacks/manager";
import { AgentAction, AgentFinish } from "@langchain/core/agents";
import { OutputParserException } from "@langchain/core/output_parsers";
import { renderTemplate } from "@langchain/core/prompts";
import { AgentActionOutputParser } from "../types.js";
import {
AGENT_ACTION_FORMAT_INSTRUCTIONS,
FORMAT_INSTRUCTIONS,
} from "./prompt.js";
import { OutputFixingParser } from "../../output_parsers/fix.js";
/**
* A class that provides a custom implementation for parsing the output of
* a StructuredChatAgent action. It extends the `AgentActionOutputParser`
* class and extracts the action and action input from the text output,
* returning an `AgentAction` or `AgentFinish` object.
*/
export class StructuredChatOutputParser extends AgentActionOutputParser {
lc_namespace = ["langchain", "agents", "structured_chat"];
private toolNames: string[];
constructor(fields: { toolNames: string[] }) {
super(...arguments);
this.toolNames = fields.toolNames;
}
/**
* Parses the given text and returns an `AgentAction` or `AgentFinish`
* object. If an `OutputFixingParser` is provided, it is used for parsing;
* otherwise, the base parser is used.
* @param text The text to parse.
* @param callbacks Optional callbacks for asynchronous operations.
* @returns A Promise that resolves to an `AgentAction` or `AgentFinish` object.
*/
async parse(text: string): Promise<AgentAction | AgentFinish> {
try {
const regex = /```(?:json)?(.*)(```)/gs;
const actionMatch = regex.exec(text);
if (actionMatch === null) {
throw new OutputParserException(
`Could not parse an action. The agent action must be within a markdown code block, and "action" must be a provided tool or "Final Answer"`
);
}
const response = JSON.parse(actionMatch[1].trim());
const { action, action_input } = response;
if (action === "Final Answer") {
return { returnValues: { output: action_input }, log: text };
}
return { tool: action, toolInput: action_input || {}, log: text };
} catch (e) {
throw new OutputParserException(
`Failed to parse. Text: "${text}". Error: ${e}`
);
}
}
/**
* Returns the format instructions for parsing the output of an agent
* action in the style of the StructuredChatAgent.
* @returns A string representing the format instructions.
*/
getFormatInstructions(): string {
return renderTemplate(AGENT_ACTION_FORMAT_INSTRUCTIONS, "f-string", {
tool_names: this.toolNames.join(", "),
});
}
}
/**
* An interface for the arguments used to construct a
* `StructuredChatOutputParserWithRetries` instance.
*/
export interface StructuredChatOutputParserArgs {
baseParser?: StructuredChatOutputParser;
outputFixingParser?: OutputFixingParser<AgentAction | AgentFinish>;
toolNames?: string[];
}
/**
* A class that provides a wrapper around the `StructuredChatOutputParser`
* and `OutputFixingParser` classes. It extends the
* `AgentActionOutputParser` class and allows for retrying the output
* parsing using the `OutputFixingParser` if it is provided.
* @example
* ```typescript
* const outputParser = new StructuredChatOutputParserWithRetries.fromLLM(
* new ChatOpenAI({ temperature: 0 }),
* {
* toolNames: ["calculator", "random-number-generator"],
* },
* );
* const result = await outputParser.parse(
* "What is a random number between 5 and 10 raised to the second power?"
* );
* ```
*/
export class StructuredChatOutputParserWithRetries extends AgentActionOutputParser {
lc_namespace = ["langchain", "agents", "structured_chat"];
private baseParser: StructuredChatOutputParser;
private outputFixingParser?: OutputFixingParser<AgentAction | AgentFinish>;
private toolNames: string[] = [];
constructor(fields: StructuredChatOutputParserArgs) {
super(fields);
this.toolNames = fields.toolNames ?? this.toolNames;
this.baseParser =
fields?.baseParser ??
new StructuredChatOutputParser({ toolNames: this.toolNames });
this.outputFixingParser = fields?.outputFixingParser;
}
/**
* Parses the given text and returns an `AgentAction` or `AgentFinish`
* object. Throws an `OutputParserException` if the parsing fails.
* @param text The text to parse.
* @returns A Promise that resolves to an `AgentAction` or `AgentFinish` object.
*/
async parse(
text: string,
callbacks?: Callbacks
): Promise<AgentAction | AgentFinish> {
if (this.outputFixingParser !== undefined) {
return this.outputFixingParser.parse(text, callbacks);
}
return this.baseParser.parse(text);
}
/**
* Returns the format instructions for parsing the output of an agent
* action in the style of the StructuredChatAgent.
* @returns A string representing the format instructions.
*/
getFormatInstructions(): string {
return renderTemplate(FORMAT_INSTRUCTIONS, "f-string", {
tool_names: this.toolNames.join(", "),
});
}
/**
* Creates a new `StructuredChatOutputParserWithRetries` instance from a
* `BaseLanguageModel` and options. The options can include a base parser
* and tool names.
* @param llm A `BaseLanguageModel` instance.
* @param options Options for creating a `StructuredChatOutputParserWithRetries` instance.
* @returns A new `StructuredChatOutputParserWithRetries` instance.
*/
static fromLLM(
llm: BaseLanguageModelInterface,
options: Omit<StructuredChatOutputParserArgs, "outputFixingParser">
): StructuredChatOutputParserWithRetries {
const baseParser =
options.baseParser ??
new StructuredChatOutputParser({ toolNames: options.toolNames ?? [] });
const outputFixingParser = OutputFixingParser.fromLLM(llm, baseParser);
return new StructuredChatOutputParserWithRetries({
baseParser,
outputFixingParser,
toolNames: options.toolNames,
});
}
}