{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7173bb69",
   "metadata": {},
   "source": [
    "# 阶段 6：成熟 Agent 框架实践\n",
    "\n",
    "## 📖 本阶段目标\n",
    "\n",
    "本 Notebook 将带你实践主流 Agent 开发框架，包括：\n",
    "\n",
    "- **LangChain** - 功能全面的 Agent 开发框架\n",
    "- **LlamaIndex** - 专注数据索引和 RAG 的框架\n",
    "\n",
    "通过本教程，你将掌握：\n",
    "1. LangChain 的核心概念（Chain、Tool、Memory）\n",
    "2. 使用 LangChain 创建 Agent\n",
    "3. LlamaIndex 的索引和查询机制\n",
    "4. 基于框架的 RAG 系统实现\n",
    "5. 综合 Agent 应用开发\n",
    "\n",
    "## 🚀 主流框架对比\n",
    "\n",
    "| 框架 | 特点 | 适用场景 | 学习曲线 |\n",
    "|------|------|----------|----------|\n",
    "| **LangChain** | 功能全面，生态丰富 | 通用 Agent 开发 | 中等 |\n",
    "| **LlamaIndex** | 专注数据索引和 RAG | 知识库问答 | 较低 |\n",
    "| **AutoGen** | 多 Agent 对话 | 复杂协作系统 | 中等 |\n",
    "| **CrewAI** | 角色化 Agent 团队 | 任务导向协作 | 较低 |\n",
    "| **LangGraph** | 状态图流程控制 | 复杂工作流 | 较高 |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95ccec5b",
   "metadata": {},
   "source": [
    "## 1. 环境设置与依赖安装\n",
    "\n",
    "首先安装所需的库：\n",
    "- `langchain` - LangChain 核心库\n",
    "- `langchain-openai` - OpenAI 集成\n",
    "- `langchain-community` - 社区集成（如 FAISS）\n",
    "- `llama-index` - LlamaIndex 框架\n",
    "- `faiss-cpu` - 向量数据库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28309379",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 安装依赖包（如果尚未安装）\n",
    "!pip install langchain langchain-openai langchain-community faiss-cpu llama-index llama-index-llms-openai llama-index-embeddings-openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "143f7e9a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入必要的库并配置环境\n",
    "import os\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# 加载环境变量\n",
    "load_dotenv()\n",
    "\n",
    "# 检查 Azure OpenAI 配置\n",
    "required_vars = [\n",
    "    \"AZURE_OPENAI_ENDPOINT\",\n",
    "    \"AZURE_OPENAI_API_KEY\", \n",
    "    \"AZURE_OPENAI_DEPLOYMENT\",\n",
    "    \"AZURE_OPENAI_API_VERSION\"\n",
    "]\n",
    "\n",
    "missing_vars = [var for var in required_vars if not os.getenv(var)]\n",
    "\n",
    "if missing_vars:\n",
    "    print(f\"⚠️ 缺少以下环境变量: {', '.join(missing_vars)}\")\n",
    "else:\n",
    "    print(\"✅ Azure OpenAI 配置已完成\")\n",
    "    print(f\"   Endpoint: {os.getenv('AZURE_OPENAI_ENDPOINT')}\")\n",
    "    print(f\"   Deployment: {os.getenv('AZURE_OPENAI_DEPLOYMENT')}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4cbfe79",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 2. LangChain 基础 - 链式构建\n",
    "\n",
    "LangChain 的核心概念：\n",
    "- **LLM** - 大语言模型封装\n",
    "- **Prompt Template** - 提示词模板\n",
    "- **Output Parser** - 输出解析器\n",
    "- **Chain** - 将以上组件串联起来\n",
    "\n",
    "### LCEL (LangChain Expression Language)\n",
    "使用 `|` 管道符号连接组件，形成数据流：\n",
    "\n",
    "```\n",
    "prompt | llm | output_parser\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "451e07ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "# LangChain 基础示例 - 使用 Azure OpenAI\n",
    "from langchain_openai import AzureChatOpenAI\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "\n",
    "# 1. 创建 Azure OpenAI LLM 实例\n",
    "llm = AzureChatOpenAI(\n",
    "    azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
    "    api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "    azure_deployment=os.getenv(\"AZURE_OPENAI_DEPLOYMENT\"),\n",
    "    api_version=os.getenv(\"AZURE_OPENAI_API_VERSION\"),\n",
    "    temperature=0.7\n",
    ")\n",
    "\n",
    "# 2. 创建 Prompt 模板\n",
    "prompt = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"你是一个{role}。请用简洁专业的语言回答问题。\"),\n",
    "    (\"user\", \"{input}\")\n",
    "])\n",
    "\n",
    "# 3. 创建输出解析器\n",
    "output_parser = StrOutputParser()\n",
    "\n",
    "# 4. 使用 LCEL 构建链（Chain）\n",
    "chain = prompt | llm | output_parser\n",
    "\n",
    "print(\"✅ LangChain 链已创建（使用 Azure OpenAI）\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0fc2775b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 运行链 - 示例1：Python 编程助手\n",
    "result = chain.invoke({\n",
    "    \"role\": \"Python 编程助手\",\n",
    "    \"input\": \"如何读取 JSON 文件？\"\n",
    "})\n",
    "\n",
    "print(\"问题: 如何读取 JSON 文件？\")\n",
    "print(\"-\" * 50)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "175832d8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 运行链 - 示例2：切换角色\n",
    "result2 = chain.invoke({\n",
    "    \"role\": \"数据分析师\",\n",
    "    \"input\": \"什么是 Pandas DataFrame？\"\n",
    "})\n",
    "\n",
    "print(\"问题: 什么是 Pandas DataFrame？\")\n",
    "print(\"-\" * 50)\n",
    "print(result2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79f2b736",
   "metadata": {},
   "source": [
    "### 💡 练习：自定义链\n",
    "\n",
    "尝试创建一个翻译链，将中文翻译成英文。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3bfdd463",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 练习：创建翻译链\n",
    "translation_prompt = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"你是一个专业的翻译。请将用户输入的{source_lang}翻译成{target_lang}。只输出翻译结果。\"),\n",
    "    (\"user\", \"{text}\")\n",
    "])\n",
    "\n",
    "translation_chain = translation_prompt | llm | output_parser\n",
    "\n",
    "# 测试翻译链\n",
    "result = translation_chain.invoke({\n",
    "    \"source_lang\": \"中文\",\n",
    "    \"target_lang\": \"英文\",\n",
    "    \"text\": \"人工智能正在改变世界\"\n",
    "})\n",
    "\n",
    "print(\"原文: 人工智能正在改变世界\")\n",
    "print(f\"译文: {result}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16fc1755",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 3. LangChain 工具集成\n",
    "\n",
    "Agent 的核心能力是使用工具。LangChain 提供了灵活的工具定义和集成方式。\n",
    "\n",
    "### 工具定义步骤：\n",
    "1. 定义工具函数\n",
    "2. 创建 Tool 对象（包含名称、函数、描述）\n",
    "3. 创建 Agent（使用 `create_openai_functions_agent`）\n",
    "4. 创建 AgentExecutor 执行器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b02f2bf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义工具函数\n",
    "def get_weather(city: str) -> str:\n",
    "    \"\"\"获取指定城市的天气信息\"\"\"\n",
    "    # 模拟天气API返回（实际应调用真实API）\n",
    "    weather_data = {\n",
    "        \"北京\": \"晴，温度25°C，湿度40%\",\n",
    "        \"上海\": \"多云，温度28°C，湿度65%\",\n",
    "        \"广州\": \"阴，温度30°C，湿度80%\",\n",
    "        \"深圳\": \"晴，温度29°C，湿度70%\",\n",
    "    }\n",
    "    return weather_data.get(city, f\"{city}的天气：晴，温度22°C\")\n",
    "\n",
    "def search_web(query: str) -> str:\n",
    "    \"\"\"在网络上搜索信息\"\"\"\n",
    "    # 模拟搜索结果\n",
    "    return f\"关于'{query}'的搜索结果：找到了相关信息，包括最新的文章、教程和讨论。\"\n",
    "\n",
    "def calculate(expression: str) -> str:\n",
    "    \"\"\"计算数学表达式\"\"\"\n",
    "    try:\n",
    "        # 使用安全的 eval（限制内置函数）\n",
    "        result = eval(expression, {\"__builtins__\": {}}, {})\n",
    "        return f\"计算结果: {result}\"\n",
    "    except Exception as e:\n",
    "        return f\"计算错误: {str(e)}\"\n",
    "\n",
    "# 测试工具函数\n",
    "print(\"测试工具函数：\")\n",
    "print(f\"天气: {get_weather('北京')}\")\n",
    "print(f\"搜索: {search_web('Python教程')}\")\n",
    "print(f\"计算: {calculate('(25 + 5) * 2')}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "204a5729",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建 LangChain 工具\n",
    "from langchain_core.tools import Tool\n",
    "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
    "\n",
    "# 创建工具列表\n",
    "tools = [\n",
    "    Tool(\n",
    "        name=\"get_weather\",\n",
    "        func=get_weather,\n",
    "        description=\"获取指定城市的天气信息。输入应该是城市名称，如'北京'、'上海'。\"\n",
    "    ),\n",
    "    Tool(\n",
    "        name=\"search_web\",\n",
    "        func=search_web,\n",
    "        description=\"在网络上搜索信息。输入应该是搜索查询关键词。\"\n",
    "    ),\n",
    "    Tool(\n",
    "        name=\"calculate\",\n",
    "        func=calculate,\n",
    "        description=\"计算数学表达式。输入应该是有效的数学表达式，如 '2 + 2' 或 '(10 + 5) * 3'。\"\n",
    "    )\n",
    "]\n",
    "\n",
    "print(f\"✅ 已创建 {len(tools)} 个工具：\")\n",
    "for tool in tools:\n",
    "    print(f\"  - {tool.name}: {tool.description[:50]}...\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "94660bc0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建 Agent - 使用 Azure OpenAI + LangGraph\n",
    "from langgraph.prebuilt import create_react_agent\n",
    "\n",
    "agent_llm = AzureChatOpenAI(\n",
    "    azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
    "    api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "    azure_deployment=os.getenv(\"AZURE_OPENAI_DEPLOYMENT\"),\n",
    "    api_version=os.getenv(\"AZURE_OPENAI_API_VERSION\"),\n",
    "    temperature=0\n",
    ")\n",
    "\n",
    "# 创建 ReAct Agent（使用 LangGraph）\n",
    "agent_executor = create_react_agent(agent_llm, tools)\n",
    "\n",
    "print(\"✅ Agent 已创建完成（使用 Azure OpenAI + LangGraph）\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a51dcf68",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用 Agent - 示例1：简单查询\n",
    "result = agent_executor.invoke({\n",
    "    \"messages\": [(\"user\", \"北京的天气怎么样？\")]\n",
    "})\n",
    "\n",
    "print(\"\\n\" + \"=\" * 60)\n",
    "print(\"最终结果：\")\n",
    "print(result[\"messages\"][-1].content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "785b031c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用 Agent - 示例2：多步骤任务\n",
    "result = agent_executor.invoke({\n",
    "    \"messages\": [(\"user\", \"北京的天气怎么样？如果温度超过20度，帮我计算 (25 + 5) * 2\")]\n",
    "})\n",
    "\n",
    "print(\"\\n\" + \"=\" * 60)\n",
    "print(\"最终结果：\")\n",
    "print(result[\"messages\"][-1].content)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5c995557",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 4. LangChain 记忆系统\n",
    "\n",
    "记忆系统让 Agent 能够记住对话历史，实现多轮对话。\n",
    "\n",
    "### 常用记忆类型：\n",
    "- **ConversationBufferMemory** - 保存完整对话历史\n",
    "- **ConversationSummaryMemory** - 自动总结对话历史\n",
    "- **ConversationBufferWindowMemory** - 保存最近 N 轮对话"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "94de8bd9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 缓冲记忆（Buffer Memory）- 使用 LangGraph 的现代方式\n",
    "from langgraph.checkpoint.memory import MemorySaver\n",
    "from langgraph.prebuilt import create_react_agent\n",
    "\n",
    "# 创建带记忆的对话 Agent\n",
    "conversation_llm = AzureChatOpenAI(\n",
    "    azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
    "    api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "    azure_deployment=os.getenv(\"AZURE_OPENAI_DEPLOYMENT\"),\n",
    "    api_version=os.getenv(\"AZURE_OPENAI_API_VERSION\"),\n",
    "    temperature=0.7\n",
    ")\n",
    "\n",
    "# 使用 MemorySaver 来保存对话历史\n",
    "memory = MemorySaver()\n",
    "\n",
    "# 创建一个简单的对话工具\n",
    "def chat_response(message: str) -> str:\n",
    "    \"\"\"处理用户消息\"\"\"\n",
    "    return message\n",
    "\n",
    "# 创建带记忆的 Agent\n",
    "conversation_agent = create_react_agent(\n",
    "    conversation_llm, \n",
    "    tools=[],  # 纯对话不需要工具\n",
    "    checkpointer=memory\n",
    ")\n",
    "\n",
    "# 配置线程ID用于跟踪对话\n",
    "config = {\"configurable\": {\"thread_id\": \"memory-demo-1\"}}\n",
    "\n",
    "print(\"✅ 带记忆的对话 Agent 已创建（使用 LangGraph）\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55182b66",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 多轮对话演示\n",
    "print(\"=\" * 60)\n",
    "print(\"第1轮对话\")\n",
    "print(\"=\" * 60)\n",
    "response1 = conversation_agent.invoke(\n",
    "    {\"messages\": [(\"user\", \"你好，我叫张三，我是一名Python开发者\")]},\n",
    "    config=config\n",
    ")\n",
    "print(f\"AI: {response1['messages'][-1].content}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0109db2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 继续对话\n",
    "print(\"=\" * 60)\n",
    "print(\"第2轮对话\")\n",
    "print(\"=\" * 60)\n",
    "response2 = conversation_agent.invoke(\n",
    "    {\"messages\": [(\"user\", \"我最近在学习 AI Agent 开发\")]},\n",
    "    config=config\n",
    ")\n",
    "print(f\"AI: {response2['messages'][-1].content}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd8079dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试记忆 - AI 是否记得用户信息\n",
    "print(\"=\" * 60)\n",
    "print(\"第3轮对话 - 测试记忆\")\n",
    "print(\"=\" * 60)\n",
    "response3 = conversation_agent.invoke(\n",
    "    {\"messages\": [(\"user\", \"我叫什么名字？我的职业是什么？\")]},\n",
    "    config=config\n",
    ")\n",
    "print(f\"AI: {response3['messages'][-1].content}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71f8dd95",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 查看记忆内容\n",
    "print(\"=\" * 60)\n",
    "print(\"对话历史（通过 checkpoint 获取）：\")\n",
    "print(\"=\" * 60)\n",
    "\n",
    "# 获取当前状态\n",
    "state = conversation_agent.get_state(config)\n",
    "for msg in state.values.get(\"messages\", []):\n",
    "    role = \"用户\" if msg.type == \"human\" else \"AI\"\n",
    "    print(f\"{role}: {msg.content[:100]}...\" if len(msg.content) > 100 else f\"{role}: {msg.content}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23d88815",
   "metadata": {},
   "source": [
    "### 摘要记忆（Summary Memory）\n",
    "\n",
    "当对话很长时，完整保存所有历史会消耗大量 token。摘要记忆会自动总结对话历史。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a734470b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 摘要记忆示例 - 使用新的对话线程演示长对话\n",
    "# 在 LangGraph 中，可以通过不同的 thread_id 来管理不同的对话\n",
    "\n",
    "summary_config = {\"configurable\": {\"thread_id\": \"summary-demo-1\"}}\n",
    "\n",
    "# 进行多轮对话\n",
    "print(\"=\" * 60)\n",
    "print(\"长对话演示（使用新的对话线程）\")\n",
    "print(\"=\" * 60)\n",
    "\n",
    "conversations = [\n",
    "    \"介绍一下 Python 编程语言\",\n",
    "    \"它有什么主要优点？\",\n",
    "    \"Python 适合做什么类型的项目？\"\n",
    "]\n",
    "\n",
    "for i, msg in enumerate(conversations, 1):\n",
    "    print(f\"\\n第{i}轮: {msg}\")\n",
    "    response = conversation_agent.invoke(\n",
    "        {\"messages\": [(\"user\", msg)]},\n",
    "        config=summary_config\n",
    "    )\n",
    "    print(f\"AI: {response['messages'][-1].content[:200]}...\")\n",
    "\n",
    "# 查看对话历史\n",
    "print(\"\\n\" + \"=\" * 60)\n",
    "print(\"完整对话历史：\")\n",
    "print(\"=\" * 60)\n",
    "state = conversation_agent.get_state(summary_config)\n",
    "print(f\"共 {len(state.values.get('messages', []))} 条消息\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9b49586",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 5. LangChain RAG 实现\n",
    "\n",
    "RAG（Retrieval-Augmented Generation）检索增强生成，是让 LLM 基于外部知识回答问题的技术。\n",
    "\n",
    "### RAG 流程：\n",
    "1. **加载文档** - 读取知识库文档\n",
    "2. **分割文档** - 将长文档分割成小块\n",
    "3. **向量化存储** - 使用 Embedding 模型将文本转为向量\n",
    "4. **检索** - 根据问题检索相关文档块\n",
    "5. **生成回答** - LLM 基于检索结果生成答案"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db6fa7ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 准备知识库文档\n",
    "from langchain_core.documents import Document\n",
    "\n",
    "# 模拟知识库文档\n",
    "knowledge_documents = [\n",
    "    Document(page_content=\"Python 是一种高级编程语言，由 Guido van Rossum 创建于 1991 年。它以简洁优雅的语法著称。\"),\n",
    "    Document(page_content=\"Python 的设计哲学强调代码的可读性和简洁的语法，使用缩进来定义代码块。\"),\n",
    "    Document(page_content=\"Python 拥有丰富的标准库和第三方包生态系统，如 NumPy、Pandas、TensorFlow 等。\"),\n",
    "    Document(page_content=\"Django 是一个用 Python 编写的高级 Web 框架，遵循 MVT 设计模式。\"),\n",
    "    Document(page_content=\"Flask 是一个轻量级的 Python Web 框架，适合构建小型应用和 API。\"),\n",
    "    Document(page_content=\"FastAPI 是一个现代、高性能的 Python Web 框架，支持异步编程和自动生成 API 文档。\"),\n",
    "    Document(page_content=\"LangChain 是一个用于开发 LLM 应用的框架，提供了丰富的工具和组件。\"),\n",
    "    Document(page_content=\"AI Agent 是能够自主感知环境、做出决策并执行行动的智能系统。\"),\n",
    "]\n",
    "\n",
    "print(f\"✅ 已加载 {len(knowledge_documents)} 个文档\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6d8bcdf0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 文档分割\n",
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "\n",
    "# 创建文本分割器\n",
    "text_splitter = RecursiveCharacterTextSplitter(\n",
    "    chunk_size=100,      # 每块最大字符数\n",
    "    chunk_overlap=20,    # 块之间的重叠字符数\n",
    "    length_function=len,\n",
    "    separators=[\"\\n\\n\", \"\\n\", \"。\", \"，\", \" \", \"\"]\n",
    ")\n",
    "\n",
    "# 分割文档\n",
    "splits = text_splitter.split_documents(knowledge_documents)\n",
    "\n",
    "print(f\"✅ 文档分割完成：{len(knowledge_documents)} 个文档 → {len(splits)} 个块\")\n",
    "print(\"\\n示例块：\")\n",
    "for i, split in enumerate(splits[:3]):\n",
    "    print(f\"块 {i+1}: {split.page_content[:50]}...\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5d64093",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建向量存储 - 使用 Azure OpenAI Embeddings\n",
    "from langchain_openai import AzureOpenAIEmbeddings\n",
    "from langchain_community.vectorstores import FAISS\n",
    "\n",
    "# 创建 Azure OpenAI Embedding 模型\n",
    "embeddings = AzureOpenAIEmbeddings(\n",
    "    azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
    "    api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "    azure_deployment=os.getenv(\"AZURE_OPENAI_EMBEDDING_DEPLOYMENT\", \"text-embedding-ada-002\"),\n",
    "    api_version=os.getenv(\"AZURE_OPENAI_API_VERSION\")\n",
    ")\n",
    "\n",
    "# 创建 FAISS 向量存储\n",
    "vectorstore = FAISS.from_documents(splits, embeddings)\n",
    "\n",
    "# 创建检索器\n",
    "retriever = vectorstore.as_retriever(\n",
    "    search_type=\"similarity\",  # 相似度搜索\n",
    "    search_kwargs={\"k\": 3}     # 返回最相似的3个块\n",
    ")\n",
    "\n",
    "print(\"✅ 向量存储和检索器创建完成（使用 Azure OpenAI Embeddings）\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7aaa22f2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建 RAG 问答链 - 使用 LCEL（现代方式）\n",
    "from langchain_core.runnables import RunnablePassthrough\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "# 创建 LLM\n",
    "rag_llm = AzureChatOpenAI(\n",
    "    azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
    "    api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "    azure_deployment=os.getenv(\"AZURE_OPENAI_DEPLOYMENT\"),\n",
    "    api_version=os.getenv(\"AZURE_OPENAI_API_VERSION\"),\n",
    "    temperature=0\n",
    ")\n",
    "\n",
    "# RAG 提示词模板\n",
    "rag_prompt = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"\"\"你是一个知识问答助手。请根据以下上下文信息回答用户的问题。\n",
    "如果上下文中没有相关信息，请诚实地说不知道。\n",
    "\n",
    "上下文信息：\n",
    "{context}\"\"\"),\n",
    "    (\"user\", \"{question}\")\n",
    "])\n",
    "\n",
    "# 格式化检索到的文档\n",
    "def format_docs(docs):\n",
    "    return \"\\n\\n\".join(doc.page_content for doc in docs)\n",
    "\n",
    "# 创建 RAG 链（使用 LCEL）\n",
    "rag_chain = (\n",
    "    {\"context\": retriever | format_docs, \"question\": RunnablePassthrough()}\n",
    "    | rag_prompt\n",
    "    | rag_llm\n",
    "    | StrOutputParser()\n",
    ")\n",
    "\n",
    "print(\"✅ RAG 问答链创建完成（使用 Azure OpenAI + LCEL）\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e19911d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试 RAG 系统\n",
    "questions = [\n",
    "    \"Python 是什么时候创建的？\",\n",
    "    \"有哪些 Python Web 框架？\",\n",
    "    \"什么是 AI Agent？\"\n",
    "]\n",
    "\n",
    "for question in questions:\n",
    "    print(f\"\\n{'=' * 60}\")\n",
    "    print(f\"问题: {question}\")\n",
    "    print(\"-\" * 60)\n",
    "    \n",
    "    # 使用 LCEL RAG 链\n",
    "    result = rag_chain.invoke(question)\n",
    "    print(f\"答案: {result}\")\n",
    "    \n",
    "    # 显示检索到的文档\n",
    "    retrieved_docs = retriever.invoke(question)\n",
    "    print(f\"\\n📚 来源文档:\")\n",
    "    for i, doc in enumerate(retrieved_docs, 1):\n",
    "        print(f\"  {i}. {doc.page_content[:60]}...\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05677e11",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 6. LlamaIndex 基础索引\n",
    "\n",
    "LlamaIndex 是专注于数据索引和 RAG 的框架，比 LangChain 更加专注和简洁。\n",
    "\n",
    "### 核心概念：\n",
    "- **Document** - 文档对象\n",
    "- **Index** - 索引（如 VectorStoreIndex）\n",
    "- **QueryEngine** - 查询引擎"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed5a1121",
   "metadata": {},
   "outputs": [],
   "source": [
    "# LlamaIndex 基础配置 - 使用 Azure OpenAI\n",
    "from llama_index.core import VectorStoreIndex, Document, Settings\n",
    "from llama_index.llms.azure_openai import AzureOpenAI\n",
    "from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding\n",
    "\n",
    "# 配置 Azure OpenAI LLM\n",
    "azure_llm = AzureOpenAI(\n",
    "    engine=os.getenv(\"AZURE_OPENAI_DEPLOYMENT\"),\n",
    "    azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
    "    api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "    api_version=os.getenv(\"AZURE_OPENAI_API_VERSION\"),\n",
    "    temperature=0.1\n",
    ")\n",
    "\n",
    "# 配置 Azure OpenAI Embedding\n",
    "azure_embed_model = AzureOpenAIEmbedding(\n",
    "    azure_deployment=os.getenv(\"AZURE_OPENAI_EMBEDDING_DEPLOYMENT\", \"text-embedding-ada-002\"),\n",
    "    azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
    "    api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "    api_version=os.getenv(\"AZURE_OPENAI_API_VERSION\")\n",
    ")\n",
    "\n",
    "# 配置全局设置\n",
    "Settings.llm = azure_llm\n",
    "Settings.embed_model = azure_embed_model\n",
    "\n",
    "print(\"✅ LlamaIndex 配置完成（使用 Azure OpenAI）\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "07a6e6ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建 LlamaIndex 文档\n",
    "llama_documents = [\n",
    "    Document(text=\"Python 是一种高级编程语言，创建于 1991 年，以简洁优雅著称。\"),\n",
    "    Document(text=\"LlamaIndex 是一个用于构建 LLM 应用的数据框架，专注于数据索引和检索。\"),\n",
    "    Document(text=\"向量数据库用于存储和检索文本嵌入，是 RAG 系统的核心组件。\"),\n",
    "    Document(text=\"LangChain 是一个功能全面的 Agent 开发框架，提供丰富的工具集成。\"),\n",
    "    Document(text=\"AI Agent 能够自主规划任务、调用工具、完成复杂目标。\"),\n",
    "]\n",
    "\n",
    "# 创建向量索引\n",
    "llama_index = VectorStoreIndex.from_documents(llama_documents)\n",
    "\n",
    "print(f\"✅ LlamaIndex 索引创建完成，包含 {len(llama_documents)} 个文档\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "31201249",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建查询引擎并查询\n",
    "query_engine = llama_index.as_query_engine()\n",
    "\n",
    "# 测试查询\n",
    "llama_questions = [\n",
    "    \"Python 是什么时候创建的？\",\n",
    "    \"什么是 LlamaIndex？\",\n",
    "    \"AI Agent 有什么能力？\"\n",
    "]\n",
    "\n",
    "for question in llama_questions:\n",
    "    print(f\"\\n{'=' * 60}\")\n",
    "    print(f\"问题: {question}\")\n",
    "    print(\"-\" * 60)\n",
    "    \n",
    "    response = query_engine.query(question)\n",
    "    print(f\"答案: {response}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90358394",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 7. LlamaIndex 高级 RAG\n",
    "\n",
    "LlamaIndex 提供了更细粒度的控制，包括：\n",
    "- 自定义分块策略\n",
    "- 配置检索器参数\n",
    "- 创建自定义查询引擎"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "be92374b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 高级 RAG - 自定义分块和检索\n",
    "from llama_index.core.node_parser import SentenceSplitter\n",
    "from llama_index.core.retrievers import VectorIndexRetriever\n",
    "from llama_index.core.query_engine import RetrieverQueryEngine\n",
    "\n",
    "# 准备更丰富的文档\n",
    "advanced_documents = [\n",
    "    Document(text=\"\"\"\n",
    "    AI Agent 是一种能够感知环境、做出决策并采取行动的智能系统。\n",
    "    它结合了大语言模型的推理能力和工具调用的执行能力。\n",
    "    Agent 可以自主规划任务步骤，调用各种工具完成复杂任务。\n",
    "    现代 Agent 通常包含记忆系统，能够记住之前的交互。\n",
    "    \"\"\"),\n",
    "    Document(text=\"\"\"\n",
    "    RAG（检索增强生成）是一种结合信息检索和文本生成的技术。\n",
    "    它首先从知识库检索相关文档，然后基于这些文档生成答案。\n",
    "    这种方法可以提高答案的准确性和可信度，减少幻觉。\n",
    "    RAG 是构建知识密集型 AI 应用的关键技术。\n",
    "    \"\"\"),\n",
    "    Document(text=\"\"\"\n",
    "    LangChain 和 LlamaIndex 是两个流行的 LLM 应用开发框架。\n",
    "    LangChain 功能全面，适合通用 Agent 开发。\n",
    "    LlamaIndex 专注于数据索引和 RAG，更加简洁。\n",
    "    选择框架应根据具体需求和场景决定。\n",
    "    \"\"\")\n",
    "]\n",
    "\n",
    "print(f\"✅ 准备了 {len(advanced_documents)} 个详细文档\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a3e0de23",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 自定义分块策略\n",
    "splitter = SentenceSplitter(\n",
    "    chunk_size=128,      # 每块最大 128 个 token\n",
    "    chunk_overlap=20     # 块之间重叠 20 个 token\n",
    ")\n",
    "\n",
    "# 创建索引（使用自定义分块）\n",
    "advanced_index = VectorStoreIndex.from_documents(\n",
    "    advanced_documents,\n",
    "    transformations=[splitter]\n",
    ")\n",
    "\n",
    "# 配置检索器\n",
    "advanced_retriever = VectorIndexRetriever(\n",
    "    index=advanced_index,\n",
    "    similarity_top_k=3  # 返回最相似的 3 个块\n",
    ")\n",
    "\n",
    "# 创建查询引擎\n",
    "advanced_query_engine = RetrieverQueryEngine(\n",
    "    retriever=advanced_retriever\n",
    ")\n",
    "\n",
    "print(\"✅ 高级 RAG 系统创建完成\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "53e6fef9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试高级 RAG 查询\n",
    "advanced_questions = [\n",
    "    \"什么是 AI Agent？它有什么特点？\",\n",
    "    \"RAG 技术有什么优势？\",\n",
    "    \"如何选择 LangChain 和 LlamaIndex？\"\n",
    "]\n",
    "\n",
    "for question in advanced_questions:\n",
    "    print(f\"\\n{'=' * 60}\")\n",
    "    print(f\"问题: {question}\")\n",
    "    print(\"-\" * 60)\n",
    "    \n",
    "    response = advanced_query_engine.query(question)\n",
    "    print(f\"答案: {response}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ccf7ed16",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 8. 综合 Agent 应用\n",
    "\n",
    "现在让我们结合所学内容，构建一个综合能力的 Agent：\n",
    "- ✅ 知识库查询（RAG）\n",
    "- ✅ 工具调用（计算等）\n",
    "- ✅ 对话记忆\n",
    "- ✅ 多轮交互"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99c49c1f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 综合 Agent 类定义 - 使用 Azure OpenAI + LangGraph\n",
    "from langchain_core.documents import Document as LCDocument\n",
    "from langgraph.checkpoint.memory import MemorySaver\n",
    "\n",
    "class ComprehensiveAgent:\n",
    "    \"\"\"综合能力的 Agent - 结合 RAG、工具和记忆\"\"\"\n",
    "    \n",
    "    def __init__(self):\n",
    "        # 初始化 Azure OpenAI LLM\n",
    "        self.llm = AzureChatOpenAI(\n",
    "            azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
    "            api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "            azure_deployment=os.getenv(\"AZURE_OPENAI_DEPLOYMENT\"),\n",
    "            api_version=os.getenv(\"AZURE_OPENAI_API_VERSION\"),\n",
    "            temperature=0.7\n",
    "        )\n",
    "        \n",
    "        # 创建工具\n",
    "        self.tools = self._create_tools()\n",
    "        \n",
    "        # 创建带记忆的 Agent（使用 LangGraph）\n",
    "        self.memory = MemorySaver()\n",
    "        self.agent = create_react_agent(self.llm, self.tools, checkpointer=self.memory)\n",
    "        self.config = {\"configurable\": {\"thread_id\": \"comprehensive-agent-1\"}}\n",
    "        \n",
    "        print(\"✅ 综合 Agent 初始化完成（使用 Azure OpenAI + LangGraph）\")\n",
    "    \n",
    "    def _create_knowledge_base(self):\n",
    "        \"\"\"创建知识库\"\"\"\n",
    "        # 公司知识文档\n",
    "        company_docs = [\n",
    "            \"公司成立于2020年，主营AI产品开发，总部位于北京。\",\n",
    "            \"我们的产品包括：智能客服系统、文档分析平台、代码助手。\",\n",
    "            \"技术栈：Python, FastAPI, React, PostgreSQL, Redis。\",\n",
    "            \"团队规模：50人，其中研发团队30人。\",\n",
    "            \"核心优势：先进的AI技术、专业的技术团队、优质的客户服务。\",\n",
    "        ]\n",
    "        \n",
    "        docs = [LCDocument(page_content=d) for d in company_docs]\n",
    "        \n",
    "        # 创建 Azure OpenAI Embeddings 向量存储\n",
    "        kb_embeddings = AzureOpenAIEmbeddings(\n",
    "            azure_endpoint=os.getenv(\"AZURE_OPENAI_ENDPOINT\"),\n",
    "            api_key=os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "            azure_deployment=os.getenv(\"AZURE_OPENAI_EMBEDDING_DEPLOYMENT\", \"text-embedding-ada-002\"),\n",
    "            api_version=os.getenv(\"AZURE_OPENAI_API_VERSION\")\n",
    "        )\n",
    "        kb_vectorstore = FAISS.from_documents(docs, kb_embeddings)\n",
    "        \n",
    "        return kb_vectorstore.as_retriever()\n",
    "    \n",
    "    def _create_tools(self):\n",
    "        \"\"\"创建工具集\"\"\"\n",
    "        retriever = self._create_knowledge_base()\n",
    "        \n",
    "        def query_knowledge_base(query: str) -> str:\n",
    "            \"\"\"查询公司知识库\"\"\"\n",
    "            docs = retriever.invoke(query)\n",
    "            return \"\\n\".join([doc.page_content for doc in docs])\n",
    "        \n",
    "        tools = [\n",
    "            Tool(\n",
    "                name=\"knowledge_base\",\n",
    "                func=query_knowledge_base,\n",
    "                description=\"查询公司知识库，包括公司信息、产品介绍、技术栈、团队等内容。当用户询问公司相关问题时使用。\"\n",
    "            ),\n",
    "            Tool(\n",
    "                name=\"calculate\",\n",
    "                func=lambda expr: str(eval(expr, {\"__builtins__\": {}}, {})),\n",
    "                description=\"计算数学表达式。输入应该是有效的数学表达式，如 '2 + 2' 或 '(100 + 50) * 2'。\"\n",
    "            ),\n",
    "            Tool(\n",
    "                name=\"get_current_time\",\n",
    "                func=lambda _: __import__('datetime').datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n",
    "                description=\"获取当前时间。不需要输入参数。\"\n",
    "            )\n",
    "        ]\n",
    "        \n",
    "        return tools\n",
    "    \n",
    "    def chat(self, message: str) -> str:\n",
    "        \"\"\"与 Agent 对话\"\"\"\n",
    "        result = self.agent.invoke(\n",
    "            {\"messages\": [(\"user\", message)]},\n",
    "            config=self.config\n",
    "        )\n",
    "        return result[\"messages\"][-1].content\n",
    "\n",
    "print(\"✅ ComprehensiveAgent 类定义完成（使用 Azure OpenAI + LangGraph）\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "638213e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建综合 Agent 实例\n",
    "agent = ComprehensiveAgent()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78a51fed",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 多轮对话演示\n",
    "print(\"🤖 综合 Agent 多轮对话演示\")\n",
    "print(\"=\" * 60)\n",
    "\n",
    "# 对话列表\n",
    "conversations = [\n",
    "    \"你好！请介绍一下你自己\",\n",
    "    \"公司是什么时候成立的？在哪里？\",\n",
    "    \"我们有哪些产品？\",\n",
    "    \"帮我算一下如果团队每人年薪30万，研发团队的年度人力成本是多少？\",\n",
    "    \"现在几点了？\",\n",
    "    \"总结一下我们刚才讨论了什么内容\"\n",
    "]\n",
    "\n",
    "for i, msg in enumerate(conversations, 1):\n",
    "    print(f\"\\n{'=' * 60}\")\n",
    "    print(f\"第 {i} 轮对话\")\n",
    "    print(f\"用户: {msg}\")\n",
    "    print(\"-\" * 60)\n",
    "    \n",
    "    response = agent.chat(msg)\n",
    "    print(f\"\\n🤖 Agent: {response}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e91e62c5",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 📚 框架选择建议\n",
    "\n",
    "### 选择 LangChain 当你需要：\n",
    "- ✅ 丰富的工具和集成（数据库、API、文件等）\n",
    "- ✅ 灵活的链式组合\n",
    "- ✅ 复杂的 Agent 逻辑\n",
    "- ✅ 活跃的社区支持和丰富的文档\n",
    "\n",
    "### 选择 LlamaIndex 当你需要：\n",
    "- ✅ 专注于数据索引和检索\n",
    "- ✅ 简单的 RAG 应用\n",
    "- ✅ 结构化数据处理\n",
    "- ✅ 快速原型开发\n",
    "\n",
    "### 选择 AutoGen/CrewAI 当你需要：\n",
    "- ✅ 多 Agent 协作系统\n",
    "- ✅ 角色化 Agent 团队\n",
    "- ✅ 复杂对话流程"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d021db83",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## ✅ 阶段完成检查清单\n",
    "\n",
    "完成本 Notebook 后，请检查以下内容：\n",
    "\n",
    "- [ ] 理解主流框架的特点和适用场景\n",
    "- [ ] 掌握 LangChain 的核心概念（Chain、Tool、Memory）\n",
    "- [ ] 能够使用 LangChain 创建 Agent\n",
    "- [ ] 了解 LlamaIndex 的索引和查询机制\n",
    "- [ ] 实现了基于框架的 RAG 系统\n",
    "- [ ] 完成综合 Agent 应用项目\n",
    "- [ ] 能够根据需求选择合适的框架\n",
    "\n",
    "## 🎯 下一步\n",
    "\n",
    "完成本阶段后，进入 **阶段 7：工程化、评估与安全**，学习如何将 Agent 产品化。\n",
    "\n",
    "---\n",
    "\n",
    "**💡 小贴士**：框架是工具，理解底层原理更重要。先用框架快速实现，再根据需要优化和定制。不要被框架限制思路！"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
