Files
jaspersoft-agent-learn/step_01_tools/exercise_answer.py
T

265 lines
9.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Step 01 练习题答案
⚠️ 先自己思考,再看答案!
⚠️ 答案不是唯一的,这里只是其中一种实现
"""
from step_01_tools.concept import BaseTool, ToolResult
# ═══════════════════════════════════════════════════════════════════════════════
# 练习 1 答案:TextProcessorTool
# ═══════════════════════════════════════════════════════════════════════════════
class TextProcessorTool(BaseTool):
"""文本处理工具"""
@property
def name(self) -> str:
return "text_processor"
@property
def description(self) -> str:
return "文本处理工具,统计文本的各种特征"
def execute(self, **kwargs) -> ToolResult:
"""处理文本请求"""
text = kwargs.get("text", "")
operation = kwargs.get("operation", "word_count")
if not text:
return ToolResult(success=False, error="文本不能为空")
if operation == "word_count":
result = self.word_count(text)
elif operation == "character_count":
result = self.character_count(text)
elif operation == "sentence_count":
result = self.sentence_count(text)
else:
return ToolResult(success=False, error=f"不支持的操作: {operation}")
return ToolResult(success=True, result=result)
def word_count(self, text: str) -> int:
"""统计单词数量"""
# 按空格分割,过滤空字符串
words = [w for w in text.split() if w.strip()]
return len(words)
def character_count(self, text: str) -> int:
"""统计字符数量(不包括空格)"""
# 去除所有空白字符后统计
return len(text.replace(" ", "").replace("\n", "").replace("\t", ""))
def sentence_count(self, text: str) -> int:
"""统计句子数量"""
# 按常见句子结束符分割
import re
sentences = re.split(r'[.!?]+', text)
# 过滤空字符串
sentences = [s for s in sentences if s.strip()]
return len(sentences)
# ═══════════════════════════════════════════════════════════════════════════════
# 练习 2 答案:EmailTool
# ═══════════════════════════════════════════════════════════════════════════════
class EmailTool(BaseTool):
"""邮件处理工具"""
@property
def name(self) -> str:
return "email"
@property
def description(self) -> str:
return """
邮件处理工具,用于发送和搜索邮件。
支持的操作:
send_email: 发送邮件
- to: 收件人邮箱
- subject: 邮件主题
- body: 邮件正文
返回: {"success": true, "message_id": "xxx"}
search_emails: 搜索邮件
- keyword: 搜索关键词
- limit: 返回数量(默认10
返回: [{"from": "...", "subject": "...", "date": "..."}, ...]
get_unread_count: 获取未读邮件数量
无需参数
返回: {"count": 5}
"""
def execute(self, **kwargs) -> ToolResult:
"""执行邮件操作"""
operation = kwargs.get("operation", "get_unread_count")
if operation == "send_email":
return self.send_email(
to=kwargs.get("to", ""),
subject=kwargs.get("subject", ""),
body=kwargs.get("body", "")
)
elif operation == "search_emails":
return self.search_emails(
keyword=kwargs.get("keyword", ""),
limit=kwargs.get("limit", 10)
)
elif operation == "get_unread_count":
return self.get_unread_count()
else:
return ToolResult(success=False, error=f"不支持的操作: {operation}")
def send_email(self, to: str, subject: str, body: str) -> ToolResult:
"""发送邮件"""
if not to:
return ToolResult(success=False, error="收件人不能为空")
if not subject:
return ToolResult(success=False, error="主题不能为空")
# 实际场景:调用邮件发送 API
# 这里用模拟数据
message_id = f"msg_{hash(to + subject) % 100000}"
return ToolResult(
success=True,
result={
"success": True,
"message_id": message_id,
"to": to,
"subject": subject
}
)
def search_emails(self, keyword: str, limit: int) -> ToolResult:
"""搜索邮件"""
if not keyword:
return ToolResult(success=False, error="搜索关键词不能为空")
# 模拟搜索结果
mock_results = [
{
"from": "boss@company.com",
"subject": f"关于项目的{keyword}",
"date": "2024-01-15",
"snippet": "..."
},
{
"from": "colleague@company.com",
"subject": f"回复: {keyword}的讨论",
"date": "2024-01-14",
"snippet": "..."
},
]
return ToolResult(
success=True,
result=mock_results[:limit]
)
def get_unread_count(self) -> ToolResult:
"""获取未读邮件数量"""
# 实际场景:调用邮件 API 获取未读数
return ToolResult(success=True, result={"count": 5})
# ═══════════════════════════════════════════════════════════════════════════════
# 练习 3 答案:给 ToolRegistry 添加 search_tools
# ═══════════════════════════════════════════════════════════════════════════════
from step_01_tools.concept import ToolRegistry, CalculatorTool, SearchTool
def add_search_to_registry():
"""
演示如何给 ToolRegistry 添加 search_tools 方法
"""
# 方法1:在原类上添加(直接修改原类)
def search_tools_original(self, keyword: str) -> list[dict]:
"""根据关键词搜索工具"""
keyword_lower = keyword.lower()
results = []
for tool in self._tools.values():
# 检查名称或描述中是否包含关键词
name_match = keyword_lower in tool.name.lower()
desc_match = keyword_lower in tool.description.lower()
if name_match or desc_match:
results.append(tool.to_dict())
return results
# 给 ToolRegistry 添加方法
ToolRegistry.search_tools = search_tools_original
# 测试
registry = ToolRegistry()
registry.register(CalculatorTool())
registry.register(SearchTool())
registry.register(TextProcessorTool())
print("搜索 'text':")
for t in registry.search_tools("text"):
print(f" - {t['name']}")
print("搜索 'calculate':")
for t in registry.search_tools("calculate"):
print(f" - {t['name']}")
print("搜索 'web':")
for t in registry.search_tools("web"):
print(f" - {t['name']}")
# ═══════════════════════════════════════════════════════════════════════════════
# 测试运行
# ═══════════════════════════════════════════════════════════════════════════════
def test_answers():
"""测试答案"""
print("\n" + "=" * 60)
print("测试练习答案")
print("=" * 60)
# 测试练习 1
print("\n📝 练习 1: TextProcessorTool")
tool = TextProcessorTool()
test_text = "Hello, world! This is a test. How are you?"
print(f"测试文本: {test_text}")
print(f"单词数量: {tool.word_count(test_text)}") # 应该是 9
print(f"字符数量: {tool.character_count(test_text)}") # 应该是 38
print(f"句子数量: {tool.sentence_count(test_text)}") # 应该是 3
# 测试练习 2
print("\n📝 练习 2: EmailTool")
email_tool = EmailTool()
print("\n 发送邮件:")
result = email_tool.send_email("test@example.com", "测试", "这是一封测试邮件")
print(f" 结果: {result.result}")
print("\n 搜索邮件:")
result = email_tool.search_emails("项目", limit=5)
print(f" 结果: {result.result}")
print("\n 未读邮件数:")
result = email_tool.get_unread_count()
print(f" 结果: {result.result}")
# 测试练习 3
print("\n📝 练习 3: search_tools")
add_search_to_registry()
if __name__ == "__main__":
test_answers()