fix: 修复 NameError/状态污染/类型标注/统计; 补全练习与 main; 新增 config/.gitignore/requirements; 文档统一

This commit is contained in:
agent
2026-06-02 13:44:46 +08:00
parent ef876a22d1
commit 908431e25f
23 changed files with 919 additions and 77 deletions
+16 -18
View File
@@ -200,30 +200,28 @@ class MultiAgentSystem:
def __init__(self):
# 注册各个 Agent
self.agents = {
"generator": GeneratorAgent(),
"validator": ValidatorAgent(),
"searcher": SearcherAgent(),
}
# 协调器
self.orchestrator = Orchestrator(self.agents)
self.agents: dict[str, Agent] = {}
def process(self, requirement: str) -> str:
"""协调多个 Agent 处理请求"""
def register(self, agent: Agent) -> None:
self.agents[agent.name] = agent
def process(self, requirement: str):
# 1. 搜索相关知识
context = self.agents["searcher"].search(requirement)
searcher = self.agents.get("searcher")
context = searcher.process(requirement) if searcher else ""
# 2. 生成(可能需要多轮)
for attempt in range(3):
draft = self.agents["generator"].generate(requirement, context)
generator = self.agents.get("generator")
draft = generator.process({"requirement": requirement, "context": context}) if generator else requirement
# 3. 验证
validation = self.agents["validator"].validate(draft)
# 3. 验证
validator = self.agents.get("validator")
if validator:
validation = validator.process(draft)
if not validation.get("passed", True):
return {"error": "验证失败", "validation": validation}
if validation["passed"]:
return validation["result"]
return "处理失败"
return draft
```
---
+3 -3
View File
@@ -4,6 +4,9 @@ Step 05-07: RAG / Self-Correction / Multi-Agent
进阶内容代码示例
"""
from dataclasses import dataclass
from typing import Any, Dict, List
# ═══════════════════════════════════════════════════════════════════════════════════════
# RAG 实现
# ═══════════════════════════════════════════════════════════════════════════════════════
@@ -152,9 +155,6 @@ class SelfCorrectingAgent:
# Multi-Agent 实现
# ═══════════════════════════════════════════════════════════════════════════════════════
from dataclasses import dataclass, field
from typing import Dict, List, Callable
@dataclass
class AgentMessage:
+88
View File
@@ -0,0 +1,88 @@
"""
Step 05-07 练习题:进阶能力
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎯 练习目标:
1. 体验 RAG 的检索质量
2. 写一个 Self-Correction 闭环
3. 设计多 Agent 编排
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
"""
# ═══════════════════════════════════════════════════════════════════════════════
# 练习 1:提升 SimpleRAG 的检索质量
# ═══════════════════════════════════════════════════════════════════════════════
"""
任务:
SimpleRAG.retrieve() 当前用 Jaccard 相似度 + 简单分词。
改造为:把分词改成 "中文按字 + 英文按词 + 大小写归一化" 后再算 Jaccard。
要求:
1. 复用 SimpleRAG 类,不要重写
2. 实现 upgrade_retrieve(rag) 替换 rag.retrieve 方法
3. 用一个含中英文的小语料验证
提示:
- re.findall(r'[\u4e00-\u9fff]|[A-Za-z]+', text.lower())
"""
# ═══════════════════════════════════════════════════════════════════════════════
# 练习 2:实现 Self-Correction 主循环
# ═══════════════════════════════════════════════════════════════════════════════
"""
任务:
SelfCorrectingAgent 在 concept.py 中是骨架。请补全它的 run() 方法:
def run(self, requirement: str, generate_fn, validate_fn, max_retries=3):
for attempt in range(max_retries):
output = generate_fn(requirement, attempt, feedback)
validation = validate_fn(output)
if validation.passed:
return output
feedback = self.build_feedback(validation)
return output
要求:
1. 第一次 attempt 不带 feedback
2. 每次失败用 build_feedback 拼出新的 feedback
3. 超过 max_retries 返回最后一次 output(不要抛异常)
"""
# ═══════════════════════════════════════════════════════════════════════════════
# 练习 3:给 MultiAgentSystem 加超时与失败回退
# ═══════════════════════════════════════════════════════════════════════════════
"""
任务:
MultiAgentSystem.process() 是顺序调用 searcher -> generator -> validator。
任何一个 Agent 抛异常都让整个流程崩。
要求:
1. 在 process() 外层包 try/except,失败时返回 {"error": str(e)}
2. 给每个 Agent 加 timeout_seconds 参数(用 time.monotonic
3. 验证:故意让 validator 抛异常,确认 process() 不会让程序崩溃
提示:
- time.monotonic() 不受系统时间影响
- 简单演示里可以靠 sleep + 时间比较实现超时
"""
def test_exercises():
from step_05_07_advanced.concept import SimpleRAG
rag = SimpleRAG()
rag.add_document("JasperReports 是一个 Java 报表库", {"source": "doc1"})
rag.add_document("JRXML 是 JasperReports 模板格式", {"source": "doc2"})
print(rag.retrieve("JasperReports"))
if __name__ == "__main__":
test_exercises()
+169
View File
@@ -0,0 +1,169 @@
"""
Step 05-07 练习题答案
⚠️ 先自己思考,再看答案!
⚠️ 答案不是唯一的,这里只是其中一种实现
"""
import re
import time
from typing import Callable
from step_05_07_advanced.concept import (
Agent,
MultiAgentSystem,
SelfCorrectingAgent,
SimpleRAG,
ValidationResult,
)
# ═══════════════════════════════════════════════════════════════════════════════
# 练习 1 答案:升级 SimpleRAG 分词
# ═══════════════════════════════════════════════════════════════════════════════
_TOKEN_PATTERN = re.compile(r"[\u4e00-\u9fff]|[A-Za-z]+")
def _tokenize(text: str) -> set[str]:
return set(_TOKEN_PATTERN.findall(text.lower()))
def upgrade_retrieve(rag: SimpleRAG) -> None:
def retrieve(self, query: str, top_k: int = 3):
q_words = _tokenize(query)
scored = []
for doc in self.documents:
d_words = _tokenize(doc["text"])
union = q_words | d_words
if not union:
continue
score = len(q_words & d_words) / len(union)
scored.append((score, doc))
scored.sort(key=lambda x: x[0], reverse=True)
return [doc for _, doc in scored[:top_k]]
SimpleRAG.retrieve = retrieve
# ═══════════════════════════════════════════════════════════════════════════════
# 练习 2 答案:Self-Correction 主循环
# ═══════════════════════════════════════════════════════════════════════════════
def install_self_correction_run() -> None:
def run(
self: SelfCorrectingAgent,
requirement: str,
generate_fn: Callable,
validate_fn: Callable,
max_retries: int = 3,
):
feedback = None
output = None
for attempt in range(max_retries):
output = generate_fn(requirement, attempt, feedback)
validation: ValidationResult = validate_fn(output)
if validation.passed:
return output
feedback = self.build_feedback(validation, output, attempt)
return output
SelfCorrectingAgent.run = run
# ═══════════════════════════════════════════════════════════════════════════════
# 练习 3 答案:MultiAgentSystem 超时与回退
# ═══════════════════════════════════════════════════════════════════════════════
def install_safe_process() -> None:
def process(self: MultiAgentSystem, requirement: str, timeout_seconds: float = 2.0):
try:
return self._timed_process(requirement, timeout_seconds)
except Exception as e:
return {"error": str(e)}
def _timed_process(self, requirement: str, timeout_seconds: float):
deadline = time.monotonic() + timeout_seconds
searcher = self.agents.get("searcher")
if searcher:
self._check_timeout(deadline)
context = searcher.process(requirement)
else:
context = ""
generator = self.agents.get("generator")
if generator:
self._check_timeout(deadline)
result = generator.process({"requirement": requirement, "context": context})
else:
result = requirement
validator = self.agents.get("validator")
if validator:
self._check_timeout(deadline)
validation = validator.process(result)
if not validation.get("passed", True):
return {"error": "验证失败", "validation": validation}
return result
def _check_timeout(self, deadline: float):
if time.monotonic() > deadline:
raise TimeoutError("Multi-Agent 处理超时")
MultiAgentSystem.process = process
MultiAgentSystem._timed_process = _timed_process
MultiAgentSystem._check_timeout = _check_timeout
# ═══════════════════════════════════════════════════════════════════════════════
# 测试
# ═══════════════════════════════════════════════════════════════════════════════
def test_answers():
print("\n" + "=" * 60)
print("Step 05-07 练习答案测试")
print("=" * 60)
print("\n📝 练习 1: 升级 SimpleRAG")
rag = SimpleRAG()
rag.add_document("JasperReports 是一个 Java 报表库", {"source": "doc1"})
rag.add_document("JRXML 是 JasperReports 模板格式", {"source": "doc2"})
upgrade_retrieve(rag)
hits = rag.retrieve("JasperReports")
print(f" 检索命中 {len(hits)}")
for d in hits:
print(f" - {d['text']}")
print("\n📝 练习 2: Self-Correction run()")
install_self_correction_run()
sc = SelfCorrectingAgent()
def fake_generate(req, attempt, feedback):
# 第一次失败,第二次成功
return f"v{attempt}"
def fake_validate(output):
passed = output == "v1"
return ValidationResult(passed=passed, score=1.0 if passed else 0.2, issues=[] if passed else ["不达标"])
final = sc.run("测试", fake_generate, fake_validate, max_retries=3)
print(f" 最终结果 = {final}")
print("\n📝 练习 3: Multi-Agent 安全 process()")
install_safe_process()
class BoomValidator(Agent):
name = "validator"
def process(self, input_data):
raise RuntimeError("故意崩溃")
sys = MultiAgentSystem()
sys.agents["validator"] = BoomValidator()
res = sys.process("任何需求")
print(f" 异常被吞掉: {res}")
if __name__ == "__main__":
test_answers()
+17
View File
@@ -0,0 +1,17 @@
"""
Step 05-07: RAG / Self-Correction / Multi-Agent 主程序
运行方式:
cd step_05_07_advanced
python main.py
"""
from concept import demo
def main():
demo()
if __name__ == "__main__":
main()