Skip to content

Commit e5968f1

Browse files
authored
Merge pull request #49 from WorkflowAI/pierre-example-instruction-variables
Create 14_templated_instructions.py
2 parents 48ecb43 + ee673ac commit e5968f1

File tree

2 files changed

+238
-0
lines changed

2 files changed

+238
-0
lines changed

README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,64 @@ async def analyze_call_feedback(input: CallFeedbackInput) -> CallFeedbackOutput:
198198
> a newer version of the same model with the same or a lower price so calling the api with
199199
> a retired model will always work.
200200
201+
### Using templated instructions
202+
203+
You can use [Jinja2](https://jinja.palletsprojects.com/)-style templating in your agent's instructions (docstring) to make them dynamic based on input values. The template variables are automatically populated from the fields in your input model.
204+
205+
```python
206+
class CodeReviewInput(BaseModel):
207+
language: str = Field(description="Programming language of the code")
208+
style_guide: str = Field(description="Style guide to follow")
209+
is_production: bool = Field(description="Whether this is a production review")
210+
focus_areas: list[str] = Field(description="Areas to focus on during review", default_factory=list)
211+
212+
class CodeReviewOutput(BaseModel):
213+
"""Output from a code review."""
214+
issues: list[str] = Field(
215+
default_factory=list,
216+
description="List of identified issues or suggestions for improvement"
217+
)
218+
compliments: list[str] = Field(
219+
default_factory=list,
220+
description="List of positive aspects and good practices found in the code"
221+
)
222+
summary: str = Field(
223+
description="A brief summary of the code review findings"
224+
)
225+
226+
@workflowai.agent(id="code-review")
227+
async def review_code(review_input: CodeReviewInput) -> CodeReviewOutput:
228+
"""
229+
You are a code reviewer for {{ language }} code.
230+
Please review according to the {{ style_guide }} style guide.
231+
232+
{% if is_production %}
233+
This is a PRODUCTION review - be extra thorough and strict.
234+
{% else %}
235+
This is a development review - focus on maintainability.
236+
{% endif %}
237+
238+
{% if focus_areas %}
239+
Key areas to focus on:
240+
{% for area in focus_areas %}
241+
{{ loop.index }}. {{ area }}
242+
{% endfor %}
243+
{% endif %}
244+
"""
245+
...
246+
```
247+
248+
The template uses [Jinja2](https://jinja.palletsprojects.com/) syntax and supports common templating features including:
249+
250+
- Variable substitution: `{{ variable }}`
251+
- Conditionals: `{% if condition %}...{% endif %}`
252+
- Loops: `{% for item in items %}...{% endfor %}`
253+
- Loop indices: `{{ loop.index }}`
254+
255+
See the [Jinja2 documentation](https://jinja.palletsprojects.com/) for the full template syntax and capabilities.
256+
257+
We recommend using ChatGPT or CursorAI to help generate the template.
258+
201259
### Version from code or deployments
202260

203261
Setting a docstring or a model in the agent decorator signals the client that the agent parameters are
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
"""
2+
This example demonstrates how to use templated instructions that adapt based on input variables.
3+
The template variables are automatically populated from the input model's fields.
4+
5+
The templating uses Jinja2 syntax (server-side rendering):
6+
- {{ variable }} for variable substitution
7+
- {% if condition %} ... {% endif %} for conditionals
8+
- {% for item in items %} ... {% endfor %} for loops
9+
- {{ loop.index }} for loop indices
10+
11+
For full Jinja2 template syntax documentation, see:
12+
https://jinja.palletsprojects.com/en/stable/
13+
14+
It showcases:
15+
1. Simple variable substitution
16+
2. Conditional logic
17+
3. Loops
18+
4. Nested conditionals
19+
"""
20+
21+
import asyncio
22+
23+
from pydantic import BaseModel, Field
24+
25+
import workflowai
26+
from workflowai import Model, Run
27+
28+
29+
class CodeReviewInput(BaseModel):
30+
"""Input model for the code review agent."""
31+
32+
language: str = Field(
33+
description="The programming language of the code to review",
34+
examples=["python", "javascript", "typescript"],
35+
)
36+
code: str = Field(
37+
description="The code to review",
38+
)
39+
style_guide: str = Field(
40+
description="The style guide to follow",
41+
examples=["PEP 8", "Google Style", "Airbnb"],
42+
)
43+
is_production: bool = Field(
44+
description="Whether this is a production code review",
45+
default=False,
46+
)
47+
required_checks: list[str] = Field(
48+
description="List of specific checks to perform",
49+
default=["code style", "performance", "maintainability"],
50+
)
51+
security_level: str = Field(
52+
description="Required security level",
53+
default="standard",
54+
examples=["standard", "high"],
55+
)
56+
57+
58+
class CodeReviewOutput(BaseModel):
59+
"""Output model containing the code review results."""
60+
61+
overall_assessment: str = Field(
62+
description="Overall assessment of the code quality",
63+
)
64+
style_violations: list[str] = Field(
65+
description="List of style guide violations",
66+
)
67+
security_issues: list[str] = Field(
68+
description="List of security concerns",
69+
default_factory=list,
70+
)
71+
suggested_improvements: list[str] = Field(
72+
description="List of suggested improvements",
73+
)
74+
75+
76+
@workflowai.agent(
77+
id="templated-code-reviewer",
78+
model=Model.CLAUDE_3_5_SONNET_LATEST,
79+
)
80+
async def review_code(review_input: CodeReviewInput) -> Run[CodeReviewOutput]:
81+
"""
82+
Review code based on specified parameters and guidelines.
83+
84+
You are a code reviewer for {{ language }} code.
85+
Please review the code according to the {{ style_guide }} style guide.
86+
87+
{% if is_production %}
88+
This is a PRODUCTION code review - please be extra thorough and strict about best practices.
89+
{% else %}
90+
This is a development code review - focus on maintainability and clarity.
91+
{% endif %}
92+
93+
Required checks to perform:
94+
{% for check in required_checks %}{{ loop.index }}. {{ check }}
95+
{% endfor %}
96+
97+
{% if security_level == "high" %}
98+
Additional security requirements:
99+
- Must follow secure coding practices
100+
- Check for potential security vulnerabilities
101+
- Ensure all inputs are properly sanitized
102+
{% endif %}
103+
104+
Guidelines:
105+
1. Check for adherence to {{ style_guide }} conventions
106+
2. Look for potential bugs and performance issues
107+
3. Suggest improvements while keeping the {{ language }} best practices in mind
108+
109+
{% if language == "python" %}
110+
Python-specific checks:
111+
- Type hints usage
112+
- PEP 8 compliance
113+
- Docstring format
114+
{% elif language == "javascript" or language == "typescript" %}
115+
JavaScript/TypeScript-specific checks:
116+
- ESLint rules compliance
117+
- Modern ES6+ features usage
118+
- Browser compatibility
119+
{% endif %}
120+
121+
Please analyze the following code and provide:
122+
1. An overall assessment
123+
2. Style guide violations
124+
3. Security issues (if any)
125+
4. Suggested improvements
126+
127+
The code is:
128+
{{ code }}
129+
"""
130+
...
131+
132+
133+
async def main():
134+
# Example 1: Python code review for development
135+
print("\nExample 1: Python Development Code Review")
136+
print("-" * 50)
137+
python_code = """
138+
def calculate_sum(numbers):
139+
result = 0
140+
for n in numbers:
141+
result = result + n
142+
return result
143+
"""
144+
145+
run = await review_code(
146+
CodeReviewInput(
147+
language="python",
148+
code=python_code,
149+
style_guide="PEP 8",
150+
required_checks=["type hints", "docstring", "performance"],
151+
),
152+
)
153+
print(run)
154+
155+
# Example 2: TypeScript production code with high security
156+
print("\nExample 2: TypeScript Production Code Review (High Security)")
157+
print("-" * 50)
158+
typescript_code = """
159+
function processUserData(data: any) {
160+
const userId = data.id;
161+
const query = `SELECT * FROM users WHERE id = ${userId}`;
162+
return executeQuery(query);
163+
}
164+
"""
165+
166+
run = await review_code(
167+
CodeReviewInput(
168+
language="typescript",
169+
code=typescript_code,
170+
style_guide="Airbnb",
171+
is_production=True,
172+
security_level="high",
173+
required_checks=["security", "type safety", "SQL injection"],
174+
),
175+
)
176+
print(run)
177+
178+
179+
if __name__ == "__main__":
180+
asyncio.run(main())

0 commit comments

Comments
 (0)