Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"NameError: name 'FilePath' is not defined" in calling create_schema_from_function #27226

Open
5 tasks done
MRYingLEE opened this issue Oct 9, 2024 · 1 comment
Open
5 tasks done
Labels
🤖:bug Related to a bug, vulnerability, unexpected error with an existing feature

Comments

@MRYingLEE
Copy link

Checked other resources

  • I added a very descriptive title to this issue.
  • I searched the LangChain documentation with the integrated search.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).

Example Code

The following code:

from langchain_core.tools.base import (
    create_schema_from_function as create_schema_from_function,
)
    
import pandas
func=pandas.read_csv
print(type(func))
print(func.__name__)
print(func.__qualname__)

model = create_schema_from_function(
    func_name,
    func,
    filter_args=(),
    parse_docstring=True,
    error_on_invalid_docstring=False,
    include_injected=False,
)

Error Message and Stack Trace (if applicable)

<class 'function'>
read_csv
read_csv

NameError Traceback (most recent call last)
Cell In[27], line 11
8 print(func.name)
9 print(func.qualname)
---> 11 model = create_schema_from_function(
12 func_name,
13 func,
14 filter_args=(),
15 parse_docstring=True,
16 error_on_invalid_docstring=False,
17 include_injected=False,
18 )

File /lib/python3.12/site-packages/langchain_core/tools/base.py:249, in create_schema_from_function(model_name, func, filter_args, parse_docstring, error_on_invalid_docstring, include_injected)
244 with warnings.catch_warnings():
245 # We are using deprecated functionality here.
246 # This code should be re-written to simply construct a pydantic model
247 # using inspect.signature and create_model.
248 warnings.simplefilter("ignore", category=PydanticDeprecationWarning)
--> 249 validated = validate_arguments(func, config=_SchemaConfig) # type: ignore
251 # Let's ignore self and cls arguments for class and instance methods
252 # If qualified name has a ".", then it likely belongs in a class namespace
253 in_class = bool(func.qualname and "." in func.qualname)

File /lib/python3.12/site-packages/pydantic/deprecated/decorator.py:64, in validate_arguments(func, config)
61 return wrapper_function
63 if func:
---> 64 return validate(func)
65 else:
66 return validate

File /lib/python3.12/site-packages/pydantic/deprecated/decorator.py:51, in validate_arguments..validate(_func)
50 def validate(_func: 'AnyCallable') -> 'AnyCallable':
---> 51 vd = ValidatedFunction(_func, config)
53 @wraps(_func)
54 def wrapper_function(*args: Any, **kwargs: Any) -> Any:
55 return vd.call(*args, **kwargs)

File /lib/python3.12/site-packages/pydantic/deprecated/decorator.py:94, in ValidatedFunction.init(self, function, config)
91 self.v_args_name = 'args'
92 self.v_kwargs_name = 'kwargs'
---> 94 type_hints = _typing_extra.get_type_hints(function, include_extras=True)
95 takes_args = False
96 takes_kwargs = False

File /lib/python312.zip/typing.py:2246, in get_type_hints(obj, globalns, localns, include_extras)
2238 if isinstance(value, str):
2239 # class-level forward refs were handled above, this must be either
2240 # a module-level annotation or a function argument annotation
2241 value = ForwardRef(
2242 value,
2243 is_argument=not isinstance(obj, types.ModuleType),
2244 is_class=False,
2245 )
-> 2246 hints[name] = _eval_type(value, globalns, localns)
2247 return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()}

File /lib/python312.zip/typing.py:400, in _eval_type(t, globalns, localns, recursive_guard)
393 """Evaluate all forward references in the given type t.
394
395 For use of globalns and localns see the docstring for get_type_hints().
396 recursive_guard is used to prevent infinite recursion with a recursive
397 ForwardRef.
398 """
399 if isinstance(t, ForwardRef):
--> 400 return t._evaluate(globalns, localns, recursive_guard)
401 if isinstance(t, (_GenericAlias, GenericAlias, types.UnionType)):
402 if isinstance(t, GenericAlias):

File /lib/python312.zip/typing.py:907, in ForwardRef.evaluate(self, globalns, localns, recursive_guard)
902 if self.forward_module is not None:
903 globalns = getattr(
904 sys.modules.get(self.forward_module, None), 'dict', globalns
905 )
906 type
= _type_check(
--> 907 eval(self.forward_code, globalns, localns),
908 "Forward references must evaluate to types.",
909 is_argument=self.forward_is_argument,
910 allow_special_forms=self.forward_is_class,
911 )
912 self.forward_value = eval_type(
913 type
, globalns, localns, recursive_guard | {self.forward_arg}
914 )
915 self.forward_evaluated = True

File :1

NameError: name 'FilePath' is not defined

NameError Traceback (most recent call last)
Cell In[27], line 11
8 print(func.name)
9 print(func.qualname)
---> 11 model = create_schema_from_function(
12 func_name,
13 func,
14 filter_args=(),
15 parse_docstring=True,
16 error_on_invalid_docstring=False,
17 include_injected=False,
18 )

File /lib/python3.12/site-packages/langchain_core/tools/base.py:249, in create_schema_from_function(model_name, func, filter_args, parse_docstring, error_on_invalid_docstring, include_injected)
244 with warnings.catch_warnings():
245 # We are using deprecated functionality here.
246 # This code should be re-written to simply construct a pydantic model
247 # using inspect.signature and create_model.
248 warnings.simplefilter("ignore", category=PydanticDeprecationWarning)
--> 249 validated = validate_arguments(func, config=_SchemaConfig) # type: ignore
251 # Let's ignore self and cls arguments for class and instance methods
252 # If qualified name has a ".", then it likely belongs in a class namespace
253 in_class = bool(func.qualname and "." in func.qualname)

File /lib/python3.12/site-packages/pydantic/deprecated/decorator.py:64, in validate_arguments(func, config)
61 return wrapper_function
63 if func:
---> 64 return validate(func)
65 else:
66 return validate

File /lib/python3.12/site-packages/pydantic/deprecated/decorator.py:51, in validate_arguments..validate(_func)
50 def validate(_func: 'AnyCallable') -> 'AnyCallable':
---> 51 vd = ValidatedFunction(_func, config)
53 @wraps(_func)
54 def wrapper_function(*args: Any, **kwargs: Any) -> Any:
55 return vd.call(*args, **kwargs)

File /lib/python3.12/site-packages/pydantic/deprecated/decorator.py:94, in ValidatedFunction.init(self, function, config)
91 self.v_args_name = 'args'
92 self.v_kwargs_name = 'kwargs'
---> 94 type_hints = _typing_extra.get_type_hints(function, include_extras=True)
95 takes_args = False
96 takes_kwargs = False

File /lib/python312.zip/typing.py:2246, in get_type_hints(obj, globalns, localns, include_extras)
2238 if isinstance(value, str):
2239 # class-level forward refs were handled above, this must be either
2240 # a module-level annotation or a function argument annotation
2241 value = ForwardRef(
2242 value,
2243 is_argument=not isinstance(obj, types.ModuleType),
2244 is_class=False,
2245 )
-> 2246 hints[name] = _eval_type(value, globalns, localns)
2247 return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()}

File /lib/python312.zip/typing.py:400, in _eval_type(t, globalns, localns, recursive_guard)
393 """Evaluate all forward references in the given type t.
394
395 For use of globalns and localns see the docstring for get_type_hints().
396 recursive_guard is used to prevent infinite recursion with a recursive
397 ForwardRef.
398 """
399 if isinstance(t, ForwardRef):
--> 400 return t._evaluate(globalns, localns, recursive_guard)
401 if isinstance(t, (_GenericAlias, GenericAlias, types.UnionType)):
402 if isinstance(t, GenericAlias):

File /lib/python312.zip/typing.py:907, in ForwardRef.evaluate(self, globalns, localns, recursive_guard)
902 if self.forward_module is not None:
903 globalns = getattr(
904 sys.modules.get(self.forward_module, None), 'dict', globalns
905 )
906 type
= _type_check(
--> 907 eval(self.forward_code, globalns, localns),
908 "Forward references must evaluate to types.",
909 is_argument=self.forward_is_argument,
910 allow_special_forms=self.forward_is_class,
911 )
912 self.forward_value = eval_type(
913 type
, globalns, localns, recursive_guard | {self.forward_arg}
914 )
915 self.forward_evaluated = True

File :1

NameError: name 'FilePath' is not defined

Description

I tried to call create_schema_from_function on some popular functions, such as pandas.read_csv, to generate schema for OpenAI structured outputs.

System Info

System Information

OS: Emscripten
OS Version: #1
Python Version: 3.12.1 (main, Jul 26 2024, 14:03:47) [Clang 19.0.0git (https:/github.com/llvm/llvm-project 0a8cd1ed1f4f35905df318015b

Package Information

langchain_core: 0.3.10
langsmith: 0.1.132

Optional packages not installed

langgraph
langserve

Other Dependencies

httpx: 0.27.2
jsonpatch: 1.33
orjson: 3.10.1
packaging: 23.2
pydantic: 2.7.0
PyYAML: 6.0.1
requests: 2.31.0
requests-toolbelt: 1.0.0
tenacity: 8.5.0
typing-extensions: 4.11.0

@dosubot dosubot bot added the 🤖:bug Related to a bug, vulnerability, unexpected error with an existing feature label Oct 9, 2024
@eyurtsev
Copy link
Collaborator

eyurtsev commented Oct 9, 2024

There's some issue with resolving forward references. We could take a look, but i don't recommend doing this.

read_csv has a very large function signature. feeding all of this into a chat model is probably going to result in pretty bad performance and expensive calls due to higher token usage.

Instead I'd recommend being much more selective of the surface area of the tool that you're exposing.

from langchain_core.tools import tool

@tool
def read_csv(my_argument: str):
   """Carefully document what the tool does."""
   df =  pd.DataFrame(my_argument)
   # what do you want to do with df here -- chat models expect a string.
   
   return df

you could return an arficat, but i'd recommend reading the relevant how to guide: https://python.langchain.com/docs/how_to/tool_artifacts/#defining-the-tool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖:bug Related to a bug, vulnerability, unexpected error with an existing feature
Projects
None yet
Development

No branches or pull requests

2 participants