Skip to content

Commit 9b83aab

Browse files
authored
Merge branch 'main' into model-params
2 parents 9acdf43 + e0c1af0 commit 9b83aab

File tree

5 files changed

+166
-71
lines changed

5 files changed

+166
-71
lines changed

cookbook/flows/label_issues.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import marvin
2+
from gh_util.functions import add_labels_to_issue, fetch_repo_labels
3+
from gh_util.types import GitHubIssueEvent
4+
from prefect import flow, task
5+
6+
7+
@flow(log_prints=True)
8+
async def label_issues(
9+
event_body_str: str,
10+
): # want to do {{ event.payload.body | from_json }} but not supported
11+
"""Label issues based on their action"""
12+
issue_event = GitHubIssueEvent.model_validate_json(event_body_str)
13+
print(
14+
f"Issue '#{issue_event.issue.number} - {issue_event.issue.title}' was {issue_event.action}"
15+
)
16+
17+
issue_body = issue_event.issue.body
18+
19+
owner, repo = issue_event.repository.owner.login, issue_event.repository.name
20+
21+
repo_labels = await task(fetch_repo_labels)(owner, repo)
22+
23+
label = task(marvin.classify)(
24+
issue_body, labels=[label.name for label in repo_labels]
25+
)
26+
27+
await task(add_labels_to_issue)(owner, repo, issue_event.issue.number, {label})
28+
29+
print(f"Labeled issue with '{label}'")

docs/docs/interactive/assistants.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,11 @@ Each assistant can be given a list of `tools` that it can use when responding to
7474

7575
OpenAI provides a small number of built-in tools for assistants. The most useful is the "code interpreter", which lets the assistant write and execute Python code. To use the code interpreter, add it to your assistant's list of tools.
7676

77-
!!! example "Using the code interpreter"
7877

7978
This assistant uses the code interpreter to generate a plot of sin(x). Note that Marvin's utility for pretty-printing messages to the terminal can't show the plot inline, but will download it and show a link to the file instead.
8079

