1. 构建第一个对话式Agent

构建第一个对话式Agent 学习卡片

任务目标

构建一个最小可运行的对话式Agent,能够识别用户问候并基于预置知识回答基本问题。本案例采用规则+本地知识库方案,不依赖外部LLM API,确保可独立复现运行。

实现方案

Agent核心由三部分组成:意图识别器(基于关键词规则)、知识库(预置问答对)、对话管理器(维护会话状态并生成回复)。当用户输入包含问候关键词时触发问候响应;否则在知识库中检索匹配答案;若均未命中则返回兜底话术。

完整代码

import re
import json
from typing import Dict, List, Tuple

class RuleAgent:
    """基于规则与本地知识库的对话Agent"""
    
    def __init__(self, knowledge_base: Dict[str, str]):
        self.knowledge_base = knowledge_base
        self.greeting_patterns = [
            r"^(你好|您好|hi|hello|hey|在吗|早上好|下午好|晚上好)\s*[!!。.]*$",
            r"^(嗨|哈喽|喂)\s*[!!。.]*$"
        ]
        self.fallback_response = "抱歉,我还没学会回答这个问题。你可以试试问我'你好',或者询问'你是谁'、'你能做什么'。"
        self.session_history: List[Tuple[str, str]] = []
    
    def _match_greeting(self, user_input: str) -> bool:
        """检测是否为纯问候语句"""
        text = user_input.strip().lower()
        return any(re.match(pattern, text) for pattern in self.greeting_patterns)
    
    def _match_knowledge(self, user_input: str) -> str | None:
        """在知识库中查找最匹配的答案"""
        text = user_input.strip().lower()
        # 先尝试精确匹配
        for question, answer in self.knowledge_base.items():
            if question.lower() in text or text in question.lower():
                return answer
        
        # 基于关键词的模糊匹配(取最长包含关系)
        best_match = None
        best_len = 0
        for question in self.knowledge_base:
            q_words = set(re.findall(r"[\u4e00-\u9fa5]+|[a-zA-Z]+", question.lower()))
            if not q_words:
                continue
            matched = sum(1 for w in q_words if w in text)
            if matched > 0 and matched / len(q_words) > 0.5 and len(question) > best_len:
                best_match = question
                best_len = len(question)
        
        return self.knowledge_base.get(best_match) if best_match else None
    
    def respond(self, user_input: str) -> str:
        """生成回复并记录会话历史"""
        if not user_input or not user_input.strip():
            reply = "请说点什么吧。"
        elif self._match_greeting(user_input):
            reply = "你好!我是基于规则的对话Agent。你可以问我一些基本问题,比如'你是谁'或'你能做什么'。"
        else:
            reply = self._match_knowledge(user_input) or self.fallback_response
        
        self.session_history.append((user_input, reply))
        return reply
    
    def get_history(self) -> List[Tuple[str, str]]:
        """返回会话历史"""
        return self.session_history.copy()

# ===== 初始化知识库 =====
knowledge = {
    "你是谁": "我是一个基于规则的对话Agent,通过关键词匹配和预置知识库来回答问题。",
    "你能做什么": "我可以响应问候,并回答关于我的能力、创建目的等预置问题。",
    "你叫什么名字": "我叫RuleAgent,是一个教学演示用的对话机器人。",
    "谁创建了你": "我是《Agent智能体开发实战100例》课程中的第一个案例,用于演示对话Agent的基本结构。",
    "你的工作原理是什么": "我通过正则表达式识别问候意图,在知识库中进行关键词匹配来回答问题,未命中时返回兜底回复。",
    "你会学习吗": "当前版本不会学习。我是基于固定规则的Agent,知识库是预先编写好的。",
}

# ===== 最小交互入口 =====
if __name__ == "__main__":
    agent = RuleAgent(knowledge)
    print("对话Agent已启动(输入exit退出)")
    while True:
        user_input = input("你: ").strip()
        if user_input.lower() in ("exit", "quit", "退出"):
            print("Agent: 再见!")
            break
        reply = agent.respond(user_input)
        print(f"Agent: {reply}")

运行方式

  1. 将上述代码保存为 rule_agent.py(需Python 3.10+,无需第三方库)
  2. 在终端执行:python rule_agent.py
  3. 在交互提示符后输入对话内容

验证方法

按以下顺序输入测试语句,观察输出是否符合预期:

  • 输入你好 → 应返回问候响应(含"你好!我是…")
  • 输入你是谁 → 应返回知识库中对应答案
  • 输入你会做什么 → 应通过关键词匹配返回"你能做什么"的答案
  • 输入今天天气如何 → 应返回兜底话术("抱歉,我还没学会…")
  • 输入exit → 程序正常退出

通过条件:以上5类输入均得到符合预期的回复,且程序无异常退出,即判定案例实现成功。

核心逻辑说明

意图识别采用正则精确匹配问候语;知识检索先做子串包含匹配,再对中文/英文分词后计算词覆盖率(>50%即命中),取最长匹配问题返回。会话历史保存在内存列表中,可通过get_history()查看。此实现不调用任何外部API,完全离线可运行。