mojentic 0.9.0__py3-none-any.whl → 1.0.1__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.
- _examples/async_dispatcher_example.py +12 -4
- _examples/async_llm_example.py +1 -2
- _examples/broker_as_tool.py +39 -14
- _examples/broker_examples.py +4 -6
- _examples/characterize_ollama.py +1 -1
- _examples/characterize_openai.py +1 -1
- _examples/chat_session.py +1 -1
- _examples/chat_session_with_tool.py +1 -1
- _examples/coding_file_tool.py +1 -3
- _examples/current_datetime_tool_example.py +1 -1
- _examples/embeddings.py +1 -1
- _examples/ephemeral_task_manager_example.py +13 -9
- _examples/fetch_openai_models.py +10 -3
- _examples/file_deduplication.py +6 -6
- _examples/image_analysis.py +2 -3
- _examples/image_broker.py +1 -1
- _examples/image_broker_splat.py +1 -1
- _examples/iterative_solver.py +2 -2
- _examples/model_characterization.py +2 -0
- _examples/openai_gateway_enhanced_demo.py +15 -5
- _examples/raw.py +1 -1
- _examples/react/agents/decisioning_agent.py +173 -15
- _examples/react/agents/summarization_agent.py +89 -0
- _examples/react/agents/thinking_agent.py +84 -14
- _examples/react/agents/tool_call_agent.py +83 -0
- _examples/react/formatters.py +38 -4
- _examples/react/models/base.py +60 -11
- _examples/react/models/events.py +76 -8
- _examples/react.py +71 -21
- _examples/recursive_agent.py +1 -1
- _examples/solver_chat_session.py +1 -7
- _examples/streaming.py +7 -5
- _examples/tell_user_example.py +3 -3
- _examples/tracer_demo.py +15 -17
- _examples/tracer_qt_viewer.py +49 -46
- mojentic/__init__.py +3 -3
- mojentic/agents/__init__.py +26 -8
- mojentic/agents/{agent_broker.py → agent_event_adapter.py} +3 -3
- mojentic/agents/async_aggregator_agent_spec.py +32 -33
- mojentic/agents/async_llm_agent.py +9 -5
- mojentic/agents/async_llm_agent_spec.py +21 -22
- mojentic/agents/base_async_agent.py +2 -2
- mojentic/agents/base_llm_agent.py +6 -2
- mojentic/agents/iterative_problem_solver.py +11 -5
- mojentic/agents/simple_recursive_agent.py +11 -10
- mojentic/agents/simple_recursive_agent_spec.py +423 -0
- mojentic/async_dispatcher.py +0 -1
- mojentic/async_dispatcher_spec.py +1 -1
- mojentic/context/__init__.py +0 -2
- mojentic/dispatcher.py +7 -8
- mojentic/llm/__init__.py +5 -5
- mojentic/llm/chat_session.py +24 -1
- mojentic/llm/chat_session_spec.py +40 -0
- mojentic/llm/gateways/__init__.py +19 -18
- mojentic/llm/gateways/anthropic.py +1 -0
- mojentic/llm/gateways/anthropic_messages_adapter.py +0 -1
- mojentic/llm/gateways/llm_gateway.py +1 -1
- mojentic/llm/gateways/ollama.py +2 -0
- mojentic/llm/gateways/openai.py +62 -58
- mojentic/llm/gateways/openai_message_adapter_spec.py +3 -3
- mojentic/llm/gateways/openai_model_registry.py +7 -6
- mojentic/llm/gateways/openai_model_registry_spec.py +1 -2
- mojentic/llm/gateways/openai_temperature_handling_spec.py +2 -2
- mojentic/llm/llm_broker.py +7 -5
- mojentic/llm/llm_broker_spec.py +7 -2
- mojentic/llm/message_composers.py +6 -3
- mojentic/llm/message_composers_spec.py +5 -1
- mojentic/llm/registry/__init__.py +0 -3
- mojentic/llm/tools/__init__.py +0 -9
- mojentic/llm/tools/ask_user_tool.py +11 -5
- mojentic/llm/tools/current_datetime.py +9 -6
- mojentic/llm/tools/date_resolver.py +10 -4
- mojentic/llm/tools/date_resolver_spec.py +0 -1
- mojentic/llm/tools/ephemeral_task_manager/append_task_tool.py +4 -1
- mojentic/llm/tools/ephemeral_task_manager/ephemeral_task_list.py +1 -1
- mojentic/llm/tools/ephemeral_task_manager/insert_task_after_tool.py +4 -1
- mojentic/llm/tools/ephemeral_task_manager/prepend_task_tool.py +5 -2
- mojentic/llm/tools/file_manager.py +131 -28
- mojentic/llm/tools/file_manager_spec.py +0 -3
- mojentic/llm/tools/llm_tool.py +1 -1
- mojentic/llm/tools/llm_tool_spec.py +0 -2
- mojentic/llm/tools/organic_web_search.py +4 -2
- mojentic/llm/tools/tell_user_tool.py +6 -2
- mojentic/llm/tools/tool_wrapper.py +2 -2
- mojentic/tracer/__init__.py +1 -10
- mojentic/tracer/event_store.py +7 -8
- mojentic/tracer/event_store_spec.py +1 -2
- mojentic/tracer/null_tracer.py +37 -43
- mojentic/tracer/tracer_events.py +8 -2
- mojentic/tracer/tracer_events_spec.py +6 -7
- mojentic/tracer/tracer_system.py +37 -36
- mojentic/tracer/tracer_system_spec.py +21 -6
- mojentic/utils/__init__.py +1 -1
- mojentic/utils/formatting.py +1 -0
- {mojentic-0.9.0.dist-info → mojentic-1.0.1.dist-info}/METADATA +47 -29
- mojentic-1.0.1.dist-info/RECORD +149 -0
- {mojentic-0.9.0.dist-info → mojentic-1.0.1.dist-info}/WHEEL +1 -1
- mojentic-0.9.0.dist-info/RECORD +0 -146
- {mojentic-0.9.0.dist-info → mojentic-1.0.1.dist-info}/licenses/LICENSE.md +0 -0
- {mojentic-0.9.0.dist-info → mojentic-1.0.1.dist-info}/top_level.txt +0 -0
_examples/react/models/events.py
CHANGED
|
@@ -1,28 +1,96 @@
|
|
|
1
|
+
"""Event definitions for the ReAct pattern.
|
|
2
|
+
|
|
3
|
+
This module defines all event types used to coordinate the ReAct loop,
|
|
4
|
+
including thinking, decisioning, tool calls, completion, and failure events.
|
|
5
|
+
"""
|
|
1
6
|
from pydantic import Field
|
|
2
7
|
|
|
3
8
|
from mojentic import Event
|
|
9
|
+
|
|
4
10
|
from .base import CurrentContext, NextAction
|
|
5
11
|
|
|
6
12
|
|
|
7
13
|
class InvokeThinking(Event):
|
|
8
|
-
|
|
14
|
+
"""Event to trigger the thinking/planning phase.
|
|
15
|
+
|
|
16
|
+
This event initiates the planning process where the agent creates
|
|
17
|
+
or refines a plan for answering the user's query.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
context: CurrentContext = Field(
|
|
21
|
+
...,
|
|
22
|
+
description="The current context as we work through our response."
|
|
23
|
+
)
|
|
9
24
|
|
|
10
25
|
|
|
11
26
|
class InvokeDecisioning(Event):
|
|
12
|
-
|
|
27
|
+
"""Event to trigger the decision-making phase.
|
|
28
|
+
|
|
29
|
+
This event initiates the decision process where the agent evaluates
|
|
30
|
+
the current plan and history to decide on the next action.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
context: CurrentContext = Field(
|
|
34
|
+
...,
|
|
35
|
+
description="The current context as we work through our response."
|
|
36
|
+
)
|
|
13
37
|
|
|
14
38
|
|
|
15
39
|
class InvokeToolCall(Event):
|
|
16
|
-
|
|
17
|
-
|
|
40
|
+
"""Event to trigger a tool invocation.
|
|
41
|
+
|
|
42
|
+
This event carries the information needed to execute a specific tool
|
|
43
|
+
with given arguments, along with the reasoning behind the decision.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
context: CurrentContext = Field(
|
|
47
|
+
...,
|
|
48
|
+
description="The current context as we work through our response."
|
|
49
|
+
)
|
|
50
|
+
thought: str = Field(
|
|
51
|
+
...,
|
|
52
|
+
description="The reasoning behind the decision."
|
|
53
|
+
)
|
|
18
54
|
action: NextAction
|
|
55
|
+
tool: object = Field(
|
|
56
|
+
...,
|
|
57
|
+
description="The tool instance to invoke."
|
|
58
|
+
)
|
|
59
|
+
tool_arguments: dict = Field(
|
|
60
|
+
default_factory=dict,
|
|
61
|
+
description="Arguments to pass to the tool."
|
|
62
|
+
)
|
|
19
63
|
|
|
20
64
|
|
|
21
65
|
class FinishAndSummarize(Event):
|
|
22
|
-
|
|
23
|
-
|
|
66
|
+
"""Event to trigger the completion and summarization phase.
|
|
67
|
+
|
|
68
|
+
This event indicates that the agent has gathered sufficient information
|
|
69
|
+
to answer the user's query and should generate a final response.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
context: CurrentContext = Field(
|
|
73
|
+
...,
|
|
74
|
+
description="The current context as we work through our response."
|
|
75
|
+
)
|
|
76
|
+
thought: str = Field(
|
|
77
|
+
...,
|
|
78
|
+
description="The reasoning behind the decision."
|
|
79
|
+
)
|
|
24
80
|
|
|
25
81
|
|
|
26
82
|
class FailureOccurred(Event):
|
|
27
|
-
|
|
28
|
-
|
|
83
|
+
"""Event to signal a failure in the ReAct loop.
|
|
84
|
+
|
|
85
|
+
This event captures errors or unrecoverable situations that prevent
|
|
86
|
+
the agent from continuing to process the user's query.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
context: CurrentContext = Field(
|
|
90
|
+
...,
|
|
91
|
+
description="The current context as we work through our response."
|
|
92
|
+
)
|
|
93
|
+
reason: str = Field(
|
|
94
|
+
...,
|
|
95
|
+
description="The reason for the failure."
|
|
96
|
+
)
|
_examples/react.py
CHANGED
|
@@ -1,32 +1,82 @@
|
|
|
1
|
+
"""ReAct Pattern Example.
|
|
2
|
+
|
|
3
|
+
This example demonstrates a Reasoning and Acting (ReAct) loop where agents
|
|
4
|
+
iteratively plan, decide, act, and summarize to answer user queries.
|
|
5
|
+
|
|
6
|
+
The ReAct pattern consists of:
|
|
7
|
+
1. Thinking Agent - Creates plans
|
|
8
|
+
2. Decisioning Agent - Decides next actions
|
|
9
|
+
3. Tool Call Agent - Executes tools
|
|
10
|
+
4. Summarization Agent - Generates final answers
|
|
11
|
+
"""
|
|
1
12
|
from _examples.react.agents.decisioning_agent import DecisioningAgent
|
|
13
|
+
from _examples.react.agents.summarization_agent import SummarizationAgent
|
|
2
14
|
from _examples.react.agents.thinking_agent import ThinkingAgent
|
|
15
|
+
from _examples.react.agents.tool_call_agent import ToolCallAgent
|
|
3
16
|
from _examples.react.models.base import CurrentContext
|
|
4
|
-
from _examples.react.models.events import
|
|
5
|
-
|
|
6
|
-
|
|
17
|
+
from _examples.react.models.events import (
|
|
18
|
+
FailureOccurred,
|
|
19
|
+
FinishAndSummarize,
|
|
20
|
+
InvokeDecisioning,
|
|
21
|
+
InvokeThinking,
|
|
22
|
+
InvokeToolCall,
|
|
23
|
+
)
|
|
24
|
+
from mojentic import Dispatcher, Router
|
|
25
|
+
from mojentic.agents.output_agent import OutputAgent
|
|
7
26
|
from mojentic.llm import LLMBroker
|
|
8
27
|
|
|
9
|
-
# llm = LLMBroker("qwen3:32b")
|
|
10
|
-
llm = LLMBroker("deepseek-r1:70b")
|
|
11
|
-
thinking_agent = ThinkingAgent(llm)
|
|
12
|
-
decisioning_agent = DecisioningAgent(llm)
|
|
13
28
|
|
|
14
|
-
|
|
29
|
+
def main():
|
|
30
|
+
"""Run the ReAct pattern example."""
|
|
31
|
+
# Initialize LLM broker - using qwen3:32b as it's widely available
|
|
32
|
+
llm = LLMBroker("qwen3:32b")
|
|
33
|
+
# Alternative models (uncomment if available):
|
|
34
|
+
# llm = LLMBroker("deepseek-r1:70b")
|
|
35
|
+
# llm = LLMBroker("qwen3:8b")
|
|
15
36
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
37
|
+
# Create agents
|
|
38
|
+
thinking_agent = ThinkingAgent(llm)
|
|
39
|
+
decisioning_agent = DecisioningAgent(llm)
|
|
40
|
+
tool_call_agent = ToolCallAgent()
|
|
41
|
+
summarization_agent = SummarizationAgent(llm)
|
|
42
|
+
output_agent = OutputAgent()
|
|
20
43
|
|
|
21
|
-
|
|
44
|
+
# Configure router - maps event types to agent handlers
|
|
45
|
+
router = Router({
|
|
46
|
+
InvokeThinking: [thinking_agent, output_agent],
|
|
47
|
+
InvokeDecisioning: [decisioning_agent, output_agent],
|
|
48
|
+
InvokeToolCall: [tool_call_agent, output_agent],
|
|
49
|
+
FinishAndSummarize: [summarization_agent, output_agent],
|
|
50
|
+
FailureOccurred: [output_agent],
|
|
51
|
+
})
|
|
22
52
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
53
|
+
# Create dispatcher
|
|
54
|
+
dispatcher = Dispatcher(router)
|
|
55
|
+
|
|
56
|
+
# Create initial context
|
|
57
|
+
initial_context = CurrentContext(
|
|
58
|
+
user_query="What is the date next Friday?"
|
|
29
59
|
)
|
|
30
|
-
)
|
|
31
60
|
|
|
32
|
-
|
|
61
|
+
# Start the ReAct loop
|
|
62
|
+
print("\n" + "=" * 80)
|
|
63
|
+
print("Starting ReAct Pattern Example")
|
|
64
|
+
print("=" * 80)
|
|
65
|
+
print(f"User Query: {initial_context.user_query}")
|
|
66
|
+
print("=" * 80 + "\n")
|
|
67
|
+
|
|
68
|
+
# Create and dispatch initial thinking event
|
|
69
|
+
initial_event = InvokeThinking(
|
|
70
|
+
source=type(main),
|
|
71
|
+
context=initial_context
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
dispatcher.dispatch(initial_event)
|
|
75
|
+
|
|
76
|
+
print("\n" + "=" * 80)
|
|
77
|
+
print("ReAct Pattern Example Complete")
|
|
78
|
+
print("=" * 80 + "\n")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == "__main__":
|
|
82
|
+
main()
|
_examples/recursive_agent.py
CHANGED
|
@@ -78,7 +78,7 @@ async def demonstrate_async():
|
|
|
78
78
|
|
|
79
79
|
# Create tasks for all problems and run them concurrently
|
|
80
80
|
tasks = [solve_and_print(problem) for problem in problems]
|
|
81
|
-
|
|
81
|
+
await asyncio.gather(*tasks)
|
|
82
82
|
|
|
83
83
|
print("\nAll concurrent problems have been solved!")
|
|
84
84
|
|
_examples/solver_chat_session.py
CHANGED
|
@@ -4,11 +4,10 @@ from typing import List
|
|
|
4
4
|
from mojentic.agents import IterativeProblemSolver
|
|
5
5
|
from mojentic.llm.tools.date_resolver import ResolveDateTool
|
|
6
6
|
from mojentic.llm.tools.llm_tool import LLMTool
|
|
7
|
+
from mojentic.llm import LLMBroker, ChatSession
|
|
7
8
|
|
|
8
9
|
logging.basicConfig(level=logging.WARN)
|
|
9
10
|
|
|
10
|
-
from mojentic.llm import LLMBroker, ChatSession
|
|
11
|
-
|
|
12
11
|
|
|
13
12
|
class IterativeProblemSolverTool(LLMTool):
|
|
14
13
|
def __init__(self, llm: LLMBroker, tools: List[LLMTool]):
|
|
@@ -50,11 +49,6 @@ def main():
|
|
|
50
49
|
# llm = LLMBroker(model="qwq:32b-fp16")
|
|
51
50
|
# llm = LLMBroker(model="qwen3:32b")
|
|
52
51
|
|
|
53
|
-
tools = [
|
|
54
|
-
ResolveDateTool(),
|
|
55
|
-
IterativeProblemSolverTool(llm=llm, tools=[ResolveDateTool()])
|
|
56
|
-
]
|
|
57
|
-
|
|
58
52
|
chat_session = ChatSession(llm, tools=[IterativeProblemSolverTool(llm=llm, tools=[ResolveDateTool()])])
|
|
59
53
|
|
|
60
54
|
while True:
|
_examples/streaming.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import os
|
|
2
1
|
from mojentic.llm.llm_broker import LLMBroker
|
|
3
2
|
from mojentic.llm.gateways.models import LLMMessage
|
|
4
3
|
from mojentic.llm.gateways.ollama import OllamaGateway
|
|
5
|
-
from mojentic.llm.gateways.openai import OpenAIGateway
|
|
6
4
|
from mojentic.llm.tools.date_resolver import ResolveDateTool
|
|
7
5
|
|
|
8
6
|
|
|
@@ -30,15 +28,19 @@ def main():
|
|
|
30
28
|
|
|
31
29
|
stream = broker.generate_stream(
|
|
32
30
|
messages=[
|
|
33
|
-
LLMMessage(
|
|
34
|
-
|
|
31
|
+
LLMMessage(
|
|
32
|
+
content=(
|
|
33
|
+
"Tell me a short story about a dragon. "
|
|
34
|
+
"In your story, reference several dates relative to today, "
|
|
35
|
+
"like 'three days from now' or 'last week'."
|
|
36
|
+
)
|
|
37
|
+
)
|
|
35
38
|
],
|
|
36
39
|
tools=[date_tool],
|
|
37
40
|
temperature=0.7,
|
|
38
41
|
num_ctx=32768,
|
|
39
42
|
num_predict=-1
|
|
40
43
|
)
|
|
41
|
-
|
|
42
44
|
for chunk in stream:
|
|
43
45
|
print(chunk, end='', flush=True)
|
|
44
46
|
|
_examples/tell_user_example.py
CHANGED
|
@@ -7,12 +7,12 @@ to display messages to the user without expecting a response.
|
|
|
7
7
|
|
|
8
8
|
import logging
|
|
9
9
|
|
|
10
|
-
logging.basicConfig(level=logging.WARN)
|
|
11
|
-
|
|
12
10
|
from mojentic.agents.iterative_problem_solver import IterativeProblemSolver
|
|
13
11
|
from mojentic.llm.tools.tell_user_tool import TellUserTool
|
|
14
12
|
from mojentic.llm import LLMBroker
|
|
15
13
|
|
|
14
|
+
logging.basicConfig(level=logging.WARN)
|
|
15
|
+
|
|
16
16
|
|
|
17
17
|
def main():
|
|
18
18
|
# Initialize the LLM broker with your preferred model
|
|
@@ -40,4 +40,4 @@ def main():
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
if __name__ == "__main__":
|
|
43
|
-
main()
|
|
43
|
+
main()
|
_examples/tracer_demo.py
CHANGED
|
@@ -9,23 +9,21 @@ It also demonstrates how correlation_id is used to trace related events
|
|
|
9
9
|
across the system, allowing you to track the flow of a request from start to finish.
|
|
10
10
|
"""
|
|
11
11
|
import uuid
|
|
12
|
-
from datetime import datetime
|
|
13
12
|
|
|
14
13
|
from mojentic.tracer import TracerSystem
|
|
15
14
|
from mojentic.tracer.tracer_events import LLMCallTracerEvent, LLMResponseTracerEvent, ToolCallTracerEvent
|
|
16
15
|
from mojentic.llm import ChatSession, LLMBroker
|
|
17
|
-
from mojentic.llm.gateways.models import LLMMessage, MessageRole
|
|
18
16
|
from mojentic.llm.tools.date_resolver import ResolveDateTool
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
def print_tracer_events(events):
|
|
22
20
|
"""Print tracer events using their printable_summary method."""
|
|
23
|
-
print(
|
|
21
|
+
print("\n{'-'*80}")
|
|
24
22
|
print("Tracer Events:")
|
|
25
|
-
print(
|
|
23
|
+
print("{'-'*80}")
|
|
26
24
|
|
|
27
25
|
for i, event in enumerate(events, 1):
|
|
28
|
-
print(
|
|
26
|
+
print("{i}. {event.printable_summary()}")
|
|
29
27
|
print()
|
|
30
28
|
|
|
31
29
|
|
|
@@ -69,7 +67,7 @@ def main():
|
|
|
69
67
|
turn_counter += 1
|
|
70
68
|
conversation_correlation_ids[turn_counter] = correlation_id
|
|
71
69
|
|
|
72
|
-
print(
|
|
70
|
+
print("[Turn {turn_counter}, correlation_id: {correlation_id[:8]}...]")
|
|
73
71
|
print("Assistant: ", end="")
|
|
74
72
|
|
|
75
73
|
# For demonstration purposes, we'll use the chat_session normally
|
|
@@ -85,30 +83,30 @@ def main():
|
|
|
85
83
|
# After the user exits, display tracer event summary
|
|
86
84
|
print("\nTracer System Summary")
|
|
87
85
|
print("=" * 80)
|
|
88
|
-
print(
|
|
86
|
+
print("You just had a conversation with an LLM, and the tracer recorded everything!")
|
|
89
87
|
|
|
90
88
|
# Get all events
|
|
91
89
|
all_events = tracer.get_events()
|
|
92
|
-
print(
|
|
90
|
+
print("Total events recorded: {len(all_events)}")
|
|
93
91
|
print_tracer_events(all_events)
|
|
94
92
|
|
|
95
93
|
# Show how to filter events by type
|
|
96
94
|
print("\nYou can filter events by type:")
|
|
97
95
|
|
|
98
96
|
llm_calls = tracer.get_events(event_type=LLMCallTracerEvent)
|
|
99
|
-
print(
|
|
97
|
+
print("LLM Call Events: {len(llm_calls)}")
|
|
100
98
|
if llm_calls:
|
|
101
|
-
print(
|
|
99
|
+
print("Example: {llm_calls[0].printable_summary()}")
|
|
102
100
|
|
|
103
101
|
llm_responses = tracer.get_events(event_type=LLMResponseTracerEvent)
|
|
104
|
-
print(
|
|
102
|
+
print("LLM Response Events: {len(llm_responses)}")
|
|
105
103
|
if llm_responses:
|
|
106
|
-
print(
|
|
104
|
+
print("Example: {llm_responses[0].printable_summary()}")
|
|
107
105
|
|
|
108
106
|
tool_calls = tracer.get_events(event_type=ToolCallTracerEvent)
|
|
109
|
-
print(
|
|
107
|
+
print("Tool Call Events: {len(tool_calls)}")
|
|
110
108
|
if tool_calls:
|
|
111
|
-
print(
|
|
109
|
+
print("Example: {tool_calls[0].printable_summary()}")
|
|
112
110
|
|
|
113
111
|
# Show the last few events
|
|
114
112
|
print("\nThe last few events:")
|
|
@@ -130,7 +128,7 @@ def main():
|
|
|
130
128
|
first_correlation_id = conversation_correlation_ids.get(first_turn_id)
|
|
131
129
|
|
|
132
130
|
if first_correlation_id:
|
|
133
|
-
print(
|
|
131
|
+
print("\nEvents for conversation turn {first_turn_id} (correlation_id: {first_correlation_id[:8]}...):")
|
|
134
132
|
|
|
135
133
|
# Define a filter function that checks the correlation_id
|
|
136
134
|
def filter_by_correlation_id(event):
|
|
@@ -140,7 +138,7 @@ def main():
|
|
|
140
138
|
related_events = tracer.get_events(filter_func=filter_by_correlation_id)
|
|
141
139
|
|
|
142
140
|
if related_events:
|
|
143
|
-
print(
|
|
141
|
+
print("Found {len(related_events)} related events")
|
|
144
142
|
print_tracer_events(related_events)
|
|
145
143
|
|
|
146
144
|
# Show how this helps trace the flow of a request
|
|
@@ -163,7 +161,7 @@ def main():
|
|
|
163
161
|
|
|
164
162
|
print("Tool usage frequency:")
|
|
165
163
|
for tool_name, count in tool_names.items():
|
|
166
|
-
print(
|
|
164
|
+
print(" - {tool_name}: {count} calls")
|
|
167
165
|
|
|
168
166
|
|
|
169
167
|
if __name__ == "__main__":
|