This is how I am defining the executor
const executor = await initializeAgentExecutorWithOptions(tools, model, {
agentType: 'chat-conversational-react-description',
verbose: false,
});
Whenever I prompt the AI I have this statement at the end.
type SomeObject = {
field1: number,
field2: number,
}
- It is very critical that you answer only as the above object and JSON stringify it as a single string.
Don't include any other verbose explanatiouns and don't include the markdown syntax anywhere.
The SomeObject
is just an example. Usually it will have a proper object type.
When I use the executor
to get a response from the AI, half the time I get the proper JSON string, but the other half the times are the AI completely ignoring my instructions and gives me a long verbose answer in just plain English...
How can I make sure I always get the structured data answer I want?
Maybe using the agentType: 'chat-conversational-react-description'
isn't the right approach here?
OpenAI announced today a new “JSON Mode” at the DevDay Keynote. When activated the model will only generate responses using the JSON
format.
You can refer to the official docs here.
That's a great question and LangChain
provides an easy solution. Look at LangChain's Output Parsers
if you want a quick answer. It is the recommended way to process LLM output into a specified format.
Here's the official link from the docs:
Side note: I wrote an introductory tutorial about this particular issue but for Python, so if anyone else is interested in more details you can check it out here.
The example below does not use initializeAgentExecutorWithOptions
, but will ensure that the output is processed as JSON
without specifying this explicitly in your system prompt.
In order to tell LangChain that we'll need to convert the LLM response to a JSON
output, we'll need to define a StructuredOutputParser
and pass it to our chain
.
parser
:Here's an example:
// Let's define our parser
const parser = StructuredOutputParser.fromZodSchema(
z.object({
field1: z.string().describe("first field"),
field2: z.string().describe("second field")
})
);
Chain
:// We can then add it to our chain
const chain = RunnableSequence.from([
PromptTemplate.fromTemplate(...),
new OpenAI({ temperature: 0 }),
parser, // <-- this line
]);
format_instructions
:// Finally, we'll pass the format instructions to the invoke method
const response = await chain.invoke({
question: "What is the capital of France?",
format_instructions: parser.getFormatInstructions(), // <-- this line
});
Go ahead and log the parser.getFormatInstructions()
method before you call invoke
if you'd like to see the output.
When we pass parser.getFormatInstructions()
to the format_instructions
property, this lets LangChain append the desired JSON
schema that we defined in step 1 to our prompt before sending it to the large language model.
As a final point, it is absolutely critical to make sure your query/prompt is relevant and produces values that could be interpreted as the properties in your object SomeObject
that are defined in the parser
.
Please give this a try, and let me know if you're able to consistently output JSON
.