fastworkflow 2.15.0__py3-none-any.whl → 2.15.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastworkflow/chat_session.py +16 -1
- fastworkflow/command_executor.py +2 -2
- fastworkflow/workflow_agent.py +34 -7
- {fastworkflow-2.15.0.dist-info → fastworkflow-2.15.2.dist-info}/METADATA +1 -1
- {fastworkflow-2.15.0.dist-info → fastworkflow-2.15.2.dist-info}/RECORD +8 -8
- {fastworkflow-2.15.0.dist-info → fastworkflow-2.15.2.dist-info}/LICENSE +0 -0
- {fastworkflow-2.15.0.dist-info → fastworkflow-2.15.2.dist-info}/WHEEL +0 -0
- {fastworkflow-2.15.0.dist-info → fastworkflow-2.15.2.dist-info}/entry_points.txt +0 -0
fastworkflow/chat_session.py
CHANGED
|
@@ -121,6 +121,8 @@ class ChatSession:
|
|
|
121
121
|
self._command_output_queue = Queue()
|
|
122
122
|
self._status = SessionStatus.STOPPED
|
|
123
123
|
self._chat_worker = None
|
|
124
|
+
|
|
125
|
+
self._conversation_history = dspy.History(messages=[])
|
|
124
126
|
|
|
125
127
|
# Import here to avoid circular imports
|
|
126
128
|
from fastworkflow.command_executor import CommandExecutor
|
|
@@ -297,6 +299,11 @@ class ChatSession:
|
|
|
297
299
|
def workflow_is_complete(self, value: bool) -> None:
|
|
298
300
|
if workflow := ChatSession.get_active_workflow():
|
|
299
301
|
workflow.is_complete = value
|
|
302
|
+
|
|
303
|
+
@property
|
|
304
|
+
def conversation_history(self) -> dspy.History:
|
|
305
|
+
"""Return the conversation history."""
|
|
306
|
+
return self._conversation_history
|
|
300
307
|
|
|
301
308
|
|
|
302
309
|
def _run_workflow_loop(self) -> Optional[fastworkflow.CommandOutput]:
|
|
@@ -421,7 +428,10 @@ class ChatSession:
|
|
|
421
428
|
|
|
422
429
|
lm = dspy_utils.get_lm("LLM_AGENT", "LITELLM_API_KEY_AGENT")
|
|
423
430
|
with dspy.context(lm=lm):
|
|
424
|
-
agent_result = self._workflow_tool_agent(
|
|
431
|
+
agent_result = self._workflow_tool_agent(
|
|
432
|
+
user_query=refined_message,
|
|
433
|
+
conversation_history=self.conversation_history
|
|
434
|
+
)
|
|
425
435
|
# dspy.inspect_history(n=1)
|
|
426
436
|
|
|
427
437
|
# Extract the final result from the agent
|
|
@@ -431,6 +441,11 @@ class ChatSession:
|
|
|
431
441
|
else str(agent_result)
|
|
432
442
|
)
|
|
433
443
|
|
|
444
|
+
self.conversation_history.messages.append(
|
|
445
|
+
{"user_query": message,
|
|
446
|
+
"agent_response": result_text}
|
|
447
|
+
)
|
|
448
|
+
|
|
434
449
|
# Create CommandOutput with the agent's response
|
|
435
450
|
command_response = fastworkflow.CommandResponse(response=result_text)
|
|
436
451
|
# Attach actions captured during agent execution as artifacts if available
|
fastworkflow/command_executor.py
CHANGED
|
@@ -52,7 +52,7 @@ class CommandExecutor(CommandExecutorInterface):
|
|
|
52
52
|
record = {
|
|
53
53
|
"command" if command_output.success else "failing command": command,
|
|
54
54
|
"command_name": command_output.command_name,
|
|
55
|
-
"parameters": command_output.
|
|
55
|
+
"parameters": command_output.command_parameters.model_dump() if command_output.command_parameters else None,
|
|
56
56
|
"response": command_output.command_responses[0].response if command_output.success else ''}
|
|
57
57
|
with open("action.json", "a", encoding="utf-8") as f:
|
|
58
58
|
f.write(json.dumps(record, ensure_ascii=False) + "\n")
|
|
@@ -99,7 +99,7 @@ class CommandExecutor(CommandExecutorInterface):
|
|
|
99
99
|
record = {
|
|
100
100
|
"command": command,
|
|
101
101
|
"command_name": command_name,
|
|
102
|
-
"parameters": input_obj.model_dump(),
|
|
102
|
+
"parameters": input_obj.model_dump() if input_obj else None,
|
|
103
103
|
"response": command_output.command_responses[0].response}
|
|
104
104
|
with open("action.json", "a", encoding="utf-8") as f:
|
|
105
105
|
f.write(json.dumps(record, ensure_ascii=False) + "\n")
|
fastworkflow/workflow_agent.py
CHANGED
|
@@ -18,6 +18,7 @@ class WorkflowAgentSignature(dspy.Signature):
|
|
|
18
18
|
All the tasks in the todo list must be completed before returning the final answer.
|
|
19
19
|
"""
|
|
20
20
|
user_query = dspy.InputField(desc="The natural language user query.")
|
|
21
|
+
conversation_history: dspy.History = dspy.InputField()
|
|
21
22
|
final_answer = dspy.OutputField(desc="Comprehensive final answer with supporting evidence to demonstrate that all the tasks in the todo list have been completed.")
|
|
22
23
|
|
|
23
24
|
def _what_can_i_do(chat_session_obj: fastworkflow.ChatSession) -> str:
|
|
@@ -119,7 +120,8 @@ def _ask_user_tool(clarification_request: str, chat_session_obj: fastworkflow.Ch
|
|
|
119
120
|
command_responses=[fastworkflow.CommandResponse(response=clarification_request)]
|
|
120
121
|
)
|
|
121
122
|
chat_session_obj.command_output_queue.put(command_output)
|
|
122
|
-
|
|
123
|
+
user_query = chat_session_obj.user_message_queue.get()
|
|
124
|
+
return _think_and_plan(user_query, chat_session_obj)
|
|
123
125
|
|
|
124
126
|
def initialize_workflow_tool_agent(mcp_server: FastWorkflowMCPServer, max_iters: int = 25):
|
|
125
127
|
"""
|
|
@@ -133,11 +135,6 @@ def initialize_workflow_tool_agent(mcp_server: FastWorkflowMCPServer, max_iters:
|
|
|
133
135
|
Returns:
|
|
134
136
|
DSPy ReAct agent configured with workflow tools
|
|
135
137
|
"""
|
|
136
|
-
# available_tools = mcp_server.list_tools()
|
|
137
|
-
|
|
138
|
-
# if not available_tools:
|
|
139
|
-
# return None
|
|
140
|
-
|
|
141
138
|
chat_session_obj = mcp_server.chat_session
|
|
142
139
|
if not chat_session_obj:
|
|
143
140
|
return None
|
|
@@ -185,7 +182,7 @@ def initialize_workflow_tool_agent(mcp_server: FastWorkflowMCPServer, max_iters:
|
|
|
185
182
|
"""
|
|
186
183
|
Executes the command and returns either a response, or a clarification request.
|
|
187
184
|
Use the "what_can_i_do" tool to get details on available commands, including their names and parameters. Fyi, values in the 'examples' field are fake and for illustration purposes only.
|
|
188
|
-
Commands must be formatted as follows: command_name <param1_name>param1_value</param1_name> <param2_name>param2_value</param2_name> ...
|
|
185
|
+
Commands must be formatted using plain text for command name followed by XML tags enclosing parameter values (if any) as follows: command_name <param1_name>param1_value</param1_name> <param2_name>param2_value</param2_name> ...
|
|
189
186
|
Don't use this tool to respond to a clarification requests in PARAMETER EXTRACTION ERROR state
|
|
190
187
|
"""
|
|
191
188
|
try:
|
|
@@ -225,3 +222,33 @@ def initialize_workflow_tool_agent(mcp_server: FastWorkflowMCPServer, max_iters:
|
|
|
225
222
|
tools=tools,
|
|
226
223
|
max_iters=max_iters,
|
|
227
224
|
)
|
|
225
|
+
|
|
226
|
+
def _think_and_plan(user_query: str, chat_session_obj: fastworkflow.ChatSession) -> str:
|
|
227
|
+
"""
|
|
228
|
+
Returns a refined plan by breaking down a user_query into simpler tasks based only on available commands and returns a todo list.
|
|
229
|
+
"""
|
|
230
|
+
class TaskPlannerSignature(dspy.Signature):
|
|
231
|
+
"""
|
|
232
|
+
Break down a user_query into simpler tasks based only on available commands and return a todo list.
|
|
233
|
+
If user_query is simple, return a single todo that is the user_query as-is
|
|
234
|
+
"""
|
|
235
|
+
user_query: str = dspy.InputField()
|
|
236
|
+
available_commands: list[str] = dspy.InputField()
|
|
237
|
+
todo_list: list[str] = dspy.OutputField(desc="task descriptions as short sentences")
|
|
238
|
+
|
|
239
|
+
current_workflow = chat_session_obj.get_active_workflow()
|
|
240
|
+
available_commands = CommandMetadataAPI.get_command_display_text(
|
|
241
|
+
subject_workflow_path=current_workflow.folderpath,
|
|
242
|
+
cme_workflow_path=fastworkflow.get_internal_workflow_path("command_metadata_extraction"),
|
|
243
|
+
active_context_name=current_workflow.current_command_context_name,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
planner_lm = dspy_utils.get_lm("LLM_PLANNER", "LITELLM_API_KEY_PLANNER")
|
|
247
|
+
with dspy.context(lm=planner_lm):
|
|
248
|
+
task_planner_func = dspy.ChainOfThought(TaskPlannerSignature)
|
|
249
|
+
prediction = task_planner_func(user_query=user_query, available_commands=available_commands)
|
|
250
|
+
|
|
251
|
+
if not prediction.todo_list or (len(prediction.todo_list) == 1 and prediction.todo_list[0] == user_query):
|
|
252
|
+
return user_query
|
|
253
|
+
|
|
254
|
+
return f"{user_query}\nNext steps:\n{'\n'.join([f'{i + 1}. {task}' for i, task in enumerate(prediction.todo_list)])}"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastworkflow
|
|
3
|
-
Version: 2.15.
|
|
3
|
+
Version: 2.15.2
|
|
4
4
|
Summary: A framework for rapidly building large-scale, deterministic, interactive workflows with a fault-tolerant, conversational UX
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Keywords: fastworkflow,ai,workflow,llm,openai
|
|
@@ -33,11 +33,11 @@ fastworkflow/build/navigator_stub_generator.py,sha256=_DSvHC6r1xWQiFHtUgPhI51nQf
|
|
|
33
33
|
fastworkflow/build/pydantic_model_generator.py,sha256=oNyoANyUWBpHG-fE3tGL911RNvDzQXjxAm0ssvuXUH4,1854
|
|
34
34
|
fastworkflow/build/utterance_generator.py,sha256=UrtkF0wyAZ1hiFitHX0g8w7Wh-D0leLCrP1aUACSfHo,299
|
|
35
35
|
fastworkflow/cache_matching.py,sha256=OoB--1tO6-O4BKCuCrUbB0CkUr76J62K4VAf6MShi-w,7984
|
|
36
|
-
fastworkflow/chat_session.py,sha256=
|
|
36
|
+
fastworkflow/chat_session.py,sha256=EOtPy3XG6tDR_FW1j-FAxcdgwRM668t13NuusEa_smg,25776
|
|
37
37
|
fastworkflow/cli.py,sha256=RB78V78NAZsZtNqF4_kk-TnEKCOy-cFLF6wSwz8aP14,26345
|
|
38
38
|
fastworkflow/command_context_model.py,sha256=nWxLP3TR7WJr3yWCedqcdFOxo_kwae_mS3VRN2cOmK8,13437
|
|
39
39
|
fastworkflow/command_directory.py,sha256=aJ6UQCwevfF11KbcQB2Qz6mQ7Kj91pZtvHmQY6JFnao,29030
|
|
40
|
-
fastworkflow/command_executor.py,sha256=
|
|
40
|
+
fastworkflow/command_executor.py,sha256=nlg-vzZI78f-9tcacrOB4_SK4vVhvszsZd6cwfDP9hc,9030
|
|
41
41
|
fastworkflow/command_interfaces.py,sha256=PWIKlcp0G8nmYl0vkrg1o6QzJL0pxXkfrn1joqTa0eU,460
|
|
42
42
|
fastworkflow/command_metadata_api.py,sha256=KtidE3PM9HYfY-nmEXZ8Y4nnaw2qn23p_gvwFVT3F8Y,39770
|
|
43
43
|
fastworkflow/command_routing.py,sha256=R7194pcY0d2VHzmCu9ALacm1UvNuIRIvTn8mLp-EZIM,17219
|
|
@@ -166,10 +166,10 @@ fastworkflow/utils/python_utils.py,sha256=OzSf-bGve1401SHM3QXXFauBOBrlGQzPNgvvGJ
|
|
|
166
166
|
fastworkflow/utils/signatures.py,sha256=3B3EafS5b76L4hOwDyABKMuY_bfEwmCYdK6T5DxWM1w,20968
|
|
167
167
|
fastworkflow/utils/startup_progress.py,sha256=9icSdnpFAxzIq0sUliGpNaH0Efvrt5lDtGfURV5BD98,3539
|
|
168
168
|
fastworkflow/workflow.py,sha256=F7kGoNQbAMwy71zT1V_KF8PbRTCY4Dz-16Zv4ApK8m8,18939
|
|
169
|
-
fastworkflow/workflow_agent.py,sha256=
|
|
169
|
+
fastworkflow/workflow_agent.py,sha256=9l1P8_6Ej5BwomMjHJa8PlxSGkd9g9l9IWw0o8AtPBo,13183
|
|
170
170
|
fastworkflow/workflow_inheritance_model.py,sha256=Pp-qSrQISgPfPjJVUfW84pc7HLmL2evuq0UVIYR51K0,7974
|
|
171
|
-
fastworkflow-2.15.
|
|
172
|
-
fastworkflow-2.15.
|
|
173
|
-
fastworkflow-2.15.
|
|
174
|
-
fastworkflow-2.15.
|
|
175
|
-
fastworkflow-2.15.
|
|
171
|
+
fastworkflow-2.15.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
172
|
+
fastworkflow-2.15.2.dist-info/METADATA,sha256=-z606kQh8w5hHKtF78paGR5EEQ8rWpMaj13h99bGNZY,29867
|
|
173
|
+
fastworkflow-2.15.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
174
|
+
fastworkflow-2.15.2.dist-info/entry_points.txt,sha256=m8HqoPzCyaZLAx-V5X8MJgw3Lx3GiPDlxNEZ7K-Gb-U,54
|
|
175
|
+
fastworkflow-2.15.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|