Initial commit: jaspersoft-agent-learn teaching project
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
# Step 03: 构建简单 Agent
|
||||
|
||||
## 🎯 学习目标
|
||||
|
||||
- 理解什么是 Agent(代理)
|
||||
- 理解 Agent 的核心循环:思考 → 行动 → 观察
|
||||
- 学会构建一个完整的 Agent
|
||||
- 理解 LangGraph 的基本用法
|
||||
|
||||
---
|
||||
|
||||
## 📖 概念讲解
|
||||
|
||||
### 什么是 Agent?
|
||||
|
||||
**Agent = LLM + Tool + Loop**
|
||||
|
||||
```
|
||||
Agent 工作流程:
|
||||
|
||||
┌─────────────────────────────────────┐
|
||||
│ │
|
||||
│ ┌───────────┐ │
|
||||
│ │ 思考 │ ◀────────────────┼── LLM 决定
|
||||
│ └─────┬─────┘ │ 要执行什么
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌───────────┐ ┌─────────┐ │
|
||||
│ │ 行动 │───▶│ 执行工具 │ │
|
||||
│ └───────────┘ └────┬────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────┐ │
|
||||
│ │ 观察结果 │ │
|
||||
│ └────┬────┘ │
|
||||
│ │ │
|
||||
└──────────────────────────┼────────┘
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
继续思考 结束 结束
|
||||
```
|
||||
|
||||
### Agent 的核心循环
|
||||
|
||||
```
|
||||
while True:
|
||||
1. Think(思考):LLM 分析当前状态,决定下一步行动
|
||||
2. Act(行动):执行工具或返回结果
|
||||
3. Observe(观察):获取执行结果,更新状态
|
||||
|
||||
如果决定结束 → break
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💻 代码实现
|
||||
|
||||
请打开 `concept.py` 查看详细代码注释。
|
||||
@@ -0,0 +1,603 @@
|
||||
"""
|
||||
Step 03: 构建简单 Agent
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎓 本节内容:
|
||||
1. 什么是 Agent?(LLM + Tool + Loop)
|
||||
2. Agent 的核心循环:Think → Act → Observe
|
||||
3. 如何构建一个完整的 Agent
|
||||
4. LangGraph 的基本用法
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
"""
|
||||
|
||||
from typing import TypedDict, List, Dict, Any, Literal, Optional
|
||||
from dataclasses import dataclass
|
||||
from abc import ABC, abstractmethod
|
||||
import json
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 第一部分:理解 Agent 的本质
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
"""
|
||||
Agent 的核心公式:
|
||||
|
||||
Agent = LLM + Tool + Loop
|
||||
|
||||
为什么这个公式很重要?
|
||||
|
||||
1. LLM:负责"思考"——理解用户意图,决定下一步行动
|
||||
2. Tool:负责"行动"——执行具体的操作
|
||||
3. Loop:负责"循环"——不断执行直到任务完成
|
||||
|
||||
没有 LLM,Agent 只能机械地执行预设命令
|
||||
没有 Tool,LLM 只能思考不能行动
|
||||
没有 Loop,Agent 只能执行一步
|
||||
|
||||
只有三者结合,才是真正的"智能代理"
|
||||
"""
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 第二部分:定义 Agent State
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
class SimpleAgentState(TypedDict, total=False):
|
||||
"""
|
||||
简单 Agent 的状态
|
||||
|
||||
相比 Step 02 的状态,这个状态更精简,适合教学
|
||||
"""
|
||||
|
||||
# 用户输入
|
||||
user_input: str
|
||||
|
||||
# 对话历史
|
||||
messages: List[dict]
|
||||
"""
|
||||
格式:
|
||||
[
|
||||
{"role": "user", "content": "用户说了什么"},
|
||||
{"role": "assistant", "content": "助手说了什么"},
|
||||
{"role": "system", "content": "系统做了什么"},
|
||||
]
|
||||
"""
|
||||
|
||||
# 当前行动
|
||||
current_action: str
|
||||
"""
|
||||
当前正在执行的动作:
|
||||
- "thinking": LLM 正在思考
|
||||
- "using_tool": 正在使用工具
|
||||
- "finished": 完成
|
||||
"""
|
||||
|
||||
# 工具调用相关
|
||||
tool_calls: List[dict] # 记录所有工具调用
|
||||
last_tool_result: Any # 最后一个工具的执行结果
|
||||
tool_result: Any # 当前工具执行结果
|
||||
|
||||
# 生成结果
|
||||
final_output: str # 最终输出
|
||||
generation: str # 当前正在生成的文本
|
||||
|
||||
# 状态
|
||||
status: str
|
||||
"""
|
||||
状态值:
|
||||
- "input": 等待输入
|
||||
- "thinking": 思考中
|
||||
- "acting": 执行中
|
||||
- "finished": 完成
|
||||
- "error": 错误
|
||||
"""
|
||||
error: str
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 第三部分:定义 Tool 接口
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@dataclass
|
||||
class ToolCall:
|
||||
"""工具调用的数据结构"""
|
||||
name: str # 工具名称
|
||||
arguments: dict # 传递给工具的参数
|
||||
result: Any = None # 工具执行结果
|
||||
error: str = None # 错误信息
|
||||
|
||||
|
||||
class BaseTool(ABC):
|
||||
"""
|
||||
工具基类(简化版,来自 Step 01)
|
||||
"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def name(self) -> str:
|
||||
"""工具名称"""
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def description(self) -> str:
|
||||
"""工具描述"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def execute(self, **kwargs) -> Any:
|
||||
"""执行工具"""
|
||||
pass
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 第四部分:实现具体的 Tool
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
class CalculatorTool(BaseTool):
|
||||
"""计算器工具"""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "calculator"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return "执行数学计算。输入一个数学表达式,返回计算结果。"
|
||||
|
||||
def execute(self, expression: str) -> str:
|
||||
"""执行计算"""
|
||||
try:
|
||||
result = eval(expression, {"__builtins__": {}}, {})
|
||||
return str(result)
|
||||
except Exception as e:
|
||||
return f"计算错误: {e}"
|
||||
|
||||
|
||||
class JRXMLGeneratorTool(BaseTool):
|
||||
"""JRXML 生成工具"""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "jrxml_generator"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return "生成 JasperReports JRXML 报表模板。根据用户需求生成 XML 代码。"
|
||||
|
||||
def execute(self, requirement: str, context: str = "") -> str:
|
||||
"""
|
||||
执行 JRXML 生成
|
||||
|
||||
实际应用中,这里会调用 LLM
|
||||
这里用模拟数据演示
|
||||
"""
|
||||
# 模拟生成
|
||||
template = f'''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
|
||||
name="{requirement}" pageWidth="595" pageHeight="842">
|
||||
<title>{requirement}</title>
|
||||
<queryString>
|
||||
<![CDATA[SELECT * FROM data WHERE 1=1]]>
|
||||
</queryString>
|
||||
<field name="id" class="java.lang.Integer"/>
|
||||
<field name="name" class="java.lang.String"/>
|
||||
<band height="50">
|
||||
<staticText>
|
||||
<reportElement x="0" y="0" width="100" height="20"/>
|
||||
<text>名称</text>
|
||||
</staticText>
|
||||
<textField>
|
||||
<reportElement x="0" y="20" width="100" height="20"/>
|
||||
<textFieldExpression>$F{{name}}</textFieldExpression>
|
||||
</textField>
|
||||
</band>
|
||||
</jasperReport>'''
|
||||
|
||||
return template
|
||||
|
||||
|
||||
class TemplateSearchTool(BaseTool):
|
||||
"""模板搜索工具"""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "template_search"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return "搜索 JRXML 报表模板。在知识库中搜索相关的报表模板作为参考。"
|
||||
|
||||
def execute(self, keyword: str, limit: int = 3) -> str:
|
||||
"""搜索模板"""
|
||||
# 模拟搜索结果
|
||||
results = [
|
||||
f"模板1: 关于 '{keyword}' 的基础报表模板",
|
||||
f"模板2: '{keyword}' 的高级报表模板",
|
||||
f"模板3: '{keyword}' 的数据透视表模板",
|
||||
]
|
||||
return "\n".join(results[:limit])
|
||||
|
||||
|
||||
class JRXMLValidatorTool(BaseTool):
|
||||
"""JRXML 验证工具"""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "jrxml_validator"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return "验证 JRXML 报表模板的正确性。检查 XML 语法和 JasperReports 规范。"
|
||||
|
||||
def execute(self, jrxml: str) -> dict:
|
||||
"""验证 JRXML"""
|
||||
# 模拟验证
|
||||
issues = []
|
||||
|
||||
# 检查基本结构
|
||||
if "<?xml" not in jrxml:
|
||||
issues.append("缺少 XML 声明")
|
||||
|
||||
if "<jasperReport" not in jrxml:
|
||||
issues.append("缺少 <jasperReport> 根元素")
|
||||
|
||||
if "<field" not in jrxml and "<band" not in jrxml:
|
||||
issues.append("报表中没有定义字段或波段")
|
||||
|
||||
return {
|
||||
"valid": len(issues) == 0,
|
||||
"issues": issues
|
||||
}
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 第五部分:构建 Agent 的大脑(LLM 决策)
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
class AgentBrain:
|
||||
"""
|
||||
Agent 的大脑——负责决定下一步做什么
|
||||
|
||||
在真实系统中,这里会调用 LLM
|
||||
这里用规则引擎模拟 LLM 的决策过程
|
||||
|
||||
决策逻辑:
|
||||
1. 如果用户要求生成报表 → 调用 jrxml_generator
|
||||
2. 如果用户要求搜索模板 → 调用 template_search
|
||||
3. 如果用户要求验证 → 调用 jrxml_validator
|
||||
4. 如果用户只是聊天 → 直接回答
|
||||
5. 如果工具执行完成 → 返回结果或继续调用
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# 工具描述(用于告诉 LLM 有哪些工具可用)
|
||||
self.tools = {
|
||||
"calculator": "计算器,执行数学表达式,如 2+3*4",
|
||||
"jrxml_generator": "生成 JasperReports JRXML 报表模板",
|
||||
"template_search": "搜索报表模板",
|
||||
"jrxml_validator": "验证 JRXML 报表的正确性",
|
||||
}
|
||||
|
||||
def decide(self, state: SimpleAgentState) -> dict:
|
||||
"""
|
||||
决定下一步行动
|
||||
|
||||
返回:
|
||||
{
|
||||
"action": "use_tool" | "respond" | "finish",
|
||||
"tool_name": str, # 如果 action == "use_tool"
|
||||
"tool_args": dict, # 如果 action == "use_tool"
|
||||
"response": str, # 如果 action == "respond"
|
||||
}
|
||||
"""
|
||||
user_input = state.get("user_input", "").lower()
|
||||
messages = state.get("messages", [])
|
||||
tool_result = state.get("tool_result")
|
||||
|
||||
# 如果有工具执行结果
|
||||
if tool_result is not None:
|
||||
return {
|
||||
"action": "respond",
|
||||
"response": f"工具执行完成,结果:{tool_result}"
|
||||
}
|
||||
|
||||
# 根据用户输入决定行动
|
||||
if "生成" in user_input or "报表" in user_input:
|
||||
return {
|
||||
"action": "use_tool",
|
||||
"tool_name": "jrxml_generator",
|
||||
"tool_args": {
|
||||
"requirement": state.get("user_input", ""),
|
||||
"context": ""
|
||||
}
|
||||
}
|
||||
|
||||
elif "搜索" in user_input or "模板" in user_input:
|
||||
return {
|
||||
"action": "use_tool",
|
||||
"tool_name": "template_search",
|
||||
"tool_args": {
|
||||
"keyword": user_input.replace("搜索", "").replace("模板", "").strip(),
|
||||
"limit": 3
|
||||
}
|
||||
}
|
||||
|
||||
elif "验证" in user_input and "<" in user_input:
|
||||
return {
|
||||
"action": "use_tool",
|
||||
"tool_name": "jrxml_validator",
|
||||
"tool_args": {
|
||||
"jrxml": user_input
|
||||
}
|
||||
}
|
||||
|
||||
elif any(op in user_input for op in ["计算", "+", "-", "*", "/"]):
|
||||
# 提取表达式
|
||||
import re
|
||||
expr = re.search(r'[\d\+\-\*\/\(\)\.]+', user_input)
|
||||
if expr:
|
||||
return {
|
||||
"action": "use_tool",
|
||||
"tool_name": "calculator",
|
||||
"tool_args": {
|
||||
"expression": expr.group()
|
||||
}
|
||||
}
|
||||
|
||||
else:
|
||||
# 默认:直接回答
|
||||
return {
|
||||
"action": "respond",
|
||||
"response": f"我理解你的需求:{state.get('user_input', '')}。请问具体想做什么?"
|
||||
}
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 第六部分:构建 Agent
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
class SimpleAgent:
|
||||
"""
|
||||
简单 Agent 实现
|
||||
|
||||
这个 Agent 的工作流程:
|
||||
1. 接收用户输入
|
||||
2. LLM(大脑)决定下一步行动
|
||||
3. 执行行动(使用工具或直接回答)
|
||||
4. 返回结果
|
||||
5. 循环直到用户结束
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# 初始化工具
|
||||
self.tools = {
|
||||
"calculator": CalculatorTool(),
|
||||
"jrxml_generator": JRXMLGeneratorTool(),
|
||||
"template_search": TemplateSearchTool(),
|
||||
"jrxml_validator": JRXMLValidatorTool(),
|
||||
}
|
||||
|
||||
# 初始化大脑
|
||||
self.brain = AgentBrain()
|
||||
|
||||
# 初始化状态
|
||||
self.state = SimpleAgentState(
|
||||
messages=[],
|
||||
tool_calls=[],
|
||||
status="input"
|
||||
)
|
||||
|
||||
def reset(self):
|
||||
"""重置 Agent 状态"""
|
||||
self.state = SimpleAgentState(
|
||||
messages=[],
|
||||
tool_calls=[],
|
||||
status="input"
|
||||
)
|
||||
|
||||
def get_available_tools(self) -> list[dict]:
|
||||
"""获取可用工具列表"""
|
||||
return [
|
||||
{"name": tool.name, "description": tool.description}
|
||||
for tool in self.tools.values()
|
||||
]
|
||||
|
||||
def execute_tool(self, tool_name: str, **kwargs) -> Any:
|
||||
"""
|
||||
执行工具
|
||||
|
||||
封装了工具执行的逻辑,包括:
|
||||
- 查找工具
|
||||
- 执行工具
|
||||
- 记录调用
|
||||
- 处理错误
|
||||
"""
|
||||
if tool_name not in self.tools:
|
||||
return {"error": f"工具 '{tool_name}' 不存在"}
|
||||
|
||||
tool = self.tools[tool_name]
|
||||
try:
|
||||
result = tool.execute(**kwargs)
|
||||
|
||||
# 记录工具调用
|
||||
self.state["tool_calls"].append({
|
||||
"tool": tool_name,
|
||||
"args": kwargs,
|
||||
"result": result
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
error_result = {"error": str(e)}
|
||||
self.state["tool_calls"].append({
|
||||
"tool": tool_name,
|
||||
"args": kwargs,
|
||||
"error": str(e)
|
||||
})
|
||||
return error_result
|
||||
|
||||
def process(self, user_input: str) -> str:
|
||||
"""
|
||||
处理用户输入
|
||||
|
||||
这是 Agent 的主入口
|
||||
每次用户输入,调用这个方法来处理
|
||||
"""
|
||||
# 1. 保存用户输入
|
||||
self.state["user_input"] = user_input
|
||||
self.state["messages"].append({
|
||||
"role": "user",
|
||||
"content": user_input
|
||||
})
|
||||
self.state["status"] = "thinking"
|
||||
|
||||
# 2. 大脑决定行动
|
||||
decision = self.brain.decide(self.state)
|
||||
|
||||
# 3. 执行行动
|
||||
if decision["action"] == "use_tool":
|
||||
# 使用工具
|
||||
self.state["status"] = "acting"
|
||||
tool_name = decision["tool_name"]
|
||||
tool_args = decision["tool_args"]
|
||||
|
||||
result = self.execute_tool(tool_name, **tool_args)
|
||||
|
||||
# 保存结果到状态
|
||||
self.state["tool_result"] = result
|
||||
self.state["current_action"] = f"使用了工具: {tool_name}"
|
||||
|
||||
# 再次调用大脑,决定下一步
|
||||
decision = self.brain.decide(self.state)
|
||||
|
||||
if decision["action"] == "respond":
|
||||
response = decision["response"]
|
||||
self.state["messages"].append({
|
||||
"role": "assistant",
|
||||
"content": response
|
||||
})
|
||||
self.state["final_output"] = response
|
||||
self.state["status"] = "finished"
|
||||
return response
|
||||
|
||||
elif decision["action"] == "finish":
|
||||
self.state["status"] = "finished"
|
||||
return self.state.get("final_output", "任务完成")
|
||||
|
||||
# 默认返回当前状态
|
||||
return self.state.get("current_action", "处理中...")
|
||||
|
||||
def get_history(self) -> list[dict]:
|
||||
"""获取对话历史"""
|
||||
return self.state.get("messages", [])
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 第七部分:使用 LangGraph 重构(可选进阶内容)
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
"""
|
||||
LangGraph 是 LangChain 提供的图结构框架
|
||||
|
||||
核心概念:
|
||||
1. StateGraph:状态图
|
||||
2. Node:节点(执行函数)
|
||||
3. Edge:边(状态转换)
|
||||
4. Conditional Edge:条件边(根据状态决定下一步)
|
||||
|
||||
为什么使用 LangGraph?
|
||||
1. 代码结构更清晰
|
||||
2. 内置状态管理
|
||||
3. 支持复杂的条件分支
|
||||
4. 内置循环和回退
|
||||
|
||||
如果你想学习 LangGraph:
|
||||
请参考 jaspersoft 项目中的实际实现:
|
||||
- agent/graph.py:状态图定义
|
||||
- agent/nodes.py:节点实现
|
||||
- agent/state.py:状态定义
|
||||
|
||||
这里的 SimpleAgent 展示的是核心原理
|
||||
LangGraph 只是实现方式之一
|
||||
"""
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 第八部分:演示代码
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
def demo():
|
||||
"""演示简单 Agent 的使用"""
|
||||
print("=" * 60)
|
||||
print("Step 03: 构建简单 Agent - 演示")
|
||||
print("=" * 60)
|
||||
|
||||
# 创建 Agent
|
||||
agent = SimpleAgent()
|
||||
|
||||
print("\n📋 可用工具:")
|
||||
for tool in agent.get_available_tools():
|
||||
print(f" - {tool['name']}: {tool['description']}")
|
||||
|
||||
# 场景 1:生成报表
|
||||
print("\n\n🔄 场景 1: 生成报表")
|
||||
print("-" * 40)
|
||||
print("用户: 生成一个销售报表")
|
||||
|
||||
response = agent.process("生成一个销售报表")
|
||||
print(f"Agent: {response}")
|
||||
|
||||
# 场景 2:搜索模板
|
||||
print("\n\n🔄 场景 2: 搜索模板")
|
||||
print("-" * 40)
|
||||
print("用户: 搜索采购相关的模板")
|
||||
|
||||
response = agent.process("搜索采购相关的模板")
|
||||
print(f"Agent: {response}")
|
||||
|
||||
# 场景 3:计算
|
||||
print("\n\n🔄 场景 3: 数学计算")
|
||||
print("-" * 40)
|
||||
print("用户: 计算 100 + 200 * 3")
|
||||
|
||||
response = agent.process("计算 100 + 200 * 3")
|
||||
print(f"Agent: {response}")
|
||||
|
||||
# 场景 4:多轮对话
|
||||
print("\n\n🔄 场景 4: 多轮对话")
|
||||
print("-" * 40)
|
||||
print("用户: 我想生成一个报表")
|
||||
|
||||
response1 = agent.process("我想生成一个报表")
|
||||
print(f"Agent: {response1}")
|
||||
|
||||
print("用户: 显示月度汇总数据")
|
||||
|
||||
response2 = agent.process("显示月度汇总数据")
|
||||
print(f"Agent: {response2}")
|
||||
|
||||
# 展示对话历史
|
||||
print("\n\n📜 对话历史:")
|
||||
for msg in agent.get_history():
|
||||
print(f" [{msg['role']}]: {msg['content'][:50]}...")
|
||||
|
||||
# 展示工具调用记录
|
||||
print("\n\n🔧 工具调用记录:")
|
||||
for call in agent.state.get("tool_calls", []):
|
||||
if "error" in call:
|
||||
print(f" - {call['tool']}: ❌ {call['error']}")
|
||||
else:
|
||||
result = str(call.get("result", ""))[:30]
|
||||
print(f" - {call['tool']}: ✓ {result}...")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("✅ 演示完成")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo()
|
||||
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
Step 03: 构建简单 Agent - 主程序
|
||||
|
||||
运行方式:
|
||||
cd step_03_simple_agent
|
||||
python main.py
|
||||
"""
|
||||
|
||||
from concept import SimpleAgent
|
||||
|
||||
|
||||
def main():
|
||||
"""交互式演示 Agent"""
|
||||
|
||||
print("=" * 70)
|
||||
print(" Step 03: 构建简单 Agent - 交互式演示")
|
||||
print("=" * 70)
|
||||
print("""
|
||||
欢迎使用 Jaspersoft 报表助手!
|
||||
|
||||
我可以帮你:
|
||||
- 生成 JRXML 报表模板
|
||||
- 搜索相关报表模板
|
||||
- 验证报表代码
|
||||
- 执行数学计算
|
||||
|
||||
输入 'quit' 或 '退出' 结束对话
|
||||
""")
|
||||
|
||||
# 创建 Agent
|
||||
agent = SimpleAgent()
|
||||
|
||||
# 显示可用工具
|
||||
print("\n📋 我的能力:")
|
||||
for tool in agent.get_available_tools():
|
||||
print(f" • {tool['name']}: {tool['description']}")
|
||||
|
||||
print("\n" + "-" * 70)
|
||||
print("开始对话:")
|
||||
print("-" * 70)
|
||||
|
||||
# 交互式循环
|
||||
while True:
|
||||
try:
|
||||
user_input = input("\n👤 你: ").strip()
|
||||
|
||||
if not user_input:
|
||||
continue
|
||||
|
||||
if user_input.lower() in ["quit", "退出", "exit", "q"]:
|
||||
print("\n👋 再见!")
|
||||
break
|
||||
|
||||
# 处理输入
|
||||
response = agent.process(user_input)
|
||||
|
||||
# 显示响应
|
||||
print(f"\n🤖 Agent: {response}")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n👋 再见!")
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"\n❌ 出错了: {e}")
|
||||
|
||||
# 显示会话统计
|
||||
print("\n\n" + "=" * 70)
|
||||
print("📊 会话统计")
|
||||
print("=" * 70)
|
||||
print(f" 对话轮次: {len(agent.get_history()) // 2}")
|
||||
print(f" 工具调用: {len(agent.state.get('tool_calls', []))}")
|
||||
print("\n💡 继续学习:")
|
||||
print(" Step 04: 添加 Memory - 记忆系统")
|
||||
print(" Step 05: 添加 RAG - 知识检索")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user