ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s

This commit is contained in:
2026-08-20 13:12:50 +00:00
commit b119135836
10275 changed files with 3284984 additions and 0 deletions
@@ -0,0 +1,110 @@
import os
import sys
from pathlib import Path
import unittest
# Add the project root to Python path
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))
from aworld.config.conf import AgentConfig, ModelConfig, ContextRuleConfig, OptimizationConfig, LlmCompressionConfig
from aworld.core.context.processor import CompressionResult, CompressionType
from aworld.core.context.processor.llm_compressor import LLMCompressor
from aworld.core.context.processor.prompt_processor import PromptProcessor
class TestPromptCompressor(unittest.TestCase):
"""Test cases for PromptCompressor.compress_batch function"""
def test_compress_batch_basic(self):
compressor = LLMCompressor(
llm_config=ModelConfig(
llm_model_name=os.environ["LLM_MODEL_NAME"],
llm_base_url=os.environ["LLM_BASE_URL"],
llm_api_key=os.environ["LLM_API_KEY"],
)
)
# Test data
contents = [
"[SYSTEM]You are a helpful assistant.\n[USER]This is the first long text content that needs compression. This is the first long text content that needs compression.",
]
# Execute compress_batch
results = compressor.compress_batch(contents)
# Assertions
for result in results:
self.assertIsInstance(result, CompressionResult)
self.assertEqual(result.compression_type, CompressionType.LLM_BASED)
self.assertTrue(
'This is the first long text content that needs compression. This is the first long text content that needs compression.' not in result.compressed_content)
def test_compress_messages(self):
"""Test compress_messages function from PromptProcessor"""
# Create context rule with compression enabled
context_rule = ContextRuleConfig(
optimization_config=OptimizationConfig(
enabled=True,
max_token_budget_ratio=0.8
),
llm_compression_config=LlmCompressionConfig(
enabled=True,
trigger_compress_token_length=10, # Low threshold to trigger compression
compress_model=ModelConfig(
llm_model_name=os.environ["LLM_MODEL_NAME"],
llm_base_url=os.environ["LLM_BASE_URL"],
llm_api_key=os.environ["LLM_API_KEY"],
)
)
)
# Create prompt processor with context_rule and model_config
processor = PromptProcessor(context_rule=context_rule, model_config=ModelConfig(
llm_model_name=os.environ["LLM_MODEL_NAME"],
llm_base_url=os.environ["LLM_BASE_URL"],
llm_api_key=os.environ["LLM_API_KEY"],
))
# Test messages with repeated content that needs compression
messages = [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "This is the first long text content that needs compression. This is the first long text content that needs compression."
},
{
"role": "assistant",
"content": "I understand you want me to help with compression."
}
]
# Execute compress_messages
compressed_messages = processor.compress_messages(messages)
# Assertions
self.assertIsInstance(compressed_messages, list)
self.assertEqual(len(compressed_messages), len(messages))
# Find the user message and verify it was processed
user_message = None
for msg in compressed_messages:
if msg.get("role") == "user":
user_message = msg
break
self.assertIsNotNone(user_message)
# The original repeated text should be compressed
original_content = "This is the first long text content that needs compression. This is the first long text content that needs compression."
self.assertNotEqual(user_message["content"], original_content)
# The compressed content should be shorter than original
self.assertLess(len(user_message["content"]), len(original_content))
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,170 @@
import asyncio
import os
import sys
from pathlib import Path
import unittest
# Add the project root to Python path
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))
from aworld.core.context.session import Session
from aworld.core.agent.swarm import Swarm
from tests.base_test import assertEqual, assertIn, assertIsInstance, assertIsNotNone, assertTrue, run_multi_agent_as_team, run_task
from aworld.runners.hook.hook_factory import HookFactory
from aworld.core.context.base import Context
from aworld.config.conf import AgentConfig, ContextRuleConfig, ModelConfig, OptimizationConfig, LlmCompressionConfig
from aworld.agents.llm_agent import Agent
from aworld.core.task import Task
from tests.base_test import init_agent, run_agent, run_multi_agent_as_team
class TestContextManagement(unittest.TestCase):
# def test_save_and_reload(self):
# context = Context()
# context.context_info.set("hello", "world")
# task = Task(input="""What is an agent.""",
# swarm=Swarm(init_agent("1"), max_steps=1), context=context)
# task.session_id = "1"
# context.session = Session(session_id="1")
# context.set_task(task)
# context_manager = ContextManager()
# checkpoint = asyncio.run(context_manager.save(context))
# session_id = context.session_id
# context = asyncio.run(context_manager.reload(session_id))
# assertEqual(context.context_info.get("hello"), "world")
def test_default_context_configuration(self):
mock_agent = init_agent("1")
response = run_agent(
input="""What is an agent. describe within 20 words""", agent=mock_agent)
assertIsNotNone(response.answer)
assertEqual(
mock_agent.conf.llm_config.llm_model_name, os.environ["LLM_MODEL_NAME"])
# Test default context rule behavior
assertIsNotNone(mock_agent.context_rule)
assertIsNotNone(
mock_agent.context_rule.optimization_config)
def test_custom_context_configuration(self):
"""Test custom context configuration (README Configuration example)"""
# Create custom context rules
mock_agent = init_agent(context_rule=ContextRuleConfig(
optimization_config=OptimizationConfig(
enabled=True,
max_token_budget_ratio=0.00015
),
llm_compression_config=LlmCompressionConfig(
enabled=True,
trigger_compress_token_length=100,
compress_model=ModelConfig(
llm_model_name=os.environ["LLM_MODEL_NAME"],
llm_base_url=os.environ["LLM_BASE_URL"],
llm_api_key=os.environ["LLM_API_KEY"],
)
)
))
response = run_agent(
input="""describe What is an agent in details""", agent=mock_agent)
assertIsNotNone(response.answer)
# Test configuration values
assertTrue(
mock_agent.context_rule.optimization_config.enabled)
assertTrue(
mock_agent.context_rule.llm_compression_config.enabled)
def test_multi_agent_state_trace(self):
class StateModifyAgent(Agent):
async def async_policy(self, observation, info=None, **kwargs):
result = await super().async_policy(observation, info, **kwargs)
self.context.context_info.set('policy_executed', True)
return result
class StateTrackingAgent(Agent):
async def async_policy(self, observation, info=None, **kwargs):
result = await super().async_policy(observation, info, **kwargs)
assert self.context.context_info.get('policy_executed', True)
return result
# Create custom agent instance
custom_agent = StateModifyAgent(
conf=AgentConfig(
llm_model_name=os.environ["LLM_MODEL_NAME"],
llm_base_url=os.environ["LLM_BASE_URL"],
llm_api_key=os.environ["LLM_API_KEY"]
),
name="state_modify_agent",
system_prompt="You are a Python expert who provides detailed and practical answers.",
agent_prompt="You are a Python expert who provides detailed and practical answers.",
)
# Create a second agent for multi-agent testing
second_agent = StateTrackingAgent(
conf=AgentConfig(
llm_model_name=os.environ["LLM_MODEL_NAME"],
llm_base_url=os.environ["LLM_BASE_URL"],
llm_api_key=os.environ["LLM_API_KEY"]
),
name="state_tracking_agent",
system_prompt="You are a helpful assistant.",
agent_prompt="You are a helpful assistant.",
)
response = run_multi_agent_as_team(
input="What is an agent. describe within 20 words",
agent1=custom_agent,
agent2=second_agent
)
assertIsNotNone(response.answer)
# Verify state changes after execution
assertTrue(custom_agent.context.context_info.get('policy_executed', True))
def test_multi_task_state_trace(self):
context = Context()
task = Task(input="What is an agent.", context=context)
new_context = task.context.deep_copy()
new_context.context_info.update({"hello": "world"})
run_task(context=new_context, agent=init_agent("1"))
assertEqual(new_context.context_info.get("hello"), "world")
task.context.merge_context(new_context)
assertEqual(task.context.context_info.get("hello"), "world")
def test_hook_registration(self):
from tests.runners.hook.llm_hook import TestPreLLMHook, TestPostLLMHook
"""Test hook registration and retrieval"""
# Test that hooks are registered in _cls attribute
assertIn("TestPreLLMHook", HookFactory._cls)
assertIn("TestPostLLMHook", HookFactory._cls)
# Test hook creation using __call__ method
pre_hook = HookFactory("TestPreLLMHook")
post_hook = HookFactory("TestPostLLMHook")
assertIsInstance(pre_hook, TestPreLLMHook)
assertIsInstance(post_hook, TestPostLLMHook)
def test_hook_execution(self):
mock_agent = init_agent("1")
response = run_agent(
input="""What is an agent. describe within 20 words""", agent=mock_agent)
assertIsNotNone(response.answer)
def test_task_context_transfer(self):
mock_agent = init_agent("1")
context = Context()
context.context_info.update({"task": "What is an agent."})
run_task(context=context, agent=mock_agent)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,125 @@
# Add the project root to Python path
from pathlib import Path
import sys
import unittest
project_root = Path(__file__).parent.parent.parent
print(project_root)
sys.path.insert(0, str(project_root))
from aworld.agents.llm_agent import Agent
from tests.base_test import assertEqual, init_agent, run_agent, run_task
from aworld.core.context.base import Context
from aworld.core.context.prompts.dynamic_variables import create_simple_field_getter, format_ordered_dict_json, \
get_field_values_from_list, get_value_by_path
from aworld.core.context.prompts.string_prompt_template import StringPromptTemplate
class TestPromptTemplate(unittest.TestCase):
def test_dynamic_variables(self):
context = Context()
context.context_info.update({"task": "chat"})
# Test dot separator
value_dot = get_value_by_path(context, "context_info.task")
assert "chat" == value_dot
# Test slash separator
value_slash = get_value_by_path(context, "context_info/task")
assert "chat" == value_slash
def test_formatted_field_getter(self):
context = Context()
value = {"steps": [1, 2, 3]}
context.trajectories.update(value)
getter = create_simple_field_getter(field_path="trajectories", default="default_value")
result = getter(context=context)
assert "steps" in value
# test default format function
assert "OrderedDict" not in result
# Test formatted field getter with processor
getter = create_simple_field_getter(field_path="trajectories", default="default_value",
processor=format_ordered_dict_json)
result = getter(context=context)
assert "steps" in result
def test_multiple_field_getters(self):
context = Context()
context.context_info.update({"task": "chat"})
context.trajectories.update({"steps": [1, 2, 3]})
field_paths = ["context_info.task", "trajectories.steps"]
result = get_field_values_from_list(context=context, field_paths=field_paths)
assert result["context_info_task"] == "chat"
assert result["trajectories_steps"] == "[1, 2, 3]"
def test_string_prompt_template(self):
# Use proper dot notation for nested field access
template = StringPromptTemplate.from_template(
"Hello {{name}}, welcome to {{place}}! Task: {{task}} Age: {{age}}",
partial_variables={"age": "1"})
assert "name" in template.input_variables
assert "place" in template.input_variables
assert "task" in template.input_variables
context = Context()
context.context_info.update({"task": "chat"})
# Pass task as a direct parameter since template expects it
result = template.format(context=context, name="Alice", place="AWorld", task="chat")
assert result == "Hello Alice, welcome to AWorld! Task: chat Age: 1"
def test_enhanced_field_values_basic(self):
context = Context()
context.context_info.update({"task": "chat"})
# Test retrieving both time variables and context fields
result = get_field_values_from_list(
context=context,
field_paths=["current_time", "context_info.task"],
default="not_found"
)
# Verify context field retrieved
assert result["context_info_task"] == "chat"
# Verify time variable retrieved (should be in HH:MM:SS format)
assert ":" in result["current_time"]
assert len(result["current_time"].split(":")) == 3
def test_undefined_system_prompt_template(self):
agent = init_agent()
agent._log_messages = lambda messages: assertEqual(messages[0]['content'], "You are a helpful assistant.")
result = run_task(
input="What is the weather in Beijing?",
agent=agent
)
assert result is not None
def test_custom_system_prompt_template(self):
context = Context()
context.context_info.set("name", "Qwen")
context.context_info.set("plan", [{"input": "query weather in Beijing"}])
system_prompt_template = StringPromptTemplate.from_template(
"Hello {{context_info.name}}, you are a {{role}}, {{context_info.plan}}",
partial_variables={"role": "assistant", "context_info.plan": lambda ob: "please " + ob[0]['input']})
agent = init_agent(
system_prompt_template=system_prompt_template,
)
agent._log_messages = lambda messages: assertEqual(messages[0]['content'], "Hello Qwen, you are a assistant, please query weather in Beijing")
result = run_task(
input="What is the weather in Beijing?",
agent=agent,
context=context
)
assert result is not None
if __name__ == "__main__":
unittest.main()