Repository: stanfordnlp/dspy
Pull request #8536 (2025-07-16 10:31:07)

Remove or rephrase todo comments in the community pages
The community pages contained some TODO comments or Wip comments that should not be displayed in the public website. This PR rephrased/removed these comments.


Patch:
diff --git a/docs/docs/community/community-resources.md b/docs/docs/community/community-resources.md
index 93173737..7adf149a 100644
--- a/docs/docs/community/community-resources.md
+++ b/docs/docs/community/community-resources.md
@@ -60,7 +60,7 @@ Weaviate has a directory of 10 amazing notebooks and 6 podcasts!
 Huge shoutout to them for the massive support ❤️. See the [Weaviate DSPy directory](https://weaviate.io/developers/weaviate/more-resources/dspy).
 
 
-TODO: This list in particular is highly incomplete. There are dozens of other good ones. To allow space, divide into opintionated blogs / podcasts / interviews vs. tutorials & talks.
+This list represents a curated selection of DSPy resources. We continuously add new content as it becomes available in the community.
 
 Credit: Some of these resources were originally compiled in the [Awesome DSPy](https://github.com/ganarajpr/awesome-dspy/tree/master) repo.
 
diff --git a/docs/docs/community/use-cases.md b/docs/docs/community/use-cases.md
index 02e7204a..5f9c3c31 100644
--- a/docs/docs/community/use-cases.md
+++ b/docs/docs/community/use-cases.md
@@ -2,7 +2,7 @@
 
 We often get questions like “How are people using DSPy in practice?”, both in production and for research. This list was created to collect a few pointers and to encourage others in the community to add their own work below.
 
-This list is ever-expanding and highly incomplete (WIP)! We'll be adding a bunch more. If you would like to add your product or research to this list, please submit a PR.
+This list is continuously growing. We regularly add new use cases and welcome community contributions. If you would like to add your product or research to this list, please submit a PR.
 
 ## A Few Company Use Cases
 
@@ -35,7 +35,7 @@ This list is ever-expanding and highly incomplete (WIP)! We'll be adding a bunch
 | **[Pretrain](https://pretrain.com)** | Uses DSPy to automatically optimize AI performance towards user-defined tasks based on uploaded examples. |
 | **[Spindle AI](https://spindle.ai)** | Turns natural-language constrained optimization problems into solvable mathematical programs whose candidate solutions are scenarios. |
 
-WIP. This list mainly the small fraction of companies that have public posts or have OKed being publicly included for specific products so far, out of hundreds of other industry use cases.
+This list represents companies that have publicly shared their use cases or have provided permission to be included. It reflects a selection of the many industry applications of DSPy currently in production.
 
 
 ## A Few Papers Using DSPy
@@ -57,7 +57,7 @@ WIP. This list mainly the small fraction of companies that have public posts or
 | **[Co-STORM](https://arxiv.org/pdf/2408.15232)** | Collaborative STORM: Generate Wikipedia-like articles through collaborative discourse among users and multiple LM agents |
 | **[MedVAL](https://arxiv.org/abs/2507.03152)** | Expert-level validation of AI-generated medical text with scalable language models |
 
-WIP, this list is highly outdated and incomplete.
+This list is regularly updated with new research publications using DSPy.
 
 ## A Few Repositories (or other OSS examples) using DSPy
 
@@ -86,7 +86,7 @@ WIP, this list is highly outdated and incomplete.
 | **Self Discover**| [Github](https://colab.research.google.com/drive/1GkAQKmw1XQgg5UNzzy8OncRe79V6pADB?usp=sharing) |
 | **MedVAL**| [Github](https://github.com/StanfordMIMI/MedVAL) |
 
-TODO: This list in particular is highly incomplete. There are a couple dozen other good ones.
+This list showcases some of the open-source projects and repositories using DSPy, with many more examples available in the community.
 
 ## A Few Providers, Integrations, and related Blog Releases
 
diff --git a/dspy/adapters/types/tool.py b/dspy/adapters/types/tool.py
index b3e6b451..843eceed 100644
--- a/dspy/adapters/types/tool.py
+++ b/dspy/adapters/types/tool.py
@@ -103,7 +103,7 @@ class Tool(Type):
                 v_json_schema = _resolve_json_schema_reference(v.model_json_schema())
                 args[k] = v_json_schema
             else:
-                args[k] = TypeAdapter(v).json_schema()
+                args[k] = _resolve_json_schema_reference(TypeAdapter(v).json_schema())
             if default_values[k] is not inspect.Parameter.empty:
                 args[k]["default"] = default_values[k]
             if arg_desc and k in arg_desc:


Test patch:
diff --git a/tests/adapters/test_tool.py b/tests/adapters/test_tool.py
index 20f59604..18571453 100644
--- a/tests/adapters/test_tool.py
+++ b/tests/adapters/test_tool.py
@@ -50,7 +50,12 @@ class UserProfile(BaseModel):
     tags: list[str] = []
 
 
-def complex_dummy_function(profile: UserProfile, priority: int, notes: str | None = None) -> dict[str, Any]:
+class Note(BaseModel):
+    content: str
+    author: str
+
+
+def complex_dummy_function(profile: UserProfile, priority: int, notes: list[Note] | None = None) -> dict[str, Any]:
     """Process user profile with complex nested structure.
 
     Args:
@@ -89,7 +94,9 @@ async def async_dummy_with_pydantic(model: DummyModel) -> str:
 
 
 async def async_complex_dummy_function(
-    profile: UserProfile, priority: int, notes: str | None = None
+    profile: UserProfile,
+    priority: int,
+    notes: list[Note] | None = None,
 ) -> dict[str, Any]:
     """Process user profile with complex nested structure asynchronously.
 
@@ -167,6 +174,7 @@ def test_tool_from_function_with_pydantic_nesting():
     tool = Tool(complex_dummy_function)
 
     assert tool.name == "complex_dummy_function"
+
     assert "profile" in tool.args
     assert "priority" in tool.args
     assert "notes" in tool.args
@@ -177,6 +185,13 @@ def test_tool_from_function_with_pydantic_nesting():
     assert tool.args["profile"]["properties"]["contact"]["type"] == "object"
     assert tool.args["profile"]["properties"]["contact"]["properties"]["email"]["type"] == "string"
 
+    # Reference should be resolved for nested pydantic models
+    assert "$defs" not in str(tool.args["notes"])
+    assert tool.args["notes"]["anyOf"][0]["type"] == "array"
+    assert tool.args["notes"]["anyOf"][0]["items"]["type"] == "object"
+    assert tool.args["notes"]["anyOf"][0]["items"]["properties"]["content"]["type"] == "string"
+    assert tool.args["notes"]["anyOf"][0]["items"]["properties"]["author"]["type"] == "string"
+
 
 def test_tool_callable():
     tool = Tool(dummy_function)
@@ -319,11 +334,11 @@ async def test_async_tool_with_complex_pydantic():
         ),
     )
 
-    result = await tool.acall(profile=profile, priority=1, notes="Test note")
+    result = await tool.acall(profile=profile, priority=1, notes=[Note(content="Test note", author="Test author")])
     assert result["user_id"] == 1
     assert result["name"] == "Test User"
     assert result["priority"] == 1
-    assert result["notes"] == "Test note"
+    assert result["notes"] == [Note(content="Test note", author="Test author")]
     assert result["primary_address"]["street"] == "123 Main St"
 
 
@@ -382,42 +397,39 @@ TOOL_CALL_TEST_CASES = [
     ([], [{"type": "tool_calls", "tool_calls": []}]),
     (
         [{"name": "search", "args": {"query": "hello"}}],
-        [{
-            "type": "tool_calls",
-            "tool_calls": [{
-                "type": "function",
-                "function": {"name": "search", "arguments": {"query": "hello"}}
-            }]
-        }],
+        [
+            {
+                "type": "tool_calls",
+                "tool_calls": [{"type": "function", "function": {"name": "search", "arguments": {"query": "hello"}}}],
+            }
+        ],
     ),
     (
         [
             {"name": "search", "args": {"query": "hello"}},
-            {"name": "translate", "args": {"text": "world", "lang": "fr"}}
+            {"name": "translate", "args": {"text": "world", "lang": "fr"}},
+        ],
+        [
+            {
+                "type": "tool_calls",
+                "tool_calls": [
+                    {"type": "function", "function": {"name": "search", "arguments": {"query": "hello"}}},
+                    {
+                        "type": "function",
+                        "function": {"name": "translate", "arguments": {"text": "world", "lang": "fr"}},
+                    },
+                ],
+            }
         ],
-        [{
-            "type": "tool_calls",
-            "tool_calls": [
-                {
-                    "type": "function",
-                    "function": {"name": "search", "arguments": {"query": "hello"}}
-                },
-                {
-                    "type": "function",
-                    "function": {"name": "translate", "arguments": {"text": "world", "lang": "fr"}}
-                }
-            ]
-        }],
     ),
     (
         [{"name": "get_time", "args": {}}],
-        [{
-            "type": "tool_calls",
-            "tool_calls": [{
-                "type": "function",
-                "function": {"name": "get_time", "arguments": {}}
-            }]
-        }],
+        [
+            {
+                "type": "tool_calls",
+                "tool_calls": [{"type": "function", "function": {"name": "get_time", "arguments": {}}}],
+            }
+        ],
     ),
 ]
 
@@ -431,11 +443,12 @@ def test_tool_calls_format_basic(tool_calls_data, expected):
 
     assert result == expected
 
+
 def test_tool_calls_format_from_dict_list():
     """Test format works with ToolCalls created from from_dict_list."""
     tool_calls_dicts = [
         {"name": "search", "args": {"query": "hello"}},
-        {"name": "translate", "args": {"text": "world", "lang": "fr"}}
+        {"name": "translate", "args": {"text": "world", "lang": "fr"}},
     ]
 
     tool_calls = ToolCalls.from_dict_list(tool_calls_dicts)