Skip to content

[Bug] ValueError on Signatures docs page? #8543

@weklund

Description

@weklund

What happened?

Running through the documentation and got a ValueError on the Programming Signatures for 'Working with Custom Types' page.

Want to verify the issue, and maybe even align on propose change?

It seems like the signature parsing can not parse through nested classes, although the docs are using it.

The code in question:

class Container:
    class MyQuery(BaseModel):
        text: str
    class Score(BaseModel):
        score: float


signature = dspy.Signature("query: Container.MyQuery -> score: Container.Score")

Here's the stack

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[24], line 24
     18         score: float
     20 # Extract the nested classes
     21 # MyQuery = Container.MyQuery
     22 # Score = Container.Score
---> 24 signature = dspy.Signature("query: Container.MyQuery -> score: Container.Score")
     25 print(signature)

File [~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py:49](http://localhost:8888/lab/tree/~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py#line=48), in SignatureMeta.__call__(cls, *args, **kwargs)
     46     if custom_types is None and args and isinstance(args[0], str):
     47         custom_types = cls._detect_custom_types_from_caller(args[0])
---> 49     return make_signature(*args, custom_types=custom_types, **kwargs)
     50 return super().__call__(*args, **kwargs)

File [~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py:412](http://localhost:8888/lab/tree/~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py#line=411), in make_signature(signature, instructions, signature_name, custom_types)
    409     names = dict(typing.__dict__)
    410     names.update(custom_types)
--> 412 fields = _parse_signature(signature, names) if isinstance(signature, str) else signature
    414 # Validate the fields, this is important because we sometimes forget the
    415 # slightly unintuitive syntax with tuples of (type, Field)
    416 fixed_fields = {}

File [~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py:457](http://localhost:8888/lab/tree/~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py#line=456), in _parse_signature(signature, names)
    454 inputs_str, outputs_str = signature.split("->")
    456 fields = {}
--> 457 for field_name, field_type in _parse_field_string(inputs_str, names):
    458     fields[field_name] = (field_type, InputField())
    459 for field_name, field_type in _parse_field_string(outputs_str, names):

File [~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py:475](http://localhost:8888/lab/tree/~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py#line=474), in _parse_field_string(field_string, names)
    473 args = ast.parse(f"def f({field_string}): pass").body[0].args.args
    474 field_names = [arg.arg for arg in args]
--> 475 types = [str if arg.annotation is None else _parse_type_node(arg.annotation, names) for arg in args]
    476 return zip(field_names, types)

File [~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py:558](http://localhost:8888/lab/tree/~/Projects/dspy-learning-notebook/.venv/lib/python3.13/site-packages/dspy/signatures/signature.py#line=557), in _parse_type_node(node, names)
    555         if full_name in names:
    556             return names[full_name]
--> 558     raise ValueError(f"Unknown attribute: {attr_name} on {base}")
    560 if isinstance(node, ast.Subscript):
    561     base_type = _parse_type_node(node.value, names)

ValueError: Unknown attribute: MyQuery on typing.Container

I was able to resolve by extracting them:

# Extract the nested classes
MyQuery = Container.MyQuery
Score = Container.Score

signature = dspy.Signature("query: MyQuery -> score: Score")

Not sure if this is bug where we should be supporting nested classes

Steps to reproduce

Steps to reproduce are to run the provided code in a notebook or similar runtime.

DSPy version

2.6.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions