VibecoderMcSwaggins commited on
Commit
534dece
Β·
1 Parent(s): e324277

docs: Add P0 AIFunction serialization bug (Free Tier broken)

Browse files
docs/bugs/ACTIVE_BUGS.md CHANGED
@@ -1,10 +1,34 @@
1
  # Active Bugs
2
 
3
- > Last updated: 2025-12-01 (16:15 PST)
4
  >
5
  > **Note:** Completed bug docs archived to `docs/bugs/archive/`
6
  > **See also:** [Code Quality Audit Findings (2025-11-30)](AUDIT_FINDINGS_2025_11_30.md)
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  ## P3 - UX Polish
9
 
10
  ### P3 - Progress Bar Positioning/Overlap in ChatInterface
 
1
  # Active Bugs
2
 
3
+ > Last updated: 2025-12-01 (16:30 PST)
4
  >
5
  > **Note:** Completed bug docs archived to `docs/bugs/archive/`
6
  > **See also:** [Code Quality Audit Findings (2025-11-30)](AUDIT_FINDINGS_2025_11_30.md)
7
 
8
+ ## P0 - Critical
9
+
10
+ ### P0 - AIFunction Not JSON Serializable (Free Tier Broken)
11
+ **File:** `docs/bugs/P0_AIFUNCTION_NOT_JSON_SERIALIZABLE.md`
12
+ **Found:** 2025-12-01 (HuggingFace Spaces)
13
+
14
+ **Problem:** Every search round fails with "Object of type AIFunction is not JSON serializable".
15
+
16
+ **Error:**
17
+ ```
18
+ πŸ“š SEARCH_COMPLETE: searcher: Agent searcher: Error processing request -
19
+ Object of type AIFunction is not JSON serializable
20
+ ```
21
+
22
+ **Root Cause:** `HuggingFaceChatClient` passes raw `AIFunction` objects to `InferenceClient.chat_completion()`. When `requests` tries to serialize them to JSON, it fails.
23
+
24
+ **Impact:** Free Tier cannot do any research. 5 rounds of errors, no results.
25
+
26
+ **Proposed Fix:** Either:
27
+ 1. **Quick**: Disable tools with `tools=None` (agents use natural language)
28
+ 2. **Proper**: Convert `AIFunction` to JSON schema before passing to HF API
29
+
30
+ ---
31
+
32
  ## P3 - UX Polish
33
 
34
  ### P3 - Progress Bar Positioning/Overlap in ChatInterface
docs/bugs/P0_AIFUNCTION_NOT_JSON_SERIALIZABLE.md ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # P0 Bug: AIFunction Not JSON Serializable (Free Tier Broken)
2
+
3
+ **Severity**: P0 (Critical) - Free Tier cannot perform research
4
+ **Status**: Open
5
+ **Discovered**: 2025-12-01
6
+ **Reporter**: Production user via HuggingFace Spaces
7
+
8
+ ## Symptom
9
+
10
+ Every search round fails with:
11
+ ```
12
+ πŸ“š SEARCH_COMPLETE: searcher: Agent searcher: Error processing request -
13
+ Object of type AIFunction is not JSON serializable
14
+ ```
15
+
16
+ Research never completes. Users see 5 rounds of the same error.
17
+
18
+ ## Root Cause
19
+
20
+ ### The Problem
21
+
22
+ In `src/clients/huggingface.py` lines 82-103:
23
+
24
+ ```python
25
+ # Extract tool configuration
26
+ tools = chat_options.tools if chat_options.tools else None # AIFunction objects!
27
+ ...
28
+ call_fn = partial(
29
+ self._client.chat_completion,
30
+ messages=hf_messages,
31
+ tools=tools, # <-- RAW AIFunction objects passed here
32
+ ...
33
+ )
34
+ ```
35
+
36
+ The `chat_options.tools` contains `AIFunction` objects from Microsoft's agent-framework.
37
+ When `requests` tries to serialize these for the HTTP request, it fails:
38
+ ```
39
+ TypeError: Object of type AIFunction is not JSON serializable
40
+ ```
41
+
42
+ ### Why This Happens
43
+
44
+ 1. Microsoft's agent-framework defines tools as `AIFunction` objects
45
+ 2. `ChatAgent` with tools passes them via `chat_options.tools`
46
+ 3. Our `HuggingFaceChatClient` forwards them directly to `InferenceClient.chat_completion()`
47
+ 4. `requests.post()` internally calls `json.dumps()` on the request body
48
+ 5. `AIFunction` has no `__json__()` method or isn't a dict β†’ TypeError
49
+
50
+ ### The Warning We Ignored
51
+
52
+ The agent framework already warned us:
53
+ ```
54
+ [WARNING] The provided chat client does not support function invoking,
55
+ this might limit agent capabilities.
56
+ ```
57
+
58
+ ## Impact
59
+
60
+ | Component | Impact |
61
+ |-----------|--------|
62
+ | Free Tier (HuggingFace) | **COMPLETELY BROKEN** |
63
+ | Advanced Mode without API key | **Cannot do research** |
64
+ | Paid Tier (OpenAI) | Unaffected (OpenAI handles AIFunction) |
65
+
66
+ ## Proposed Solutions
67
+
68
+ ### Option 1: Disable Tools for HuggingFace (QUICK FIX)
69
+
70
+ Pass `tools=None` to disable function calling entirely:
71
+
72
+ ```python
73
+ # src/clients/huggingface.py
74
+
75
+ async def _inner_get_response(self, ...):
76
+ hf_messages = self._convert_messages(messages)
77
+
78
+ # QUICK FIX: Disable tools - HuggingFace free tier doesn't reliably support them
79
+ # The agents will use natural language instructions instead
80
+ tools = None # Was: chat_options.tools if chat_options.tools else None
81
+ hf_tool_choice = None
82
+ ...
83
+ ```
84
+
85
+ **Pros**:
86
+ - 5-minute fix
87
+ - No serialization errors
88
+ - Agents still work via natural language instructions
89
+
90
+ **Cons**:
91
+ - Agents can't use structured tool calls
92
+ - Less precise than function calling
93
+ - Qwen2.5-72B DOES support function calling (we're not using it)
94
+
95
+ ### Option 2: Convert AIFunction to JSON Schema (PROPER FIX)
96
+
97
+ Serialize `AIFunction` objects to OpenAI-compatible tool format:
98
+
99
+ ```python
100
+ def _convert_tools(self, tools: list[Any] | None) -> list[dict[str, Any]] | None:
101
+ """Convert AIFunction objects to JSON-serializable tool definitions."""
102
+ if not tools:
103
+ return None
104
+
105
+ json_tools = []
106
+ for tool in tools:
107
+ if hasattr(tool, 'to_dict'):
108
+ # AIFunction.to_dict() returns JSON-serializable dict
109
+ json_tools.append(tool.to_dict())
110
+ elif hasattr(tool, 'schema'):
111
+ # Alternative: use schema property
112
+ json_tools.append({
113
+ "type": "function",
114
+ "function": {
115
+ "name": tool.name,
116
+ "description": tool.description,
117
+ "parameters": tool.schema,
118
+ }
119
+ })
120
+ else:
121
+ # Fallback: skip unknown tool types
122
+ logger.warning(f"Skipping non-serializable tool: {type(tool)}")
123
+
124
+ return json_tools if json_tools else None
125
+ ```
126
+
127
+ **Pros**:
128
+ - Proper function calling with Qwen2.5
129
+ - Structured tool invocation
130
+ - Better agent capabilities
131
+
132
+ **Cons**:
133
+ - More complex
134
+ - Need to handle tool call responses
135
+ - May require testing with different HF models
136
+
137
+ ### Option 3: Hybrid Approach (RECOMMENDED)
138
+
139
+ Try to convert tools, fall back to None if it fails:
140
+
141
+ ```python
142
+ def _convert_tools(self, tools: list[Any] | None) -> list[dict[str, Any]] | None:
143
+ """Attempt to convert tools to JSON, disable if conversion fails."""
144
+ if not tools:
145
+ return None
146
+
147
+ try:
148
+ json_tools = []
149
+ for tool in tools:
150
+ if hasattr(tool, 'to_dict'):
151
+ json_tools.append(tool.to_dict())
152
+ elif isinstance(tool, dict):
153
+ json_tools.append(tool)
154
+ return json_tools if json_tools else None
155
+ except Exception as e:
156
+ logger.warning(f"Tool conversion failed, disabling function calling: {e}")
157
+ return None
158
+ ```
159
+
160
+ ## Recommended Fix
161
+
162
+ **Immediate (P0)**: Option 1 - Disable tools with `tools=None`
163
+ **Follow-up**: Option 3 - Implement proper conversion with fallback
164
+
165
+ ## Call Stack Trace
166
+
167
+ ```
168
+ User Query (HuggingFace Spaces)
169
+ ↓
170
+ src/app.py:research_agent()
171
+ ↓
172
+ src/orchestrators/advanced.py:AdvancedOrchestrator.run()
173
+ ↓
174
+ agent_framework.MagenticBuilder.run_stream()
175
+ ↓
176
+ agent_framework.ChatAgent (SearchAgent with tools=[search_pubmed, ...])
177
+ ↓
178
+ src/clients/huggingface.py:HuggingFaceChatClient._inner_get_response()
179
+ β†’ chat_options.tools contains AIFunction objects
180
+ ↓
181
+ huggingface_hub.InferenceClient.chat_completion(tools=tools)
182
+ ↓
183
+ requests.post(json={..., "tools": [AIFunction, ...]})
184
+ ↓
185
+ json.dumps() β†’ TypeError: Object of type AIFunction is not JSON serializable
186
+ ```
187
+
188
+ ## Testing
189
+
190
+ ```bash
191
+ # Reproduce locally (remove OpenAI key)
192
+ unset OPENAI_API_KEY
193
+ uv run python -c "
194
+ import asyncio
195
+ from src.orchestrators.advanced import AdvancedOrchestrator
196
+
197
+ async def test():
198
+ orch = AdvancedOrchestrator(max_rounds=2)
199
+ async for event in orch.run('testosterone benefits'):
200
+ print(f'[{event.type}] {event.message[:50]}...')
201
+
202
+ asyncio.run(test())
203
+ "
204
+
205
+ # Expected: TypeError: Object of type AIFunction is not JSON serializable
206
+ # After fix: Should complete without serialization errors
207
+ ```
208
+
209
+ ## References
210
+
211
+ - [Microsoft Agent Framework - AIFunction](https://learn.microsoft.com/en-us/python/api/agent-framework-core/agent_framework.aifunction)
212
+ - [HuggingFace Chat Completion API](https://huggingface.co/docs/api-inference/en/tasks/chat-completion)
213
+ - [Qwen Function Calling](https://qwen.readthedocs.io/en/latest/framework/function_call.html)
214
+ - [huggingface_hub chat_completion](https://github.com/huggingface/huggingface_hub/releases/tag/v0.22.0)