Skip to content

Commit e4e9145

Browse files
author
Pierre
authored
Merge pull request #48 from WorkflowAI/pierre-clean-docstring
clean_docstring
2 parents fd1a19c + 7db7cf4 commit e4e9145

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-2
lines changed

workflowai/core/client/_fn_utils.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,28 @@ async def __call__(self, input: AgentInput, **kwargs: Unpack[RunParams[AgentOutp
147147
yield chunk.output
148148

149149

150+
def clean_docstring(docstring: Optional[str]) -> str:
151+
"""Clean a docstring by removing empty lines at start/end and normalizing indentation."""
152+
if not docstring:
153+
return ""
154+
155+
# Split into lines and remove empty lines at start/end
156+
lines = [line.rstrip() for line in docstring.split("\n")]
157+
while lines and not lines[0].strip():
158+
lines.pop(0)
159+
while lines and not lines[-1].strip():
160+
lines.pop()
161+
162+
if not lines:
163+
return ""
164+
165+
# Find and remove common indentation
166+
indent = min(len(line) - len(line.lstrip()) for line in lines if line.strip())
167+
lines = [line[indent:] if line.strip() else "" for line in lines]
168+
169+
return "\n".join(lines)
170+
171+
150172
def wrap_run_template(
151173
client: Callable[[], APIClient],
152174
agent_id: str,
@@ -165,7 +187,7 @@ def wrap_run_template(
165187

166188
if not version and (fn.__doc__ or model):
167189
version = VersionProperties(
168-
instructions=fn.__doc__,
190+
instructions=clean_docstring(fn.__doc__),
169191
model=model,
170192
)
171193

workflowai/core/client/_fn_utils_test.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import AsyncIterator
1+
from typing import AsyncIterator, Union
22
from unittest.mock import Mock
33

44
import pytest
@@ -13,6 +13,7 @@
1313
_RunnableStreamAgent, # pyright: ignore [reportPrivateUsage]
1414
_RunnableStreamOutputOnlyAgent, # pyright: ignore [reportPrivateUsage]
1515
agent_wrapper,
16+
clean_docstring,
1617
extract_fn_spec,
1718
get_generic_args,
1819
is_async_iterator,
@@ -113,3 +114,62 @@ async def test_fn_stream_output_only(self, mock_api_client: Mock):
113114
assert len(chunks) == 1
114115
assert isinstance(chunks[0], HelloTaskOutput)
115116
assert chunks[0] == HelloTaskOutput(message="Hello, World!")
117+
118+
119+
@pytest.mark.parametrize(
120+
("value", "expected"),
121+
[
122+
# Empty docstrings
123+
("", ""),
124+
(None, ""),
125+
126+
# Single line docstrings
127+
("Hello world", "Hello world"),
128+
(" Hello world ", "Hello world"),
129+
130+
# Docstring with empty lines at start/end
131+
("""
132+
133+
Hello world
134+
135+
""", "Hello world"),
136+
137+
# Multi-line docstring with indentation
138+
("""
139+
First line
140+
Second line
141+
Indented line
142+
Last line
143+
""", "First line\nSecond line\n Indented line\nLast line"),
144+
145+
# Docstring with empty lines in between
146+
("""
147+
First line
148+
149+
Second line
150+
151+
Third line
152+
""", "First line\n\nSecond line\n\nThird line"),
153+
154+
# Real-world example
155+
("""
156+
Find the capital city of the country where the input city is located.
157+
158+
Guidelines:
159+
1. First identify the country where the input city is located
160+
2. Then provide the capital city of that country
161+
3. Include an interesting historical or cultural fact about the capital
162+
4. Be accurate and precise with geographical information
163+
5. If the input city is itself the capital, still provide the information
164+
""",
165+
"Find the capital city of the country where the input city is located.\n\n"
166+
"Guidelines:\n"
167+
"1. First identify the country where the input city is located\n"
168+
"2. Then provide the capital city of that country\n"
169+
"3. Include an interesting historical or cultural fact about the capital\n"
170+
"4. Be accurate and precise with geographical information\n"
171+
"5. If the input city is itself the capital, still provide the information"),
172+
],
173+
)
174+
def test_clean_docstring(value: Union[str, None], expected: str):
175+
assert clean_docstring(value) == expected

0 commit comments

Comments
 (0)