Skip to content

Commit

Permalink
Core: google docstring parsing fix (#28404)
Browse files Browse the repository at this point in the history
Thank you for contributing to LangChain!

- [ ] **PR title**: "core: google docstring parsing fix"


- [x] **PR message**:
- **Description:** Added a solution for invalid parsing of google
docstring such as:
    Args:
net_annual_income (float): The user's net annual income (in current year
dollars).
- **Issue:** Previous code would return arg = "net_annual_income
(float)" which would cause exception in
_validate_docstring_args_against_annotations
    - **Dependencies:** None

If no one reviews your PR within a few days, please @-mention one of
baskaryan, efriis, eyurtsev, ccurme, vbarda, hwchase17.

Co-authored-by: Erick Friis <[email protected]>
  • Loading branch information
Tesla2000 and efriis authored Dec 10, 2024
1 parent b78b2f7 commit 4e743b5
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
8 changes: 6 additions & 2 deletions libs/core/langchain_core/utils/function_calling.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,9 +646,13 @@ def _parse_google_docstring(
for line in args_block.split("\n")[1:]:
if ":" in line:
arg, desc = line.split(":", maxsplit=1)
arg_descriptions[arg.strip()] = desc.strip()
arg = arg.strip()
arg_name, _, _annotations = arg.partition(" ")
if _annotations.startswith("(") and _annotations.endswith(")"):
arg = arg_name
arg_descriptions[arg] = desc.strip()
elif arg:
arg_descriptions[arg.strip()] += " " + line.strip()
arg_descriptions[arg] += " " + line.strip()
return description, arg_descriptions


Expand Down
15 changes: 15 additions & 0 deletions libs/core/tests/unit_tests/utils/test_function_calling.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ def dummy_function(arg1: int, arg2: Literal["bar", "baz"]) -> None:
return dummy_function


@pytest.fixture()
def function_docstring_annotations() -> Callable:
def dummy_function(arg1: int, arg2: Literal["bar", "baz"]) -> None:
"""dummy function
Args:
arg1 (int): foo
arg2: one of 'bar', 'baz'
"""

return dummy_function


@pytest.fixture()
def runnable() -> Runnable:
class Args(ExtensionsTypedDict):
Expand Down Expand Up @@ -278,6 +291,7 @@ def dummy_function(cls, arg1: int, arg2: Literal["bar", "baz"]) -> None:
def test_convert_to_openai_function(
pydantic: type[BaseModel],
function: Callable,
function_docstring_annotations: Callable,
dummy_structured_tool: StructuredTool,
dummy_tool: BaseTool,
json_schema: dict,
Expand Down Expand Up @@ -311,6 +325,7 @@ def test_convert_to_openai_function(
for fn in (
pydantic,
function,
function_docstring_annotations,
dummy_structured_tool,
dummy_tool,
json_schema,
Expand Down

0 comments on commit 4e743b5

Please sign in to comment.