Skip to content

Commit a63e0cd

Browse files
gobrandoclaude
andcommitted
test: Temperature and reasoning level impact on web search usage
## Test 1: Temperature vs Web Search (50 API calls) **Configuration:** - Model: gpt-5.1 - Reasoning: none - Temperatures tested: 0.0, 0.25, 0.5, 0.75, 1.0 - Prompts per temperature: 10 - Total: 50 API calls **Key Findings:** - ❌ Temperature does NOT affect web search frequency - All temperatures showed 100% web search usage - Latency increases with temperature: - temp=0.0: 11.42s avg - temp=0.25: 13.98s avg - temp=0.5: 14.18s avg - temp=0.75: 15.08s avg - temp=1.0: 17.55s avg **Recommendation:** Keep current temperature=0.25 configuration --- ## Test 2: Reasoning Level vs Web Search (60 API calls) **Configuration:** - Model: gpt-5.1 - No temperature parameter - Reasoning levels tested: none vs low - Prompts: 30 - Total: 60 API calls (30 per reasoning level) **Key Findings:** - ❌ Reasoning level does NOT affect web search frequency - Both showed 100% web search usage - ⚠️ reasoning='low' has MASSIVE latency impact: - reasoning='none': 19.99s avg - reasoning='low': 182.50s avg (+812.9%) - ⚠️ reasoning='low' does NOT support temperature parameter **Recommendation:** Stay with reasoning='none' for production --- ## Overall Conclusions 1. **Web search frequency is not affected by:** - Temperature (0.0 to 1.0) - Reasoning level (none vs low) 2. **Production configuration is optimal:** - Model: gpt-5.1 - Reasoning: none - Temperature: 0.25 - Web search: enabled 3. **Performance benefits:** - reasoning='none' is 9.1x faster than reasoning='low' - Lower temperatures provide slightly faster responses - Current config balances speed and quality 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent e6c3780 commit a63e0cd

6 files changed

Lines changed: 15240 additions & 0 deletions
Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Compare reasoning="low" vs reasoning="none" WITHOUT temperature parameter.
4+
5+
Goal: Test if reasoning level affects:
6+
1. Web search usage frequency
7+
2. Response latency
8+
3. Output quality (resource count)
9+
10+
Configuration:
11+
- Model: gpt-5.1
12+
- NO temperature parameter
13+
- 30 diverse prompts
14+
- Compare reasoning="low" vs reasoning="none"
15+
"""
16+
17+
import os
18+
import json
19+
import time
20+
from openai import OpenAI
21+
from collections import defaultdict
22+
23+
# Check for API key
24+
if "OPENAI_API_KEY" not in os.environ:
25+
raise ValueError("OPENAI_API_KEY environment variable must be set")
26+
27+
# 30 diverse test prompts covering different scenarios
28+
TEST_PROMPTS = [
29+
# Housing & Homelessness (5 prompts)
30+
"Single mother with 2 kids facing eviction in Austin, needs emergency housing assistance",
31+
"Homeless veteran in Travis County needs transitional housing and job training",
32+
"Elderly couple on fixed income needs help with rising rent costs in Austin",
33+
"Family escaping domestic violence needs emergency shelter in Central Texas",
34+
"Young adult aging out of foster care needs affordable housing options in Austin",
35+
36+
# Food Assistance (5 prompts)
37+
"Low-income family with 4 children needs food assistance in Austin, TX",
38+
"Elderly person living alone needs home-delivered meals in Travis County",
39+
"College student struggling with food insecurity needs food pantry locations near UT Austin",
40+
"Undocumented immigrant family needs food assistance that doesn't require legal status",
41+
"Person with diabetes needs food assistance with dietary restrictions in Austin",
42+
43+
# Employment & Job Training (5 prompts)
44+
"Unemployed single parent needs job training and childcare assistance in Austin",
45+
"Ex-offender needs employment programs for people with criminal records in Travis County",
46+
"Person with disability needs supported employment services in Central Texas",
47+
"Recent immigrant needs ESL classes and job placement assistance in Austin",
48+
"Teenager needs summer job opportunities and youth employment programs",
49+
50+
# Healthcare & Mental Health (5 prompts)
51+
"Uninsured family needs low-cost healthcare clinic in Austin, TX",
52+
"Person experiencing depression needs free or sliding-scale mental health counseling",
53+
"Senior citizen needs help navigating Medicare and prescription drug costs",
54+
"Pregnant woman without insurance needs prenatal care in Travis County",
55+
"Person with substance abuse issues needs addiction treatment programs in Austin",
56+
57+
# Childcare & Education (5 prompts)
58+
"Working parent needs affordable childcare for toddler and preschooler in Austin",
59+
"Family needs after-school programs for elementary school children in East Austin",
60+
"Low-income family needs Head Start or Pre-K programs for 3-year-old",
61+
"Parent needs tutoring services for child struggling in school",
62+
"Family needs summer camp programs with financial assistance in Travis County",
63+
64+
# Benefits & Legal (5 prompts)
65+
"Person recently laid off needs help applying for unemployment benefits in Texas",
66+
"Immigrant family needs help applying for SNAP and Medicaid benefits",
67+
"Senior citizen needs help with Social Security disability application",
68+
"Person facing wage theft needs legal aid services in Austin",
69+
"Low-income family needs help with tax preparation and EITC",
70+
]
71+
72+
print("=" * 80)
73+
print("REASONING LEVEL COMPARISON (NO TEMPERATURE)")
74+
print("Testing: reasoning='low' vs reasoning='none'")
75+
print("=" * 80)
76+
print(f"Model: gpt-5.1")
77+
print(f"Temperature: NOT SET (testing pure reasoning effect)")
78+
print(f"Web Search: ENABLED")
79+
print(f"Test prompts: {len(TEST_PROMPTS)}")
80+
print("=" * 80)
81+
82+
client = OpenAI()
83+
84+
def run_test(prompt_text: str, reasoning_effort: str, prompt_num: int) -> dict:
85+
"""Run a single test with the given reasoning effort level."""
86+
87+
# Format the prompt as the app would
88+
formatted_prompt = f"""You are a case worker assistant in Central Texas. Recommend 5-7 relevant social support resources.
89+
90+
Client: {prompt_text}
91+
92+
Return ONLY valid JSON in this exact format:
93+
{{
94+
"resources": [
95+
{{
96+
"name": "Organization Name",
97+
"description": "Brief description",
98+
"website": "URL",
99+
"phones": ["phone number"],
100+
"emails": ["email"],
101+
"addresses": ["address"]
102+
}}
103+
]
104+
}}"""
105+
106+
print(f"\n{'='*80}")
107+
print(f"Prompt {prompt_num}/30: {prompt_text[:80]}...")
108+
print(f"Reasoning: {reasoning_effort}")
109+
print(f"{'='*80}")
110+
111+
try:
112+
start_time = time.time()
113+
114+
# NO TEMPERATURE PARAMETER - Testing pure reasoning effect
115+
api_params = {
116+
"model": "gpt-5.1",
117+
"input": formatted_prompt,
118+
"reasoning": {"effort": reasoning_effort},
119+
"tools": [{"type": "web_search"}]
120+
}
121+
122+
response = client.responses.create(**api_params)
123+
elapsed = time.time() - start_time
124+
125+
# Parse response
126+
response_text = response.output_text
127+
128+
# Extract JSON
129+
start = response_text.find("{")
130+
end = response_text.rfind("}")
131+
if start != -1 and end != -1:
132+
json_str = response_text[start:end + 1]
133+
result_json = json.loads(json_str)
134+
resource_count = len(result_json.get("resources", []))
135+
resource_names = [r.get("name", "Unknown") for r in result_json.get("resources", [])]
136+
else:
137+
resource_count = 0
138+
resource_names = []
139+
result_json = None
140+
141+
# Check for web search indicators in response
142+
web_search_indicators = [
143+
"according to",
144+
"based on",
145+
"website",
146+
"online",
147+
".org",
148+
".gov",
149+
".com",
150+
"http",
151+
]
152+
153+
response_lower = response_text.lower()
154+
indicators_found = [ind for ind in web_search_indicators if ind in response_lower]
155+
likely_used_web_search = len(indicators_found) >= 2
156+
157+
# Count URLs
158+
url_count = response_text.count("http") + response_text.count(".org") + response_text.count(".gov")
159+
160+
result = {
161+
"success": True,
162+
"reasoning_effort": reasoning_effort,
163+
"response_time": round(elapsed, 2),
164+
"resource_count": resource_count,
165+
"resource_names": resource_names,
166+
"output_text": response_text,
167+
"output_json": result_json,
168+
"likely_used_web_search": likely_used_web_search,
169+
"url_count": url_count,
170+
"indicators_found": indicators_found,
171+
"error": None
172+
}
173+
174+
print(f"✅ SUCCESS!")
175+
print(f"⏱️ Response time: {elapsed:.2f}s")
176+
print(f"📊 Resources found: {resource_count}")
177+
print(f"🔍 Likely used web search: {'YES' if likely_used_web_search else 'NO'}")
178+
print(f"🔗 URL indicators: {url_count}")
179+
if resource_names:
180+
print(f"📝 Resources: {', '.join(resource_names[:3])}{'...' if len(resource_names) > 3 else ''}")
181+
182+
return result
183+
184+
except Exception as e:
185+
error_msg = str(e)
186+
print(f"❌ ERROR: {error_msg[:150]}")
187+
188+
return {
189+
"success": False,
190+
"reasoning_effort": reasoning_effort,
191+
"response_time": 0,
192+
"resource_count": 0,
193+
"resource_names": [],
194+
"output_text": None,
195+
"output_json": None,
196+
"likely_used_web_search": False,
197+
"url_count": 0,
198+
"indicators_found": [],
199+
"error": error_msg
200+
}
201+
202+
# Store all results
203+
all_results = []
204+
205+
# Test each prompt with both reasoning levels
206+
for i, prompt in enumerate(TEST_PROMPTS, 1):
207+
prompt_results = {
208+
"prompt_number": i,
209+
"prompt": prompt,
210+
"reasoning_none": None,
211+
"reasoning_low": None
212+
}
213+
214+
# Test with reasoning="none" (current production config)
215+
prompt_results["reasoning_none"] = run_test(prompt, "none", i)
216+
217+
# Small delay to avoid rate limits
218+
time.sleep(1)
219+
220+
# Test with reasoning="low"
221+
prompt_results["reasoning_low"] = run_test(prompt, "low", i)
222+
223+
# Small delay between prompts
224+
time.sleep(1)
225+
226+
all_results.append(prompt_results)
227+
228+
print("\n" + "=" * 80)
229+
print("ANALYSIS: Reasoning Level Comparison")
230+
print("=" * 80)
231+
232+
# Aggregate statistics
233+
stats = {
234+
"none": {
235+
"total_tests": 0,
236+
"successful_tests": 0,
237+
"total_latency": 0,
238+
"avg_latency": 0,
239+
"total_resources": 0,
240+
"avg_resources": 0,
241+
"web_search_count": 0,
242+
"web_search_rate": 0,
243+
"total_url_indicators": 0,
244+
"avg_url_indicators": 0
245+
},
246+
"low": {
247+
"total_tests": 0,
248+
"successful_tests": 0,
249+
"total_latency": 0,
250+
"avg_latency": 0,
251+
"total_resources": 0,
252+
"avg_resources": 0,
253+
"web_search_count": 0,
254+
"web_search_rate": 0,
255+
"total_url_indicators": 0,
256+
"avg_url_indicators": 0
257+
}
258+
}
259+
260+
for result in all_results:
261+
for reasoning_level in ["none", "low"]:
262+
test_result = result[f"reasoning_{reasoning_level}"]
263+
stats[reasoning_level]["total_tests"] += 1
264+
265+
if test_result["success"]:
266+
stats[reasoning_level]["successful_tests"] += 1
267+
stats[reasoning_level]["total_latency"] += test_result["response_time"]
268+
stats[reasoning_level]["total_resources"] += test_result["resource_count"]
269+
stats[reasoning_level]["total_url_indicators"] += test_result["url_count"]
270+
271+
if test_result["likely_used_web_search"]:
272+
stats[reasoning_level]["web_search_count"] += 1
273+
274+
# Calculate averages
275+
for reasoning_level in ["none", "low"]:
276+
successful = stats[reasoning_level]["successful_tests"]
277+
if successful > 0:
278+
stats[reasoning_level]["avg_latency"] = stats[reasoning_level]["total_latency"] / successful
279+
stats[reasoning_level]["avg_resources"] = stats[reasoning_level]["total_resources"] / successful
280+
stats[reasoning_level]["avg_url_indicators"] = stats[reasoning_level]["total_url_indicators"] / successful
281+
stats[reasoning_level]["web_search_rate"] = (stats[reasoning_level]["web_search_count"] / successful) * 100
282+
283+
print("\n📊 REASONING='NONE' (Current Production):")
284+
print(f" Success rate: {stats['none']['successful_tests']}/{stats['none']['total_tests']} ({stats['none']['successful_tests']/stats['none']['total_tests']*100:.1f}%)")
285+
print(f" Avg latency: {stats['none']['avg_latency']:.2f}s")
286+
print(f" Avg resources per query: {stats['none']['avg_resources']:.1f}")
287+
print(f" Web search usage: {stats['none']['web_search_count']}/{stats['none']['successful_tests']} ({stats['none']['web_search_rate']:.1f}%)")
288+
print(f" Avg URL indicators: {stats['none']['avg_url_indicators']:.1f}")
289+
290+
print("\n📊 REASONING='LOW':")
291+
print(f" Success rate: {stats['low']['successful_tests']}/{stats['low']['total_tests']} ({stats['low']['successful_tests']/stats['low']['total_tests']*100:.1f}%)")
292+
print(f" Avg latency: {stats['low']['avg_latency']:.2f}s")
293+
print(f" Avg resources per query: {stats['low']['avg_resources']:.1f}")
294+
print(f" Web search usage: {stats['low']['web_search_count']}/{stats['low']['successful_tests']} ({stats['low']['web_search_rate']:.1f}%)")
295+
print(f" Avg URL indicators: {stats['low']['avg_url_indicators']:.1f}")
296+
297+
print("\n🔍 COMPARISON:")
298+
if stats['none']['successful_tests'] > 0 and stats['low']['successful_tests'] > 0:
299+
latency_diff = stats['low']['avg_latency'] - stats['none']['avg_latency']
300+
latency_pct = (latency_diff / stats['none']['avg_latency'] * 100) if stats['none']['avg_latency'] > 0 else 0
301+
print(f" Latency impact: {latency_diff:+.2f}s ({latency_pct:+.1f}%)")
302+
303+
web_search_diff = stats['low']['web_search_rate'] - stats['none']['web_search_rate']
304+
print(f" Web search usage difference: {web_search_diff:+.1f}pp")
305+
print(f" reasoning='none': {stats['none']['web_search_rate']:.1f}%")
306+
print(f" reasoning='low': {stats['low']['web_search_rate']:.1f}%")
307+
308+
resource_diff = stats['low']['avg_resources'] - stats['none']['avg_resources']
309+
print(f" Avg resources difference: {resource_diff:+.1f}")
310+
311+
url_diff = stats['low']['avg_url_indicators'] - stats['none']['avg_url_indicators']
312+
print(f" Avg URL indicators difference: {url_diff:+.1f}")
313+
314+
print("\n" + "=" * 80)
315+
print("KEY FINDINGS:")
316+
print("=" * 80)
317+
318+
if stats['none']['successful_tests'] > 0 and stats['low']['successful_tests'] > 0:
319+
if web_search_diff > 20:
320+
print("✅ reasoning='low' SIGNIFICANTLY increases web search usage")
321+
print(f" +{web_search_diff:.1f}pp more web searches detected")
322+
elif web_search_diff > 10:
323+
print("⚠️ reasoning='low' moderately increases web search usage")
324+
print(f" +{web_search_diff:.1f}pp more web searches detected")
325+
elif web_search_diff < -10:
326+
print("❌ reasoning='low' DECREASES web search usage")
327+
print(f" {web_search_diff:.1f}pp fewer web searches detected")
328+
else:
329+
print("❌ reasoning='low' does NOT significantly affect web search usage")
330+
print(f" Only {abs(web_search_diff):.1f}pp difference")
331+
332+
if latency_pct > 50:
333+
print(f"\n⚠️ WARNING: reasoning='low' has MAJOR latency impact (+{latency_pct:.1f}%)")
334+
elif latency_pct > 20:
335+
print(f"\n⚠️ reasoning='low' has moderate latency impact (+{latency_pct:.1f}%)")
336+
else:
337+
print(f"\n✅ reasoning='low' has minimal latency impact ({latency_pct:+.1f}%)")
338+
else:
339+
print("⚠️ Unable to compare - one or both reasoning levels failed")
340+
341+
print("\n" + "=" * 80)
342+
print("RECOMMENDATIONS:")
343+
print("=" * 80)
344+
345+
if stats['none']['successful_tests'] > 0 and stats['low']['successful_tests'] > 0:
346+
if web_search_diff > 10 and latency_pct < 50:
347+
print("✅ RECOMMENDATION: Switch to reasoning='low'")
348+
print(" - More web search usage")
349+
print(" - Acceptable latency impact")
350+
print(" ⚠️ BUT: Cannot use temperature parameter with reasoning='low'")
351+
elif web_search_diff > 10:
352+
print("⚠️ RECOMMENDATION: Consider reasoning='low' if web search is critical")
353+
print(f" - +{web_search_diff:.1f}pp more web search usage")
354+
print(f" - BUT: +{latency_pct:.1f}% latency penalty")
355+
print(" ⚠️ AND: Cannot use temperature parameter")
356+
else:
357+
print("✅ RECOMMENDATION: Stay with reasoning='none'")
358+
print(" - No significant web search improvement with reasoning='low'")
359+
print(" - Supports temperature parameter for consistency")
360+
else:
361+
print("⚠️ Cannot provide recommendation - check error details")
362+
363+
print("\n" + "=" * 80)
364+
print("IMPORTANT NOTES")
365+
print("=" * 80)
366+
print("⚠️ This test uses HEURISTICS to detect web search usage.")
367+
print(" For ACCURATE counts, check trace spans in your observability platform:")
368+
print(" - 'OpenAIWebSearch' component spans")
369+
print(" - 'web_search_...' child spans")
370+
print(" - 'websearch' tokens in payloads")
371+
print("\n⚠️ CRITICAL: reasoning='low' does NOT support temperature parameter!")
372+
print(" If you need temperature control, you MUST use reasoning='none'")
373+
print("=" * 80)
374+
375+
# Save detailed results
376+
output_file = "reasoning_comparison_no_temp_results.json"
377+
with open(output_file, "w") as f:
378+
json.dump({
379+
"metadata": {
380+
"model": "gpt-5.1",
381+
"temperature": None,
382+
"total_prompts": len(TEST_PROMPTS),
383+
"reasoning_levels": ["none", "low"]
384+
},
385+
"statistics": stats,
386+
"detailed_results": all_results
387+
}, f, indent=2)
388+
389+
print(f"\n💾 Detailed results saved to: {output_file}")

0 commit comments

Comments
 (0)