langchain-ai / langchain-aws

Build LangChain Applications on AWS
MIT License
97 stars 71 forks source link

Fix bug in _drop_none #103

Closed thiagotps closed 2 months ago

thiagotps commented 3 months ago

The current implementation of _drop_none :

def _drop_none(obj: Any) -> Any:
    if isinstance(obj, dict):
        new = {k: _drop_none(v) for k, v in obj.items() if _drop_none(v) is not None}
        return new or None
    else:
        return obj

throws out empty dictionaries.

_drop_none(
    {'tools': [{"toolSpec": {
                    "name": "Answer",
                    "description": "Your answer",
                    "inputSchema": {
                        "json": {
                            "type": "object",
                            "properties": {
                                "answer": {
                                    "type": "string",
                                    "description": "Your answer"
                                },
                            },
                            "required": ["answer"]
                        }
                    }
                }},
            {'toolSpec':
                {
                    "name": "get_weather",
                    "description": "Get the current weather in a given location",
                    "inputSchema": {
                        "json": {
                            "type": "object",
                            "properties": {
                                "location": {
                                    "type": "string",
                                    "description": "The city and state, e.g. San Francisco, CA"
                                },
                                "unit": {
                                    "type": "string",
                                    "enum": ["celsius", "fahrenheit"],
                                    "description": "The unit of temperature, either \"celsius\" or \"fahrenheit\""
                                }
                            },
                            "required": ["location"]
                        }
                    }
                }
                }],
     'toolChoice': {'any': {}}}
)

returns

{'tools': [{'toolSpec': {'name': 'Answer',
    'description': 'Your answer',
    'inputSchema': {'json': {'type': 'object',
      'properties': {'answer': {'type': 'string',
        'description': 'Your answer'}},
      'required': ['answer']}}}},
  {'toolSpec': {'name': 'get_weather',
    'description': 'Get the current weather in a given location',
    'inputSchema': {'json': {'type': 'object',
      'properties': {'location': {'type': 'string',
        'description': 'The city and state, e.g. San Francisco, CA'},
       'unit': {'type': 'string',
        'enum': ['celsius', 'fahrenheit'],
        'description': 'The unit of temperature, either "celsius" or "fahrenheit"'}},
      'required': ['location']}}}}]}

with the 'toolChoice': {'any': {}} part missing.

The new implementation

def _drop_none(obj: Any) -> Any:
    if isinstance(obj, dict):
        new = {k: _drop_none(v) for k, v in obj.items() if _drop_none(v) is not None}
        return new
    else:
        return obj

Correctly handles this case.

_drop_none(
    {'tools': [{"toolSpec": {
                    "name": "Answer",
                    "description": "Your answer",
                    "inputSchema": {
                        "json": {
                            "type": "object",
                            "properties": {
                                "answer": {
                                    "type": "string",
                                    "description": "Your answer"
                                },
                            },
                            "required": ["answer"]
                        }
                    }
                }},
            {'toolSpec':
                {
                    "name": "get_weather",
                    "description": "Get the current weather in a given location",
                    "inputSchema": {
                        "json": {
                            "type": "object",
                            "properties": {
                                "location": {
                                    "type": "string",
                                    "description": "The city and state, e.g. San Francisco, CA"
                                },
                                "unit": {
                                    "type": "string",
                                    "enum": ["celsius", "fahrenheit"],
                                    "description": "The unit of temperature, either \"celsius\" or \"fahrenheit\""
                                }
                            },
                            "required": ["location"]
                        }
                    }
                }
                }],
     'toolChoice': {'any': {}}}
)

which results in

{'tools': [{'toolSpec': {'name': 'Answer',
    'description': 'Your answer',
    'inputSchema': {'json': {'type': 'object',
      'properties': {'answer': {'type': 'string',
        'description': 'Your answer'}},
      'required': ['answer']}}}},
  {'toolSpec': {'name': 'get_weather',
    'description': 'Get the current weather in a given location',
    'inputSchema': {'json': {'type': 'object',
      'properties': {'location': {'type': 'string',
        'description': 'The city and state, e.g. San Francisco, CA'},
       'unit': {'type': 'string',
        'enum': ['celsius', 'fahrenheit'],
        'description': 'The unit of temperature, either "celsius" or "fahrenheit"'}},
      'required': ['location']}}}}],
 'toolChoice': {'any': {}}}
thiagotps commented 3 months ago

@3coins Can you please have a look ? Thanks in advance.