Skip to content

Commit f4ab6ba

Browse files
committed
great
1 parent e975168 commit f4ab6ba

File tree

2 files changed

+58
-16
lines changed

2 files changed

+58
-16
lines changed

smartfunc/__init__.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import datetime
12
from functools import wraps
23
import inspect
34
from typing import Callable, get_type_hints, Any, Optional, Type
@@ -66,6 +67,19 @@ def _process_response(response_text: str, return_type: Optional[Type[BaseModel]]
6667
return json.loads(response_text)
6768
return response_text
6869

70+
def _prepare_debug_info(backend, func: Callable, all_kwargs: dict, formatted_docstring: str, return_type: Optional[Type[BaseModel]] = None) -> dict:
71+
if return_type:
72+
return_type = return_type.model_json_schema()
73+
return {
74+
"template": func.__doc__,
75+
"func_name": func.__name__,
76+
"prompt": formatted_docstring,
77+
"system": backend.system,
78+
"template_inputs": all_kwargs,
79+
"backend_kwargs": backend.kwargs,
80+
"datetime": datetime.datetime.now().isoformat(),
81+
"return_type": return_type,
82+
}
6983

7084
class backend:
7185
"""Synchronous backend decorator for LLM-powered functions.
@@ -109,18 +123,14 @@ def wrapper(*args, **kwargs):
109123
formatted_docstring,
110124
system=self.system,
111125
schema=return_type,
112-
**kwargs
126+
**self.kwargs
113127
)
114128
out = _process_response(resp.text(), return_type)
115129

116130
if self.debug:
117131
if isinstance(out, str):
118132
out = {"result": out}
119-
out["_debug"] = {
120-
"prompt": formatted_docstring,
121-
"system": self.system,
122-
"kwargs": all_kwargs,
123-
}
133+
out["_debug"] = _prepare_debug_info(self, func, all_kwargs, formatted_docstring, return_type)
124134

125135
return out
126136

@@ -167,23 +177,21 @@ def __init__(self, name, system=None, debug=False, **kwargs):
167177
def __call__(self, func: Callable) -> Callable:
168178
@wraps(func)
169179
async def wrapper(*args, **kwargs):
170-
formatted_docstring, _, return_type = _prepare_function_call(func, args, kwargs)
180+
formatted_docstring, all_kwargs, return_type = _prepare_function_call(func, args, kwargs)
171181

172182
resp = await self.model.prompt(
173183
formatted_docstring,
174184
system=self.system,
175185
schema=return_type,
176-
**kwargs
186+
**self.kwargs
177187
)
178188
text = await resp.text()
179189
out = _process_response(text, return_type)
180190

181191
if self.debug:
182-
out["_debug"] = {
183-
"prompt": formatted_docstring,
184-
"system": self.system,
185-
"kwargs": kwargs,
186-
}
192+
if isinstance(out, str):
193+
out = {"result": out}
194+
out["_debug"] = _prepare_debug_info(self, func, all_kwargs, formatted_docstring, return_type)
187195

188196
return out
189197

tests/test_basic.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def generate_summary(t):
4040

4141
assert isinstance(result, dict)
4242
assert result["_debug"]["prompt"] == "Generate a summary of the following text: Hello, world!"
43-
assert result["_debug"]["kwargs"] == {"t": "Hello, world!"}
43+
assert result["_debug"]["template_inputs"] == {"t": "Hello, world!"}
4444
assert result["_debug"]["system"] == "You are a helpful assistant."
4545
assert result["result"]
4646

@@ -56,7 +56,41 @@ def generate_summary(a, b, c):
5656

5757
assert isinstance(result, dict)
5858
assert result["_debug"]["prompt"] == "Generate a summary of the following text: Hello world !"
59-
assert result["_debug"]["kwargs"] == {"a": "Hello", "b": "world", "c": "!"}
59+
assert result["_debug"]["template_inputs"] == {"a": "Hello", "b": "world", "c": "!"}
6060
assert result["_debug"]["system"] == "You are a helpful assistant."
6161
assert result["result"]
62-
62+
63+
64+
def test_debug_info_keys():
65+
"""Test that all expected debug info keys are present with correct types"""
66+
@backend("markov", debug=True, system="You are a helpful assistant.")
67+
def generate_summary(text):
68+
"""Generate a summary of the following text: {{ text }}"""
69+
pass
70+
71+
result = generate_summary("Hello, world!")
72+
debug_info = result["_debug"]
73+
74+
# Check all expected keys are present
75+
expected_keys = {
76+
"template": str, # Original docstring template
77+
"func_name": str, # Name of the function
78+
"prompt": str, # Rendered prompt
79+
"system": str, # System prompt
80+
"template_inputs": dict, # Arguments used in template
81+
"backend_kwargs": dict, # Backend configuration
82+
"datetime": str, # ISO format datetime
83+
"return_type": type(None) # None since no return type specified
84+
}
85+
86+
for key, expected_type in expected_keys.items():
87+
assert key in debug_info, f"Missing debug key: {key}"
88+
assert isinstance(debug_info[key], expected_type), f"Incorrect type for {key}: expected {expected_type}, got {type(debug_info[key])}"
89+
90+
# Check specific values
91+
assert debug_info["template"] == "Generate a summary of the following text: {{ text }}"
92+
assert debug_info["func_name"] == "generate_summary"
93+
assert debug_info["prompt"] == "Generate a summary of the following text: Hello, world!"
94+
assert debug_info["system"] == "You are a helpful assistant."
95+
assert debug_info["template_inputs"] == {"text": "Hello, world!"}
96+
assert debug_info["return_type"] is None

0 commit comments

Comments
 (0)