Skip to content

Is here a way to cause the DeepAgent and/or subagents to return the output with favour of zod schema? #51

@kotekpsotek

Description

@kotekpsotek

Does exist builtin mechanism to handle a zod schema as a final output of a createDeepAgent function for convininience?

If not: Can it be implemented in the initial form for deepagent supervisor/planner and the subagents?

Since this method doesn't work:

const agent = createDeepAgent({
        model: supervisorModel.withStructuredOutput(deepAgentsActionAnswerSchema as any),
        tools: [], 
        middleware: [],
        subagents: [
            researcher
        ],
        systemPrompt: systemPromptBasicFiles["supervisor"]
    })

while in ai provider llm handler definition for withStructuredOutput method is:

// ... Class internal scope
withStructuredOutput(outputSchema, config) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const schema = outputSchema;
        const name = config?.name;
        const method = config?.method;
        const includeRaw = config?.includeRaw;
        if (method === "jsonMode") {
            throw new Error(`ChatGoogleGenerativeAI only supports "jsonSchema" or "functionCalling" as a method.`);
        }
        let llm;
        let outputParser;
        if (method === "functionCalling") {
            let functionName = name ?? "extract";
            let tools;
            if (isInteropZodSchema(schema)) {
                const jsonSchema = schemaToGenerativeAIParameters(schema);
                tools = [
                    {
                        functionDeclarations: [
                            {
                                name: functionName,
                                description: jsonSchema.description ?? "A function available to call.",
                                parameters: jsonSchema,
                            },
                        ],
                    },
                ];
                outputParser = new GoogleGenerativeAIToolsOutputParser({
                    returnSingle: true,
                    keyName: functionName,
                    zodSchema: schema,
                });
            }
            else {
                let geminiFunctionDefinition;
                if (typeof schema.name === "string" &&
                    typeof schema.parameters === "object" &&
                    schema.parameters != null) {
                    geminiFunctionDefinition = schema;
                    geminiFunctionDefinition.parameters = removeAdditionalProperties(schema.parameters);
                    functionName = schema.name;
                }
                else {
                    geminiFunctionDefinition = {
                        name: functionName,
                        description: schema.description ?? "",
                        parameters: removeAdditionalProperties(schema),
                    };
                }
                tools = [
                    {
                        functionDeclarations: [geminiFunctionDefinition],
                    },
                ];
                outputParser = new GoogleGenerativeAIToolsOutputParser({
                    returnSingle: true,
                    keyName: functionName,
                });
            }
            llm = this.bindTools(tools).withConfig({
                allowedFunctionNames: [functionName],
            });
        }
        else {
            const jsonSchema = schemaToGenerativeAIParameters(schema);
            llm = this.withConfig({
                responseSchema: jsonSchema,
            });
            outputParser = new JsonOutputParser();
        }
        if (!includeRaw) {
            return llm.pipe(outputParser).withConfig({
                runName: "ChatGoogleGenerativeAIStructuredOutput",
            });
        }
        const parserAssign = RunnablePassthrough.assign({
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            parsed: (input, config) => outputParser.invoke(input.raw, config),
        });
        const parserNone = RunnablePassthrough.assign({
            parsed: () => null,
        });
        const parsedWithFallback = parserAssign.withFallbacks({
            fallbacks: [parserNone],
        });
        return RunnableSequence.from([
            {
                raw: llm,
            },
            parsedWithFallback,
        ]).withConfig({
            runName: "StructuredOutputRunnable",
        });
    }

neither there isn't any property in createDeepAgent config object to provide the output schema in same fashion as is for tool LangChain function.

Additionally:

  • Zod Schema doesn't offer to string parser so there isn't option to simply parse it to string with keeping the specification, although you can use zod-to-json-schema library to make from your schema json output and specify it to the prompt;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions