Skip to content

Commit 50f7de8

Browse files
authored
Merge pull request #64 from jlowin/llm
New backend
2 parents a7e9dd2 + 3f199f0 commit 50f7de8

21 files changed

+951
-810
lines changed

docs/concepts/execution.mdx

Lines changed: 16 additions & 373 deletions
Large diffs are not rendered by default.

docs/concepts/workflow-design.mdx

Lines changed: 374 additions & 0 deletions
Large diffs are not rendered by default.

docs/mint.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"concepts/tasks",
4949
"concepts/flows",
5050
"concepts/agents",
51+
"concepts/workflow-design",
5152
"concepts/execution"
5253
]
5354
},

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "controlflow"
3-
version = "0.3.0"
3+
version = "0.4.0"
44
description = "A framework for agentic workflows"
55
authors = [
66
{ name = "Jeremiah Lowin", email = "153965+jlowin@users.noreply.github.com" },

requirements-dev.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ markupsafe==2.1.5
237237
# via mkdocs-autorefs
238238
# via mkdocstrings
239239
# via werkzeug
240-
marvin @ git+https://github.com/prefecthq/marvin@fbfa2e6d2f8f65d611f3519941966e7fc382a880
240+
marvin @ git+https://github.com/prefecthq/marvin@9ff559318af3dd1185ab7d6a1e85b39967915b81
241241
# via controlflow
242242
matplotlib-inline==0.1.6
243243
# via ipython
@@ -325,7 +325,7 @@ pluggy==1.4.0
325325
# via pytest
326326
pre-commit==3.7.0
327327
# via prefect
328-
prefect @ git+https://github.com/prefecthq/prefect@b7ce5ed9eb0cf813dfb20a9f1fe8815dd2008ca1
328+
prefect @ git+https://github.com/prefecthq/prefect@aad7f63ccfc7767729f65fe20b0defb208b2c451
329329
# via controlflow
330330
prompt-toolkit==3.0.43
331331
# via ipython

requirements.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ markupsafe==2.1.5
237237
# via mkdocs-autorefs
238238
# via mkdocstrings
239239
# via werkzeug
240-
marvin @ git+https://github.com/prefecthq/marvin@fbfa2e6d2f8f65d611f3519941966e7fc382a880
240+
marvin @ git+https://github.com/prefecthq/marvin@9ff559318af3dd1185ab7d6a1e85b39967915b81
241241
# via controlflow
242242
matplotlib-inline==0.1.7
243243
# via ipython
@@ -325,7 +325,7 @@ pluggy==1.5.0
325325
# via pytest
326326
pre-commit==3.7.1
327327
# via prefect
328-
prefect @ git+https://github.com/prefecthq/prefect@b7ce5ed9eb0cf813dfb20a9f1fe8815dd2008ca1
328+
prefect @ git+https://github.com/prefecthq/prefect@aad7f63ccfc7767729f65fe20b0defb208b2c451
329329
# via controlflow
330330
prompt-toolkit==3.0.43
331331
# via ipython

src/controlflow/__init__.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
from .settings import settings
2-
import controlflow.llm
3-
4-
default_history = controlflow.llm.history.InMemoryHistory()
52

63
from .core.flow import Flow
74
from .core.task import Task
@@ -10,3 +7,17 @@
107

118
from .instructions import instructions
129
from .decorators import flow, task
10+
11+
# --- Default agent ---
12+
13+
from .core.agent import DEFAULT_AGENT
14+
15+
default_agent = DEFAULT_AGENT
16+
del DEFAULT_AGENT
17+
18+
# --- Default history ---
19+
20+
from .llm.history import DEFAULT_HISTORY
21+
22+
default_history = DEFAULT_HISTORY
23+
del DEFAULT_HISTORY

src/controlflow/core/agent.py

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import logging
22
from typing import Callable, Optional, Union
33

4-
from litellm import Message
54
from marvin.utilities.asyncio import ExposeSyncMethodsMixin, expose_sync_method
65
from pydantic import Field
76

7+
import controlflow
88
from controlflow.core.flow import Flow, get_flow
99
from controlflow.core.task import Task
10-
from controlflow.llm.completions import Response, completion, completion_async
1110
from controlflow.tools.talk_to_human import talk_to_human
1211
from controlflow.utilities.prefect import (
1312
wrap_prefect_tool,
@@ -17,17 +16,11 @@
1716
logger = logging.getLogger(__name__)
1817

1918

20-
def default_agent():
21-
return Agent(
22-
name="Marvin",
23-
instructions="""
24-
You are a diligent AI assistant. You complete
25-
your tasks efficiently and without error.
26-
""",
27-
)
19+
def get_default_agent() -> "Agent":
20+
return controlflow.default_agent
2821

2922

30-
class Agent(Assistant, ControlFlowModel, ExposeSyncMethodsMixin):
23+
class AgentOLD(Assistant, ControlFlowModel, ExposeSyncMethodsMixin):
3124
name: str
3225
user_access: bool = Field(
3326
False,
@@ -62,11 +55,8 @@ async def run_async(
6255
controller = Controller(agents=[self], tasks=tasks or [], flow=flow)
6356
return await controller.run_agent_async(agent=self)
6457

65-
def __hash__(self):
66-
return id(self)
67-
6858

69-
class LiteAgent(ControlFlowModel, ExposeSyncMethodsMixin):
59+
class Agent(ControlFlowModel, ExposeSyncMethodsMixin):
7060
name: str = Field(
7161
...,
7262
description="The name of the agent. This is used to identify the agent in the system and should be unique per assigned task.",
@@ -84,31 +74,53 @@ class LiteAgent(ControlFlowModel, ExposeSyncMethodsMixin):
8474
False,
8575
description="If True, the agent is given tools for interacting with a human user.",
8676
)
87-
model: Optional[str] = Field(
88-
None,
77+
model: str = Field(
8978
description="The model used by the agent. If not provided, the default model will be used.",
79+
default_factory=lambda: controlflow.settings.model,
9080
)
9181

92-
async def run_async(self, messages: Union[str, dict]) -> Response:
93-
if not isinstance(messages, list):
94-
raise ValueError("Messages must be provided as a list.")
95-
96-
messages = [
97-
Message(role="user", content=m) if isinstance(m, str) else m
98-
for m in messages
99-
]
100-
101-
return await completion_async(
102-
messages=messages, model=self.model, tools=self.tools
103-
)
104-
105-
async def run(self, messages: Union[str, dict]) -> Response:
106-
if not isinstance(messages, list):
107-
raise ValueError("Messages must be provided as a list.")
82+
def __init__(self, name, **kwargs):
83+
super().__init__(name=name, **kwargs)
10884

109-
messages = [
110-
Message(role="user", content=m) if isinstance(m, str) else m
111-
for m in messages
112-
]
113-
114-
return completion(messages=messages, model=self.model, tools=self.tools)
85+
def get_tools(self) -> list[Callable]:
86+
tools = self.tools.copy()
87+
if self.user_access:
88+
tools.append(talk_to_human)
89+
return tools
90+
91+
# def say(
92+
# self, messages: Union[str, dict], thread_id: str = None, history: History = None
93+
# ) -> Response:
94+
95+
# if thread_id is None:
96+
# thread_id = self.default_thread_id
97+
# if history is None:
98+
# history = get_default_history()
99+
# if not isinstance(messages, list):
100+
# raise ValueError("Messages must be provided as a list.")
101+
102+
# messages = [
103+
# Message(role="user", content=m) if isinstance(m, str) else m
104+
# for m in messages
105+
# ]
106+
# history_messages = history.load_messages(thread_id=thread_id, limit=50)
107+
108+
# response = completion(
109+
# messages=history_messages + messages,
110+
# model=self.model,
111+
# tools=self.tools,
112+
# )
113+
# history.save_messages(
114+
# thread_id=thread_id,
115+
# messages=messages + history_messages + response.messages,
116+
# )
117+
# return response
118+
119+
120+
DEFAULT_AGENT = Agent(
121+
name="Marvin",
122+
instructions="""
123+
You are a diligent AI assistant. You complete
124+
your tasks efficiently and without error.
125+
""",
126+
)

0 commit comments

Comments
 (0)