Initial commit: jaspersoft-agent-learn teaching project

This commit is contained in:
zy187
2026-05-29 23:22:18 +08:00
commit 05bb511aab
20 changed files with 4476 additions and 0 deletions
+264
View File
@@ -0,0 +1,264 @@
"""
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()