265 lines
9.5 KiB
Python
265 lines
9.5 KiB
Python
"""
|
||
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()
|