Search code examples
pythonopenai-apilangchainpy-langchain

define an output schema for a nested json in langchain


Whats the recommended way to define an output schema for a nested json, the method I use doesn't feel ideal.

# adding to planner -> from langchain.experimental.plan_and_execute import load_chat_planner

refinement_response_schemas = [
        ResponseSchema(name="plan", description="""{'1': {'step': '','tools': [],'data_sources': [],'sub_steps_needed': bool},
 '2': {'step': '','tools': [<empty list>],'data_sources': [<>], 'sub_steps_needed': bool},}"""),] #define json schema in description, works but doesn't feel proper
    
refinement_output_parser = StructuredOutputParser.from_response_schemas(refinement_response_schemas)
refinement_format_instructions = refinement_output_parser.get_format_instructions()

refinement_output_parser.parse(output)

gives:

{'plan': {'1': {'step': 'Identify the top 5 strikers in La Liga',
   'tools': [],
   'data_sources': ['sports websites', 'official league statistics'],
   'sub_steps_needed': False},
  '2': {'step': 'Identify the top 5 strikers in the Premier League',
   'tools': [],
   'data_sources': ['sports websites', 'official league statistics'],
   'sub_steps_needed': False},
    ...
  '6': {'step': 'Given the above steps taken, please respond to the users original question',
   'tools': [],
   'data_sources': [],
   'sub_steps_needed': False}}}

it works but I want to know if theres a better way to go about this.


Solution

  • From what I can see the recommended approach is to use the pydantic output parser as opposed to the structured output parser... python.langchain.com/docs/modules/model_io/output_parsers/… (and dealing with nesting explained here... youtube.com/watch?v=yD_oDTeObJY).

    e.g.

    from langchain.output_parsers import PydanticOutputParser
    from pydantic import BaseModel, Field, validator
    from typing import List, Optional
    
    ...
    
    class PlanItem(BaseModel):
        step: str
        tools: Optional[str] = []
        data_sources: Optional[str] = []
        sub_steps_needed: str
    
    class Plan(BaseModel):
        plan: List[PlanItem]
    
    
    parser = PydanticOutputParser(pydantic_object=Plan)
    parser.get_format_instructions()