lite-agent 0.2.0__tar.gz → 0.3.0__tar.gz
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.
Potentially problematic release.
This version of lite-agent might be problematic. Click here for more details.
- {lite_agent-0.2.0 → lite_agent-0.3.0}/CHANGELOG.md +41 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/PKG-INFO +1 -1
- {lite_agent-0.2.0 → lite_agent-0.3.0}/examples/basic.py +1 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/examples/handoffs.py +6 -2
- lite_agent-0.3.0/examples/image.py +59 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/examples/message_transfer_example.py +8 -5
- lite_agent-0.3.0/examples/response_api_example.py +129 -0
- lite_agent-0.3.0/examples/rich_helpers_demo.py +130 -0
- lite_agent-0.3.0/examples/set_chat_history_example.py +104 -0
- lite_agent-0.3.0/examples/simple_rich_example.py +44 -0
- lite_agent-0.3.0/examples/stop_with_tool_call.py +49 -0
- lite_agent-0.3.0/examples/type_system_example.py +103 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/pyproject.toml +1 -1
- lite_agent-0.3.0/src/lite_agent/__init__.py +8 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/agent.py +109 -28
- lite_agent-0.3.0/src/lite_agent/client.py +34 -0
- lite_agent-0.3.0/src/lite_agent/rich_helpers.py +503 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/runner.py +162 -17
- lite_agent-0.3.0/src/lite_agent/templates/handoffs_source_instructions.xml.j2 +10 -0
- lite_agent-0.3.0/src/lite_agent/templates/handoffs_target_instructions.xml.j2 +9 -0
- lite_agent-0.3.0/src/lite_agent/templates/wait_for_user_instructions.xml.j2 +6 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/types/__init__.py +20 -0
- lite_agent-0.3.0/src/lite_agent/types/messages.py +135 -0
- lite_agent-0.3.0/tests/mocks/handoffs/1.jsonl +36 -0
- lite_agent-0.3.0/tests/performance/test_set_chat_history_performance.py +128 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/unit/test_agent.py +4 -1
- lite_agent-0.3.0/tests/unit/test_completion_condition.py +89 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/unit/test_message_transfers.py +9 -9
- lite_agent-0.3.0/tests/unit/test_response_api_format.py +296 -0
- lite_agent-0.3.0/tests/unit/test_rich_helpers.py +129 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/unit/test_runner.py +0 -1
- lite_agent-0.3.0/tests/unit/test_set_chat_history.py +355 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/uv.lock +220 -193
- lite_agent-0.2.0/examples/handoff_workflow_demo.py +0 -0
- lite_agent-0.2.0/src/lite_agent/__init__.py +0 -7
- lite_agent-0.2.0/src/lite_agent/types/messages.py +0 -68
- {lite_agent-0.2.0 → lite_agent-0.3.0}/.github/workflows/ci.yml +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/.gitignore +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/.python-version +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/.vscode/launch.json +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/README.md +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/examples/channels/rich_channel.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/examples/confirm_and_continue.py +0 -0
- /lite_agent-0.2.0/examples/test_consolidate_history.py → /lite_agent-0.3.0/examples/consolidate_history.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/examples/context.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/examples/message_transfer_example_new.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/examples/responses.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/examples/terminal.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/pyrightconfig.json +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/scripts/record_chat_messages.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/loggers.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/message_transfers.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/processors/__init__.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/processors/stream_chunk_processor.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/py.typed +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/stream_handlers/__init__.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/stream_handlers/litellm.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/types/chunks.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/src/lite_agent/types/tool_calls.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/integration/test_agent_with_mocks.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/integration/test_basic.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/integration/test_mock_litellm.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/mocks/basic/1.jsonl +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/mocks/confirm_and_continue/1.jsonl +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/mocks/confirm_and_continue/2.jsonl +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/mocks/context/1.jsonl +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/unit/test_agent_handoffs.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/unit/test_append_message.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/unit/test_file_recording.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/unit/test_litellm_stream_handler.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/unit/test_message_transfer.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/unit/test_stream_chunk_processor.py +0 -0
- {lite_agent-0.2.0 → lite_agent-0.3.0}/tests/utils/mock_litellm.py +0 -0
|
@@ -1,3 +1,44 @@
|
|
|
1
|
+
## v0.3.0
|
|
2
|
+
|
|
3
|
+
[v0.2.0...v0.3.0](https://github.com/Jannchie/lite-agent/compare/v0.2.0...v0.3.0)
|
|
4
|
+
|
|
5
|
+
### :rocket: Breaking Changes
|
|
6
|
+
|
|
7
|
+
- **rich-helpers**: rename render_chat_history to print_chat_history and update imports - By [Jannchie](mailto:jannchie@gmail.com) in [3db6721](https://github.com/Jannchie/lite-agent/commit/3db6721)
|
|
8
|
+
|
|
9
|
+
### :sparkles: Features
|
|
10
|
+
|
|
11
|
+
- **agent**: use jinja2 templates for instruction messages - By [Jannchie](mailto:jannchie@gmail.com) in [f5ccbd5](https://github.com/Jannchie/lite-agent/commit/f5ccbd5)
|
|
12
|
+
- **agent**: add completion_condition and task_done tool support - By [Jannchie](mailto:jannchie@gmail.com) in [28126b1](https://github.com/Jannchie/lite-agent/commit/28126b1)
|
|
13
|
+
- **response-api**: add response api format for text and image input - By [Jannchie](mailto:jannchie@gmail.com) in [4b44f91](https://github.com/Jannchie/lite-agent/commit/4b44f91)
|
|
14
|
+
- **rich-helpers**: add rich chat history renderer and chat summary utils - By [Jannchie](mailto:jannchie@gmail.com) in [5a570ce](https://github.com/Jannchie/lite-agent/commit/5a570ce)
|
|
15
|
+
- **runner**: add set_chat_history to support full chat history replay and agent tracking - By [Jannchie](mailto:jannchie@gmail.com) in [fd2ecdc](https://github.com/Jannchie/lite-agent/commit/fd2ecdc)
|
|
16
|
+
- **types**: enhance runner type system for flexible user_input - By [Jannchie](mailto:jannchie@gmail.com) in [3a2e9c5](https://github.com/Jannchie/lite-agent/commit/3a2e9c5)
|
|
17
|
+
|
|
18
|
+
### :adhesive_bandage: Fixes
|
|
19
|
+
|
|
20
|
+
- **examples**: check content key before modifying messages - By [Jannchie](mailto:jannchie@gmail.com) in [94b85a6](https://github.com/Jannchie/lite-agent/commit/94b85a6)
|
|
21
|
+
|
|
22
|
+
### :art: Refactors
|
|
23
|
+
|
|
24
|
+
- **agent**: abstract llm client and refactor model usage - By [Jannchie](mailto:jannchie@gmail.com) in [09c52c8](https://github.com/Jannchie/lite-agent/commit/09c52c8)
|
|
25
|
+
- **client**: move llm client classes to separate module - By [Jannchie](mailto:jannchie@gmail.com) in [a70d163](https://github.com/Jannchie/lite-agent/commit/a70d163)
|
|
26
|
+
- **rich-helpers-test**: rename render_chat_history to print_chat_history - By [Jannchie](mailto:jannchie@gmail.com) in [bf1ca8f](https://github.com/Jannchie/lite-agent/commit/bf1ca8f)
|
|
27
|
+
|
|
28
|
+
### :lipstick: Styles
|
|
29
|
+
|
|
30
|
+
- **agent**: inline error message formatting - By [Jannchie](mailto:jannchie@gmail.com) in [1453cc5](https://github.com/Jannchie/lite-agent/commit/1453cc5)
|
|
31
|
+
- **tests**: add type ignore hints to assertions - By [Jannchie](mailto:jannchie@gmail.com) in [8d2a19d](https://github.com/Jannchie/lite-agent/commit/8d2a19d)
|
|
32
|
+
|
|
33
|
+
### :memo: Documentation
|
|
34
|
+
|
|
35
|
+
- **set-chat-history**: remove set_chat_history feature documentation - By [Jannchie](mailto:jannchie@gmail.com) in [2413351](https://github.com/Jannchie/lite-agent/commit/2413351)
|
|
36
|
+
|
|
37
|
+
### :wrench: Chores
|
|
38
|
+
|
|
39
|
+
- **examples**: rename test_consolidate_history to consolidate_history - By [Jannchie](mailto:jannchie@gmail.com) in [0f5b39a](https://github.com/Jannchie/lite-agent/commit/0f5b39a)
|
|
40
|
+
- **tests**: remove legacy chat bubble and alignment tests - By [Jannchie](mailto:jannchie@gmail.com) in [46b23bc](https://github.com/Jannchie/lite-agent/commit/46b23bc)
|
|
41
|
+
|
|
1
42
|
## v0.2.0
|
|
2
43
|
|
|
3
44
|
[v0.1.0...v0.2.0](https://github.com/Jannchie/lite-agent/compare/v0.1.0...v0.2.0)
|
|
@@ -62,11 +62,15 @@ async def main():
|
|
|
62
62
|
parent.add_handoff(whether_agent)
|
|
63
63
|
parent.add_handoff(temper_agent)
|
|
64
64
|
|
|
65
|
-
print(temper_agent.fc.function_registry)
|
|
66
65
|
runner = Runner(parent)
|
|
67
|
-
resp = runner.run(
|
|
66
|
+
resp = runner.run(
|
|
67
|
+
"Hello, I need to check the whether and temperature of Tokyo.",
|
|
68
|
+
includes=["final_message", "tool_call", "tool_call_result"],
|
|
69
|
+
record_to="tests/mocks/handoffs/1.jsonl",
|
|
70
|
+
)
|
|
68
71
|
async for message in resp:
|
|
69
72
|
logger.info(message)
|
|
73
|
+
print(f"{runner.get_messages_dict()}")
|
|
70
74
|
logger.info(runner.agent.name)
|
|
71
75
|
|
|
72
76
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from rich.logging import RichHandler
|
|
5
|
+
|
|
6
|
+
from lite_agent.agent import Agent
|
|
7
|
+
from lite_agent.runner import Runner
|
|
8
|
+
|
|
9
|
+
logging.basicConfig(
|
|
10
|
+
level=logging.WARNING,
|
|
11
|
+
format="%(message)s",
|
|
12
|
+
datefmt="[%X]",
|
|
13
|
+
handlers=[RichHandler(rich_tracebacks=True)],
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger("lite_agent")
|
|
17
|
+
logger.setLevel(logging.DEBUG)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
agent = Agent(
|
|
21
|
+
model="gpt-4.1-nano",
|
|
22
|
+
name="Photo Judge Agent",
|
|
23
|
+
instructions=(
|
|
24
|
+
"You are a helpful photo judge agent. You will receive a photo and you need to judge "
|
|
25
|
+
"whether it is a good photo or not. You should rate the photo on a scale of 1 to 10, "
|
|
26
|
+
"where 1 is the worst and 10 is the best. If you think the photo is not good, you "
|
|
27
|
+
"should provide a reason why it is not good."
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
async def main():
|
|
33
|
+
runner = Runner(agent)
|
|
34
|
+
|
|
35
|
+
resp = runner.run(
|
|
36
|
+
[
|
|
37
|
+
{
|
|
38
|
+
"role": "user",
|
|
39
|
+
"content": [
|
|
40
|
+
{
|
|
41
|
+
"type": "input_text",
|
|
42
|
+
"text": "What do you think about this photo?",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"type": "input_image",
|
|
46
|
+
"detail": "low",
|
|
47
|
+
"image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/Lavant_St._Peter_und_Paul_Hochaltar_01.jpg/1024px-Lavant_St._Peter_und_Paul_Hochaltar_01.jpg",
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
includes=["final_message", "usage"],
|
|
53
|
+
)
|
|
54
|
+
async for chunk in resp:
|
|
55
|
+
logger.info(chunk)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
if __name__ == "__main__":
|
|
59
|
+
asyncio.run(main())
|
|
@@ -35,7 +35,8 @@ def example_message_transfer(messages: RunnerMessages) -> RunnerMessages:
|
|
|
35
35
|
# Add prefix to user messages
|
|
36
36
|
content = message.get("content", "")
|
|
37
37
|
processed_message = message.copy()
|
|
38
|
-
|
|
38
|
+
if "content" in processed_message:
|
|
39
|
+
processed_message["content"] = f"[PROCESSED] {content}"
|
|
39
40
|
processed_messages.append(processed_message)
|
|
40
41
|
else:
|
|
41
42
|
processed_messages.append(message)
|
|
@@ -76,10 +77,9 @@ def privacy_filter_transfer(messages: RunnerMessages) -> RunnerMessages:
|
|
|
76
77
|
|
|
77
78
|
for message in messages:
|
|
78
79
|
if isinstance(message, dict):
|
|
79
|
-
content
|
|
80
|
-
if isinstance(content, str):
|
|
80
|
+
if "content" in message and isinstance(message["content"], str):
|
|
81
81
|
processed_message = message.copy()
|
|
82
|
-
processed_message["content"] = filter_content(content)
|
|
82
|
+
processed_message["content"] = filter_content(message["content"])
|
|
83
83
|
processed_messages.append(processed_message)
|
|
84
84
|
else:
|
|
85
85
|
processed_messages.append(message)
|
|
@@ -164,7 +164,10 @@ async def main():
|
|
|
164
164
|
consolidated = consolidate_history_transfer(complex_messages)
|
|
165
165
|
print("Consolidated result:")
|
|
166
166
|
if consolidated and isinstance(consolidated[0], dict):
|
|
167
|
-
|
|
167
|
+
if "content" in consolidated[0]:
|
|
168
|
+
print(consolidated[0]["content"])
|
|
169
|
+
else:
|
|
170
|
+
print(consolidated[0])
|
|
168
171
|
|
|
169
172
|
|
|
170
173
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Example demonstrating the new Response API format for mixed text and image content.
|
|
4
|
+
|
|
5
|
+
This example shows how to use the new ResponseInputText and ResponseInputImage
|
|
6
|
+
classes for internal message representation, which are automatically converted
|
|
7
|
+
to the legacy Completion API format when making actual LLM calls.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
|
|
12
|
+
from lite_agent import Agent, Runner
|
|
13
|
+
from lite_agent.types import ResponseInputImage, ResponseInputText
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def main():
|
|
17
|
+
"""Demonstrate using Response API format for mixed content messages."""
|
|
18
|
+
|
|
19
|
+
# Create an agent
|
|
20
|
+
agent = Agent(
|
|
21
|
+
model="gpt-4-turbo",
|
|
22
|
+
name="ImageAnalysisAgent",
|
|
23
|
+
instructions="You are a helpful assistant that can analyze images and answer questions about them.",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Create a runner instance
|
|
27
|
+
runner = Runner(agent)
|
|
28
|
+
|
|
29
|
+
# Example 1: Traditional text-only message (still works)
|
|
30
|
+
print("=== Example 1: Text-only message ===")
|
|
31
|
+
runner.append_message(
|
|
32
|
+
{
|
|
33
|
+
"role": "user",
|
|
34
|
+
"content": "Hello! Can you help me analyze some images?",
|
|
35
|
+
},
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Example 2: Using new Response API format with mixed content
|
|
39
|
+
print("\n=== Example 2: Mixed content using Response API format ===")
|
|
40
|
+
|
|
41
|
+
# Create message content using new Response API format
|
|
42
|
+
mixed_content = [
|
|
43
|
+
ResponseInputText(
|
|
44
|
+
type="input_text",
|
|
45
|
+
text="What do you think about this photo?",
|
|
46
|
+
),
|
|
47
|
+
ResponseInputImage(
|
|
48
|
+
type="input_image",
|
|
49
|
+
detail="high",
|
|
50
|
+
image_url="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/Lavant_St._Peter_und_Paul_Hochaltar_01.jpg/1024px-Lavant_St._Peter_und_Paul_Hochaltar_01.jpg",
|
|
51
|
+
),
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
# Add the message with mixed content
|
|
55
|
+
runner.append_message(
|
|
56
|
+
{
|
|
57
|
+
"role": "user",
|
|
58
|
+
"content": mixed_content,
|
|
59
|
+
},
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Example 3: Demonstrating file_id limitation
|
|
63
|
+
print("\n=== Example 3: file_id limitation ===")
|
|
64
|
+
print("Note: file_id is not supported for Completion API and will raise an error")
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
file_content = [
|
|
68
|
+
ResponseInputText(
|
|
69
|
+
type="input_text",
|
|
70
|
+
text="Can you describe this image file?",
|
|
71
|
+
),
|
|
72
|
+
ResponseInputImage(
|
|
73
|
+
type="input_image",
|
|
74
|
+
detail="auto",
|
|
75
|
+
file_id="file-12345", # This will cause an error
|
|
76
|
+
),
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
runner.append_message(
|
|
80
|
+
{
|
|
81
|
+
"role": "user",
|
|
82
|
+
"content": file_content,
|
|
83
|
+
},
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# This will raise an error when trying to convert
|
|
87
|
+
converted_messages = agent._convert_responses_to_completions_format(runner.messages) # noqa: SLF001
|
|
88
|
+
print("❌ This should not be reached!")
|
|
89
|
+
|
|
90
|
+
except ValueError as e:
|
|
91
|
+
print(f"✅ Expected error caught: {e}")
|
|
92
|
+
# Clear the message that caused the error
|
|
93
|
+
runner.messages.pop()
|
|
94
|
+
|
|
95
|
+
# Print the internal message representation
|
|
96
|
+
print("\n=== Internal message representation ===")
|
|
97
|
+
for i, message in enumerate(runner.messages):
|
|
98
|
+
print(f"Message {i + 1}:")
|
|
99
|
+
if hasattr(message, "model_dump"):
|
|
100
|
+
print(f" {message.model_dump()}")
|
|
101
|
+
else:
|
|
102
|
+
print(f" {message}")
|
|
103
|
+
print()
|
|
104
|
+
|
|
105
|
+
# Show how messages are converted for LLM API calls
|
|
106
|
+
print("\n=== Converted messages for LLM API ===")
|
|
107
|
+
# Note: In a real application, this conversion happens automatically
|
|
108
|
+
# We're accessing the private method here just for demonstration
|
|
109
|
+
converted_messages = agent._convert_responses_to_completions_format(runner.messages) # noqa: SLF001
|
|
110
|
+
for i, message in enumerate(converted_messages):
|
|
111
|
+
print(f"Converted Message {i + 1}:")
|
|
112
|
+
print(f" {message}")
|
|
113
|
+
print()
|
|
114
|
+
|
|
115
|
+
print("\n=== Summary ===")
|
|
116
|
+
print("The new Response API format allows you to:")
|
|
117
|
+
print("1. Use ResponseInputText for text content")
|
|
118
|
+
print("2. Use ResponseInputImage for image content with image_url")
|
|
119
|
+
print("3. Mix text and images in a single message")
|
|
120
|
+
print("4. Automatic conversion to legacy Completion API format for LLM calls")
|
|
121
|
+
print("\n⚠️ Important limitations:")
|
|
122
|
+
print("- file_id is NOT supported for Completion API - use image_url instead")
|
|
123
|
+
print("- ResponseInputImage must have either file_id or image_url")
|
|
124
|
+
print("\nThis provides better type safety and clearer separation between")
|
|
125
|
+
print("internal representation and external API compatibility.")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
if __name__ == "__main__":
|
|
129
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""
|
|
2
|
+
示例:使用 rich_helpers 美观渲染聊天记录
|
|
3
|
+
|
|
4
|
+
这个示例展示了如何使用 rich_helpers 模块中的函数来美观地渲染聊天记录。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
|
|
9
|
+
from lite_agent.agent import Agent
|
|
10
|
+
from lite_agent.rich_helpers import print_chat_history, print_chat_summary
|
|
11
|
+
from lite_agent.runner import Runner
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def demo_tools():
|
|
15
|
+
"""演示工具函数,用于测试函数调用显示。"""
|
|
16
|
+
|
|
17
|
+
def get_weather(city: str) -> str:
|
|
18
|
+
"""获取指定城市的天气信息。"""
|
|
19
|
+
return f"The weather in {city} is sunny with 25°C"
|
|
20
|
+
|
|
21
|
+
def calculate(expression: str) -> str:
|
|
22
|
+
"""计算数学表达式。"""
|
|
23
|
+
try:
|
|
24
|
+
result = eval(expression) # noqa: S307
|
|
25
|
+
except Exception as e:
|
|
26
|
+
return f"Error calculating {expression}: {e}"
|
|
27
|
+
else:
|
|
28
|
+
return f"{expression} = {result}"
|
|
29
|
+
|
|
30
|
+
return [get_weather, calculate]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def create_sample_chat_history() -> Runner:
|
|
34
|
+
"""创建一个包含各种消息类型的示例聊天历史。"""
|
|
35
|
+
# 创建 agent
|
|
36
|
+
agent = Agent(
|
|
37
|
+
model="gpt-4o-mini",
|
|
38
|
+
name="DemoAgent",
|
|
39
|
+
instructions="You are a helpful assistant that can provide weather information and perform calculations.",
|
|
40
|
+
tools=demo_tools(),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# 创建 runner
|
|
44
|
+
runner = Runner(agent=agent)
|
|
45
|
+
|
|
46
|
+
# 手动添加一些示例消息来展示不同的消息类型
|
|
47
|
+
runner.append_message({"role": "system", "content": "You are a helpful assistant."})
|
|
48
|
+
runner.append_message({"role": "user", "content": "Hello! Can you help me with some tasks?"})
|
|
49
|
+
runner.append_message({"role": "assistant", "content": "Of course! I'd be happy to help you. What would you like to do?"})
|
|
50
|
+
runner.append_message({"role": "user", "content": "What's the weather like in Tokyo?"})
|
|
51
|
+
|
|
52
|
+
# 添加函数调用消息
|
|
53
|
+
runner.append_message(
|
|
54
|
+
{
|
|
55
|
+
"type": "function_call",
|
|
56
|
+
"function_call_id": "call_123",
|
|
57
|
+
"name": "get_weather",
|
|
58
|
+
"arguments": '{"city": "Tokyo"}',
|
|
59
|
+
"content": "",
|
|
60
|
+
},
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# 添加函数调用输出
|
|
64
|
+
runner.append_message(
|
|
65
|
+
{
|
|
66
|
+
"type": "function_call_output",
|
|
67
|
+
"call_id": "call_123",
|
|
68
|
+
"output": "The weather in Tokyo is sunny with 25°C",
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
runner.append_message({"role": "assistant", "content": "The weather in Tokyo is sunny with a temperature of 25°C. Is there anything else you'd like to know?"})
|
|
73
|
+
runner.append_message({"role": "user", "content": "Can you calculate 25 * 4 + 10?"})
|
|
74
|
+
|
|
75
|
+
# 添加另一个函数调用
|
|
76
|
+
runner.append_message(
|
|
77
|
+
{
|
|
78
|
+
"type": "function_call",
|
|
79
|
+
"function_call_id": "call_456",
|
|
80
|
+
"name": "calculate",
|
|
81
|
+
"arguments": '{"expression": "25 * 4 + 10"}',
|
|
82
|
+
"content": "",
|
|
83
|
+
},
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
runner.append_message(
|
|
87
|
+
{
|
|
88
|
+
"type": "function_call_output",
|
|
89
|
+
"call_id": "call_456",
|
|
90
|
+
"output": "25 * 4 + 10 = 110",
|
|
91
|
+
},
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
runner.append_message({"role": "assistant", "content": "The calculation 25 * 4 + 10 equals 110."})
|
|
95
|
+
|
|
96
|
+
return runner
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
async def main():
|
|
100
|
+
"""主函数:演示 rich_helpers 的使用。"""
|
|
101
|
+
print("🎨 Rich Chat History Renderer Demo\n")
|
|
102
|
+
|
|
103
|
+
# 创建示例聊天历史
|
|
104
|
+
runner = await create_sample_chat_history()
|
|
105
|
+
|
|
106
|
+
# 1. 展示聊天摘要
|
|
107
|
+
print("📊 Chat Summary:")
|
|
108
|
+
print_chat_summary(runner.messages)
|
|
109
|
+
print()
|
|
110
|
+
|
|
111
|
+
# 2. 渲染完整的聊天历史
|
|
112
|
+
print("💬 Full Chat History:")
|
|
113
|
+
print_chat_history(runner.messages)
|
|
114
|
+
|
|
115
|
+
# 3. 展示不同的渲染选项
|
|
116
|
+
print("\n" + "=" * 60)
|
|
117
|
+
print("🎛️ Different Rendering Options:")
|
|
118
|
+
print("=" * 60)
|
|
119
|
+
|
|
120
|
+
# 不显示时间戳和索引
|
|
121
|
+
print("\n📝 Without timestamps and indices:")
|
|
122
|
+
print_chat_history(
|
|
123
|
+
runner.messages,
|
|
124
|
+
show_timestamps=False,
|
|
125
|
+
show_indices=False,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
if __name__ == "__main__":
|
|
130
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Example demonstrating the set_chat_history functionality.
|
|
3
|
+
|
|
4
|
+
This example shows how to set a complete chat history and automatically track
|
|
5
|
+
which agent should be active based on function calls in the history.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from rich.logging import RichHandler
|
|
12
|
+
|
|
13
|
+
from lite_agent import consolidate_history_transfer
|
|
14
|
+
from lite_agent.agent import Agent
|
|
15
|
+
from lite_agent.loggers import logger
|
|
16
|
+
from lite_agent.runner import Runner
|
|
17
|
+
|
|
18
|
+
logging.basicConfig(
|
|
19
|
+
format="%(message)s",
|
|
20
|
+
datefmt="[%X]",
|
|
21
|
+
handlers=[RichHandler(rich_tracebacks=True)],
|
|
22
|
+
)
|
|
23
|
+
logger.setLevel(logging.DEBUG)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_temperature(city: str) -> str:
|
|
27
|
+
"""Get the temperature of a city."""
|
|
28
|
+
return f"The temperature in {city} is 25°C."
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def get_weather(city: str) -> str:
|
|
32
|
+
"""Get the weather of a city."""
|
|
33
|
+
return f"The weather in {city} is sunny."
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def main():
|
|
37
|
+
"""Demonstrate set_chat_history functionality."""
|
|
38
|
+
# Create agents
|
|
39
|
+
parent = Agent(
|
|
40
|
+
model="gpt-4.1",
|
|
41
|
+
name="ParentAgent",
|
|
42
|
+
instructions="You are a helpful agent.",
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
weather_agent = Agent(
|
|
46
|
+
model="gpt-4.1",
|
|
47
|
+
name="WeatherAgent",
|
|
48
|
+
instructions="You are a helpful agent to check weather.",
|
|
49
|
+
tools=[get_weather],
|
|
50
|
+
message_transfer=consolidate_history_transfer,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
temperature_agent = Agent(
|
|
54
|
+
model="gpt-4.1",
|
|
55
|
+
name="TemperatureAgent",
|
|
56
|
+
instructions="You are a helpful agent to check temperature.",
|
|
57
|
+
tools=[get_temperature],
|
|
58
|
+
message_transfer=consolidate_history_transfer,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
parent.add_handoff(weather_agent)
|
|
62
|
+
parent.add_handoff(temperature_agent)
|
|
63
|
+
|
|
64
|
+
# Create runner
|
|
65
|
+
runner = Runner(parent)
|
|
66
|
+
|
|
67
|
+
# Example chat history that includes agent transfers
|
|
68
|
+
chat_history = [
|
|
69
|
+
{"role": "user", "content": "Hello, I need to check the whether and temperature of Tokyo."},
|
|
70
|
+
{"role": "assistant", "content": ""},
|
|
71
|
+
{"arguments": '{"name":"WhetherAgent"}', "type": "function_call", "function_call_id": "call_HRTCM7KqkMkwhFWs2THxeub1", "name": "transfer_to_agent", "content": ""},
|
|
72
|
+
{"call_id": "call_HRTCM7KqkMkwhFWs2THxeub1", "output": "Transferring to agent: WhetherAgent", "type": "function_call_output"},
|
|
73
|
+
{"role": "assistant", "content": ""},
|
|
74
|
+
{"arguments": '{"city":"Tokyo"}', "type": "function_call", "function_call_id": "call_W02qQluI5XeM6Pk7je8xEwVs", "name": "get_weather", "content": ""},
|
|
75
|
+
{"call_id": "call_W02qQluI5XeM6Pk7je8xEwVs", "output": "The weather in Tokyo is sunny.", "type": "function_call_output"},
|
|
76
|
+
{"role": "assistant", "content": ""},
|
|
77
|
+
{"arguments": "{}", "type": "function_call", "function_call_id": "call_wnnlXwlusLSLygIppk4l5TkD", "name": "transfer_to_parent", "content": ""},
|
|
78
|
+
{"call_id": "call_wnnlXwlusLSLygIppk4l5TkD", "output": "Transferring back to parent agent: ParentAgent", "type": "function_call_output"},
|
|
79
|
+
{"role": "assistant", "content": ""},
|
|
80
|
+
{"arguments": '{"name":"TemperatureAgent"}', "type": "function_call", "function_call_id": "call_S9OlXSk7kEPQJ3HWC3GoK0xE", "name": "transfer_to_agent", "content": ""},
|
|
81
|
+
{"call_id": "call_S9OlXSk7kEPQJ3HWC3GoK0xE", "output": "Transferring to agent: TemperatureAgent", "type": "function_call_output"},
|
|
82
|
+
{"role": "assistant", "content": ""},
|
|
83
|
+
{"arguments": '{"city":"Tokyo"}', "type": "function_call", "function_call_id": "call_gDljMYP187ymVXfKCUdsgjlX", "name": "get_temperature", "content": ""},
|
|
84
|
+
{"call_id": "call_gDljMYP187ymVXfKCUdsgjlX", "output": "The temperature in Tokyo is 25°C.", "type": "function_call_output"},
|
|
85
|
+
{"role": "assistant", "content": ""},
|
|
86
|
+
{"arguments": "{}", "type": "function_call", "function_call_id": "call_bQiSAr8y7u6Q0rJMqUfVE47p", "name": "transfer_to_parent", "content": ""},
|
|
87
|
+
{"call_id": "call_bQiSAr8y7u6Q0rJMqUfVE47p", "output": "Transferring back to parent agent: ParentAgent", "type": "function_call_output"},
|
|
88
|
+
{"role": "assistant", "content": "The weather in Tokyo is sunny, and the temperature is 25°C. If you need further details about Tokyo or want updates for another city, let me know!"},
|
|
89
|
+
]
|
|
90
|
+
# Set the chat history - this should automatically track that we should be on TemperatureAgent
|
|
91
|
+
runner.set_chat_history(chat_history)
|
|
92
|
+
|
|
93
|
+
print(f"After setting chat history, current agent is: {runner.agent.name}")
|
|
94
|
+
print(f"Chat history contains {len(runner.messages)} messages")
|
|
95
|
+
|
|
96
|
+
# Continue the conversation from where we left off
|
|
97
|
+
print("\n--- Continuing conversation ---")
|
|
98
|
+
resp = runner.run([], max_steps=5, includes=["final_message", "tool_call", "tool_call_result"])
|
|
99
|
+
async for message in resp:
|
|
100
|
+
logger.info(message)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
if __name__ == "__main__":
|
|
104
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
简单使用示例:Rich 聊天记录渲染
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from lite_agent import print_chat_history, print_chat_summary
|
|
6
|
+
from lite_agent.types import AgentAssistantMessage, AgentUserMessage
|
|
7
|
+
|
|
8
|
+
# 创建一些示例消息
|
|
9
|
+
messages = [
|
|
10
|
+
AgentUserMessage(role="user", content="你好!"),
|
|
11
|
+
AgentAssistantMessage(role="assistant", content="你好!我是 AI 助手,很高兴为您服务。"),
|
|
12
|
+
{"role": "user", "content": "今天天气怎么样?"},
|
|
13
|
+
{
|
|
14
|
+
"type": "function_call",
|
|
15
|
+
"function_call_id": "call_1",
|
|
16
|
+
"name": "get_weather",
|
|
17
|
+
"arguments": '{"city": "北京"}',
|
|
18
|
+
"content": "",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"type": "function_call_output",
|
|
22
|
+
"call_id": "call_1",
|
|
23
|
+
"output": "北京今天晴朗,温度 20°C",
|
|
24
|
+
},
|
|
25
|
+
{"role": "assistant", "content": "北京今天天气很好,晴朗,温度 20°C。"},
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
# 显示聊天摘要
|
|
29
|
+
print("📊 聊天摘要:")
|
|
30
|
+
print_chat_summary(messages)
|
|
31
|
+
|
|
32
|
+
print("\n" + "=" * 60)
|
|
33
|
+
print("💬 详细聊天记录:")
|
|
34
|
+
print("=" * 60)
|
|
35
|
+
|
|
36
|
+
# 渲染完整聊天记录
|
|
37
|
+
print_chat_history(messages)
|
|
38
|
+
|
|
39
|
+
print("\n🎛️ 其他渲染选项:")
|
|
40
|
+
print_chat_history(
|
|
41
|
+
messages,
|
|
42
|
+
show_timestamps=False,
|
|
43
|
+
show_indices=False,
|
|
44
|
+
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from rich.logging import RichHandler
|
|
5
|
+
|
|
6
|
+
from lite_agent import print_chat_history
|
|
7
|
+
from lite_agent.agent import Agent
|
|
8
|
+
from lite_agent.runner import Runner
|
|
9
|
+
|
|
10
|
+
logging.basicConfig(
|
|
11
|
+
level=logging.WARNING,
|
|
12
|
+
format="%(message)s",
|
|
13
|
+
datefmt="[%X]",
|
|
14
|
+
handlers=[RichHandler(rich_tracebacks=True)],
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger("lite_agent")
|
|
18
|
+
logger.setLevel(logging.DEBUG)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def get_temperature(city: str) -> str:
|
|
22
|
+
"""Get the temperature for a city."""
|
|
23
|
+
return f"The temperature in {city} is 25°C."
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
agent = Agent(
|
|
27
|
+
model="gpt-4.1",
|
|
28
|
+
name="Weather Assistant",
|
|
29
|
+
instructions="You are a helpful weather assistant. Before using tools, briefly explain what you are going to do. Provide friendly and informative responses.",
|
|
30
|
+
tools=[get_temperature],
|
|
31
|
+
completion_condition="call", # Set completion condition to "call"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
async def main():
|
|
36
|
+
runner = Runner(agent)
|
|
37
|
+
resp = runner.run(
|
|
38
|
+
"What is the temperature and whether in New York?",
|
|
39
|
+
includes=["final_message", "usage", "tool_call", "tool_call_result"],
|
|
40
|
+
)
|
|
41
|
+
async for chunk in resp:
|
|
42
|
+
logger.info(chunk)
|
|
43
|
+
print_chat_history(
|
|
44
|
+
runner.messages,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
asyncio.run(main())
|