80+
!!! example "Using assistants with the code interpreter"
81+
8182
```python
8283
from marvin.beta import Assistant
8384
from marvin.beta.assistants import pprint_messages, CodeInterpreter

docs/docs/text/functions.md

+111-66
Original file line numberDiff line numberDiff line change
@@ -87,82 +87,127 @@ When this function is called with `n=3`, the LLM will see the string ``"... of 3
8787
### Parameters
8888

8989
The function's parameters, in conjunction with the docstring, provide the LLM with runtime context. The LLM will see the parameter names, types, defaults, and runtime values, and use this information to generate the output. Parameters are important for collecting information, but because the information is ultimately going to an LLM, they can be named anything and take any value that is conducive to generating the right output.
90-
or example, if you have a function that returns a list of recipes, you might define it like this:
9190

92-
```python
93-
@marvin.fn
94-
def recipe(
95-
ingredients: list[str],
96-
max_cook_time: int = 15,
97-
cuisine: str = "North Italy",
98-
experience_level="beginner"
99-
) -> str:
100-
"""
101-
Returns a complete recipe that uses all the `ingredients` and
102-
takes less than `max_cook_time` minutes to prepare. Takes
103-
`cuisine` style and the chef's `experience_level` into account
104-
as well. Recipes have a name, list of ingredients, and steps to follow.
105-
"""
106-
```
107-
108-
Now we can call this function in ways that would be impossible to code in Python:
109-
110-
=== "Novice chef"
91+
For example, if you have a function that returns a list of recipes, you might define it like this:
11192

93+
!!! example "Generating recipes"
11294
```python
113-
recipe(
114-
["chicken", "potatoes"],
115-
experience_level='can barely boil water'
116-
)
117-
```
95+
import marvin
96+
from pydantic import BaseModel
11897

11998

120-
!!! success "Result"
121-
Recipe for Simple North Italian Chicken and Potatoes
122-
123-
Ingredients:
124-
125-
- Chicken
126-
- Potatoes
127-
128-
Instructions:
129-
130-
1. Wash the potatoes and cut them into quarters.
131-
2. Place potatoes in a microwave-safe dish, cover with water, and microwave for 10 minutes until soft.
132-
...
133-
99+
class Recipe(BaseModel):
100+
name: str
101+
cook_time_minutes: int
102+
ingredients: list[str]
103+
steps: list[str]
134104

135-
=== "Expert chef"
136105

137-
```python
138-
recipe(
139-
["chicken", "potatoes"],
140-
max_cook_time=60,
141-
experience_level='born wearing a toque'
142-
)
106+
@marvin.fn
107+
def recipe(
108+
ingredients: list[str],
109+
max_cook_time: int = 15,
110+
cuisine: str = "North Italy",
111+
experience_level:str = "beginner"
112+
) -> Recipe:
113+
"""
114+
Returns a complete recipe that uses all the `ingredients` and
115+
takes less than `max_cook_time` minutes to prepare. Takes
116+
`cuisine` style and the chef's `experience_level` into account
117+
as well.
118+
"""
143119
```
144120

121+
!!! success "Results"
122+
=== "Novice chef"
123+
124+
Call the function:
125+
```python
126+
result = recipe(
127+
["chicken", "potatoes"],
128+
experience_level="can barely boil water",
129+
)
130+
```
131+
132+
View the result:
133+
134+
```python
135+
Recipe(
136+
name="Simple Chicken and Potatoes",
137+
cook_time_minutes=15,
138+
ingredients=["chicken", "potatoes"],
139+
steps=[
140+
"Wash the potatoes and cut them into small cubes.",
141+
(
142+
"Heat oil in a pan and cook the chicken over medium heat "
143+
"until browned."
144+
),
145+
"Add the cubed potatoes to the pan with the chicken.",
146+
(
147+
"Stir everything together and cook for 10 minutes or until "
148+
"the potatoes are tender and the chicken is cooked "
149+
"through."
150+
),
151+
"Serve hot.",
152+
],
153+
)
154+
```
155+
156+
157+
=== "Expert chef"
158+
159+
Call the function:
160+
```python
161+
result = recipe(
162+
["chicken", "potatoes"],
163+
experience_level="born wearing a toque",
164+
max_cook_time=60,
165+
)
166+
```
167+
168+
View the result:
169+
170+
```python
171+
Recipe(
172+
name="Chicken and Potato Tray Bake",
173+
cook_time_minutes=45,
174+
ingredients=[
175+
"chicken",
176+
"potatoes",
177+
"olive oil",
178+
"rosemary",
179+
"garlic",
180+
"salt",
181+
"black pepper",
182+
],
183+
steps=[
184+
(
185+
"Preheat your oven to 200 degrees Celsius (400 degrees "
186+
"Fahrenheit)."
187+
),
188+
(
189+
"Wash and cut the potatoes into halves or quarters, "
190+
"depending on size, and place in a large baking tray."
191+
),
192+
(
193+
"Drizzle olive oil over the chicken and potatoes, then "
194+
"season with salt, black pepper, and finely chopped "
195+
"rosemary and garlic."
196+
),
197+
(
198+
"Place the tray in the oven and bake for about 45 minutes, "
199+
"or until the chicken is fully cooked and the potatoes are "
200+
"golden and crispy."
201+
),
202+
(
203+
"Remove from the oven and let it rest for a few minutes "
204+
"before serving."
205+
),
206+
],
207+
)
208+
209+
```
145210

146-
!!! success "Result"
147-
148-
Recipe Name: Herbed Chicken with Roasted Potatoes
149-
150-
Ingredients:
151-
152-
- Chicken
153-
- Potatoes
154-
- Olive oil
155-
- Rosemary
156-
- Salt
157-
- Black pepper
158-
- Garlic (optional)
159-
160-
Steps:
161-
162-
1. Preheat your oven to 200 degrees Celsius (392 degrees Fahrenheit).
163-
2. Wash and cut the potatoes into chunks, then toss them with olive oil, salt, rosemary, and black pepper. Place them on a baking tray.
164-
...
165-
166211
### Return annotation
167212

168213
Marvin will cast the output of your function to the type specified in the return annotation. If you do not provide a return annotation, Marvin will assume that the function returns a string.

prefect.yaml

+21-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ push: null
88
pull:
99
- prefect.deployments.steps.git_clone:
1010
repository: https://github.com/PrefectHQ/marvin.git
11-
branch: '2.0'
1211
- prefect.deployments.steps.run_shell_script:
13-
script: pip install git+https://github.com/PrefectHQ/marvin.git@2.0 prefect-gcp
12+
script: pip install git+https://github.com/PrefectHQ/marvin.git prefect-gcp
1413

1514
deployments:
1615
- name: github-repo-digest
@@ -26,4 +25,23 @@ deployments:
2625
name: kubernetes-prd-internal-tools
2726
job_variables:
2827
env:
29-
OPENAI_API_KEY: '{{ prefect.blocks.secret.openai-api-key }}'
28+
OPENAI_API_KEY: '{{ prefect.blocks.secret.openai-api-key }}'
29+
30+
- name: label-issues
31+
tags: ['internal-tools', 'LLM']
32+
description: Label issues based on their content
33+
triggers:
34+
- enabled: true
35+
expect:
36+
- marvin.issue.opened
37+
- marvin.issue.reopened
38+
parameters:
39+
event_body_str: "{{ event.payload.body }}"
40+
entrypoint: cookbook/flows/label_issues.py:label_issues
41+
work_pool:
42+
name: kubernetes-prd-internal-tools
43+
job_variables:
44+
env:
45+
OPENAI_API_KEY: '{{ prefect.blocks.secret.openai-api-key }}'
46+
GH_UTIL_TOKEN: '{{ prefect.blocks.secret.gh-token }}'
47+
EXTRA_PIP_PACKAGES: 'gh-util'

src/marvin/utilities/openai.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@ def get_openai_client(
8888
else:
8989
raise ValueError(f"Unknown provider {marvin.settings.provider}")
9090

91+
loop = asyncio.get_event_loop() if is_async else None
92+
9193
return _get_client_memoized(
9294
cls=client_class,
93-
loop=asyncio.get_event_loop(),
95+
loop=loop,
9496
kwargs_items=tuple(kwargs.items()),
9597
)
9698

0 commit comments

Comments
 (0)