零基础学习AI智能体

AI agent (= LLM(模型)+memory(记忆)+planning skills(规划)+tool use(工具))

一、建立认知与体感

  • ChatBot、RAG 和 Agent 的区别  
维度Chatbot (聊天机器人)RAG (检索增强生成)Agent (智能体)
核心隐喻 鹦鹉学舌 / 客服话术 开卷考试的学霸 能独立办事的员工
LLM 角色 文本生成器 阅读理解 + 总结器 大脑 / 决策中枢
数据流向 用户输入 → LLM → 输出 用户输入 → 检索 → LLM → 输出 用户输入 → LLM → 规划/调用工具 → 观察结果 → 循环... → 输出
是否有外部交互 ❌ 无(仅靠预训练知识) ✅ 只读(读取知识库) ✅ 读写+执行(调API、查库、写文件)
控制流 单轮/多轮线性对话 单次检索-生成管道 动态循环
能否处理未知任务 ❌ 只能回答预设问题 ⚠️ 只能回答知识库里有的 ✅ 能拆解陌生任务并尝试解决
工程复杂度 低 中 高
典型失败模式 幻觉、拒答 检索不准、引用错误 死循环、工具调用失败、成本爆炸
  • 需要掌握的 python 基础
  1. 异步编程(asyncio)  Agent多用于  I/O密集的场景
    1. async def:定义一个异步函数(协程)
    2. await:挂起当前任务,等待结果(只有遇到网络请求、文件读写等耗时操作时使用)
    3. asyncio.gather:核心!用于并发执行多个异步任务
    4. asycio.run():启动异步程序的入口
      import asyncio
      import time
      
      # 模拟异步工具调用(实际开发中这里是 httpx 或 aiohttp 的网络请求)
      async def search_weather_tool(city: str) -> str:
          await asyncio.sleep(2)  # 模拟网络延迟 2 秒
          return f"{city}的天气是晴天"
      
      async def search_stock_tool(symbol: str) -> str:
          await asyncio.sleep(2)  # 模拟网络延迟 2 秒
          return f"{symbol}的股价是 150"
      
      async def agent_execute_tools():
          print("Agent 开始并发调用工具...")
          start_time = time.time()
          
          # ✅ 核心:使用 gather 并发执行,总耗时约等于最慢的那个任务(2秒),而不是相加(4秒)
          results = await asyncio.gather(
              search_weather_tool("北京"),
              search_stock_tool("AAPL")
          )
          
          print(f"工具返回结果: {results}")
          print(f"总耗时: {time.time() - start_time:.2f} 秒")
      
      # 运行异步程序
      if __name__ == "__main__":
          asyncio.run(agent_execute_tools())

       

  2. 类型提示(type Hints)与 pydantic:Agent 的“契约与骨架”
    1. 让 LLM 调用工具时,框架(如 LangChain/LangGraph)会自动读取 python 函数的类型提示和 pydantic 模型,将其转换为 json schema 喂给大模型,告诉大模型“你该传什么参数”,如果没有类型提示,大模型就不知道该怎么调用你的工具;
    2. 核心就是:既让 LLM阅读用户的自然语言,并且对照 Pydantic 生成的 Schema,在内部做了一个 “语义到结构的映射,又将大模型(LLM)输出的“非结构化文本”安全、可靠地转化为程序可执行的“结构化数据”。
    3. 几种核心的语法
      • 基础类型:str, int, float, bool
      • 容器类型:list[str], dict[str, int]
      • 可选类型:str | None (代替以前的 Optional[str])
        from pydantic import BaseModel, Field
        
        # ✅ 定义 Agent 工具的入参模型
        class SearchRequest(BaseModel):
            """用于搜索信息的请求参数""" # 这个文档字符串会被提取给 LLM 看!
            
            query: str = Field(description="搜索的关键词", min_length=1)
            max_results: int = Field(default=5, description="最大返回结果数")
            tags: list[str] | None = Field(default=None, description="过滤标签")
        
        # 模拟 LLM 返回的 JSON 数据(通常是字符串)
        llm_raw_output = '{"query": "Agent 开发", "max_results": 10, "tags": ["AI", "Python"]}'
        
        # ✅ Pydantic 自动将 JSON 解析为 Python 对象,并进行类型校验
        # 如果 LLM 返回的 max_results 是字符串 "10",Pydantic 会自动将其转为 int
        request_obj = SearchRequest.model_validate_json(llm_raw_output) 
        
        print(request_obj.query)       # 输出: Agent 开发
        print(type(request_obj.max_results)) # 输出: <class 'int'>

         

  3. 常用数据处理:Agent 的“消化系统”
    1. agent 的数据处理主要围绕着“字典/JSON 的解析、上下文的裁剪、文本的清洗”
    • 内置 json 模块:Agent 和外部系统交互的通用语言,
      • 常用的函数:json.loads() 将 JSON 字符串 解析为 Python 对象 (dict/list)(注和Pydantic 区别是json.loads() 只负责把 JSON 字符串变成 Python 字典,它不关心内容对不对;而 Pydantic 在解析的同时,完成了校验、类型转换和结构化三件事)
      • json.dumps()将 Python 对象 序列化为 JSON 字符串;
    • 如何处理非标准的 json 对象(处理脏数据)
      • 方案一:正则提取(最轻量,推荐首选)
        import re
        import json
        
        def safe_json_loads(raw_text: str) -> dict:
            """从 LLM 的脏输出中安全提取并解析 JSON"""
            
            # 1. 尝试去除 Markdown 代码块标记
            # 匹配 ```json ... ``` 或 ``` ... ```
            md_pattern = r'```(?:json)?\s*\n?(.*?)\n?\s*```'
            match = re.search(md_pattern, raw_text, re.DOTALL)
            if match:
                raw_text = match.group(1).strip()
            
            # 2. 如果没匹配到代码块,尝试找第一个 { 和最后一个 } 之间的内容
            if not raw_text.startswith('{'):
                brace_match = re.search(r'\{.*\}', raw_text, re.DOTALL)
                if brace_match:
                    raw_text = brace_match.group(0)
            
            # 3. 尝试解析
            return json.loads(raw_text)
        
        
        # 测试各种脏输入
        dirty_outputs = [
            '```json\n{"query": "AI"}\n```',
            '好的,结果如下:{"query": "AI"} 请查收',
            '{"query": "AI"}',  # 干净的也能处理
        ]
        
        for output in dirty_outputs:
            result = safe_json_loads(output)
            print(f"✅ 解析成功: {result}")

         

      • Pydantic 容错(最稳健,生产级推荐)
        from pydantic import BaseModel, ValidationError
        import re
        
        class SearchRequest(BaseModel):
            query: str
            max_results: int = 5
        
        def parse_llm_output(raw_text: str) -> SearchRequest:
            """带容错的 LLM 输出解析"""
            try:
                # Pydantic v2 的 model_validate_json 比 json.loads 更宽容
                return SearchRequest.model_validate_json(raw_text)
            except ValidationError:
                pass
            
            # 回退:用正则提取后再试
            extracted = re.search(r'\{.*\}', raw_text, re.DOTALL)
            if extracted:
                return SearchRequest.model_validate_json(extracted.group(0))
            
            raise ValueError(f"无法从 LLM 输出中提取有效 JSON: {raw_text[:200]}")

         

      • json_repair:自动修复几乎所有常见 JSON 错误
        pip install json_repair
        from json_repair import repair_json
        
        broken = "{'key': 'value',}"  # 单引号 + 尾随逗号
        fixed = repair_json(broken, return_objects=True)  # 直接返回 dict
        print(fixed)  # {'key': 'value'}

         

  • LLM api 交互
  1. Prompt(提示词)
    • system prompt:开发者预设的角色和行为约束,比如"你是一个后端开发"
    • user prompt:用户当前输入的具体问题或任务
    • prompt的质量直接决定输出质量
  2. token(词元)是模型处理文本的最小单位,也是计费和上下文容量的基本度量
    • 1个token约等于0.75个单词,约等于1个常用汉字
    • 不同模型的tokenizer独立训练,同一段文本在不同的模型中切分结果可能不同
    • 一次调用的消耗=输入token+输出token
  3. context window(上下文窗口)是模型本轮对话能看到的全部信息(system prompt +历史对话+工具返回结果等),而context window 是这些信息能容纳最大token数上限
    • 不同模型窗口大小差异很大:8k/32k/128k/1m等
    • 超出窗口的信息会被“遗忘”,这也是rag(检索增强生成)技术存在的意义
  4. Functing calling (工具调用)是让大模型从“只会说”变成“能做事”的关键能力,核心流程是:
    • 定义工具说明书(json schema):告诉模型有哪些工具可用,参数是什么
    • 模型决策:模型根据用户问题,返回“要调用哪个工具,传什么参数”的结构化指令
    • 应用层执行:你的代码真正去调用API/函数
    • 结果回灌:将执行结构返回给模型,模型根据此生成最终回答
  5. streaming(流式输出)是指模型不等待完整回答生成后再一次性返回,而是逐token/逐句实时推送给客户端,好处是:
    • 用户感知延迟大幅降低(不用干等);
    • 可以实时展示工具调用进度(如“正在查询天气”->"已获取结构"->正在生产建议);
    • 技术实现通常基于SSE(Server-sent events)
  • 百炼(以及所有大模型 API)绝对不会帮你执行任何外部工具,它做的事情只有三件:
    • 读懂说明书:根据你传的 TOOLS JSON Schema,知道有哪些工具、参数是什么
    • 决定调不调 + 传什么参:根据用户问题和对话历史,判断是否需要调用工具,如果需要,就返回一个包含函数名和参数的结构化数据(tool_calls)
    • 组织最终回答:当你把工具的真实返回结果以 role="tool" 的消息回传后,模型根据这个结果生成自然语言回答
      import json
      import requests
      from openai import OpenAI
      
      # ===== 配置 =====
      client = OpenAI(
          api_key="sk-你的API_Key",
          base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
      )
      MODEL = "glm-5.2"
      
      # ===== 1) 工具说明书 =====
      TOOLS = [{
          "type": "function",
          "function": {
              "name": "get_weather",
              "description": "根据用户提供的城市名查询该城市当前天气",
              "parameters": {
                  "type": "object",
                  "properties": {
                      "city": {"type": "string", "description": "城市名, 如 北京"}
                  },
                  "required": ["city"]
              }
          }
      }]
      
      # ===== 2) 工具的真实实现(改成调真实API) =====
      def get_weather(city):
          """调用和风天气API,返回真实天气数据"""
      
          # 第一步:根据城市名查城市ID
          geo_url = f"https://geocoding.qweather.com/v1/city/lookup?location={city}&key=你的和风天气Key"
          geo_resp = requests.get(geo_url).json()
      
          if geo_resp["code"] != "200":
              return {"error": f"找不到城市:{city}"}
      
          location_id = geo_resp["location"][0]["id"]
          location_name = geo_resp["location"][0]["name"]
      
          # 第二步:根据城市ID查实时天气
          weather_url = f"https://devapi.qweather.com/v7/weather/now?location={location_id}&key=你的和风天气Key"
          weather_resp = requests.get(weather_url).json()
      
          if weather_resp["code"] != "200":
              return {"error": "天气查询失败"}
      
          now = weather_resp["now"]
          return {
              "city": location_name,
              "temp": now["temp"] + "°C",
              "feels_like": now["feelslike"] + "°C",
              "humidity": now["humidity"] + "%",
              "wind": now["wind_dir"] + " " + now["wind_speed"] + "km/h",
              "condition": now["text"],
          }
      
      TOOL_IMPL = {"get_weather": get_weather}
      
      # ===== 3) Agent 工具调用循环(完全不用改) =====
      def agent_loop(messages, max_turns=5):
          for turn in range(max_turns):
              print(f"\n--- 第 {turn + 1} 轮调用模型 ---")
      
              response = client.chat.completions.create(
                  model=MODEL,
                  messages=messages,
                  tools=TOOLS,
              )
      
              msg = response.choices[0].message
      
              if not msg.tool_calls:
                  print(f"模型最终回答: {msg.content}")
                  return msg.content
      
              for call in msg.tool_calls:
                  fn_name = call.function.name
                  fn_args = json.loads(call.function.arguments)
                  print(f"🔧 调用工具: {fn_name}({fn_args})")
      
                  fn = TOOL_IMPL[fn_name]
                  result = fn(**fn_args)
                  print(f"📦 工具返回: {result}")
      
                  messages.append(msg)
                  messages.append({
                      "role": "tool",
                      "tool_call_id": call.id,
                      "content": json.dumps(result, ensure_ascii=False)
                  })
      
          return "已达最大调用次数,终止"
      
      # ===== 4) 运行 =====
      if __name__ == "__main__":
          messages = [{"role": "user", "content": "北京天气怎么样?"}]
          result = agent_loop(messages)
          print("\n✅ 最终结果:", result)

       

 

  1. 感知模块(输入口、获取多模态信息并转换)
    • 黑板理论(大模型的context window是一块面积有限的黑板,如果不加管理,最早的关键信息会被后续对话擦除)
    • 工程化手段:
      • System prompt(人设注入):锁定黑板顶端,固化“资深专家”人设;
      • Context Management(记忆剪枝):定期压缩历史记录,剔除寒暄,保留关键结论;
    • AI的知识来源与记忆管理
      • 把和用户的对话存在知识库里,企业的私有知识也存在知识库里面,把用户的问题转换成向量,去向量知识库里面查找,找到相关的片段,就把相关的资料和企业的私有资料拼接在一起交给大模型再回答(RAG技术检索增强生成)

                           1781445679447

  1. 大脑模块(思考中枢,负责决策、推理与规划)
  2. 行动模块(输出端,调用工具与环境互动)
  3. 多智能体合作(不同的专业任务需要不一样的协同方式)
    1. 上下级协同

      image

    2. 师生式协同

      image

    3. 竞争式协同

      image

       适合开放性的复杂任务

  4. 大模型应用场景(三合一叫多模态模型)
    1. 自然语言处理(NLP)
    2. 语音处理(SLP)
    3. 图像视频处理
  5. gradio 轻量webUI ai简单前端交互
    import  gradio as gr
    import numpy as np
    import cv2
    #功能实现
    def image_to_skectch(image):
        gray_image = image.convert("L")
        invered_image = 255 - np.array(gray_image)
        blurred = cv2.GaussianBlur(invered_image, (21, 21), 0)
        invered_blurred = 255 - blurred
        pencil_sketch = cv2.divide(np.array(gray_image), invered_blurred, scale=255.0)
        return pencil_sketch
    
    
    #界面配置
    demo = gr.Interface(
        fn=image_to_skectch,
        inputs = [gr.Image(label="上传图片",type="pil")],
    
    
        outputs = [gr.Image(label="铅笔画")],
        title="图像转铅笔画",
        description="将上传的图片转为铅笔画"
    
    )
    
    demo.launch()

     

  6. 提示词工程(prompt engineering)是一项通过优化提示词(prompt)和生成策略,从而获取更好的模型返回结构的工程技术

    image

     

    1. 应用可以设置自己的知识库,如果知识库没有就不返回(可以做自己公司业务的ai智能体)

      image

       json加【】 和[ ] 时可以自动转换类型,如果不加识别不出来,除非给实例examples

  7.  react 理论

image

 8.agent的划分

image

 

image

 8.RAG

  1.  纠正性RAG(CRAG)是一种用于RAG的策略,它包含对检索文档进行自我反思/评分image
  2. self-rag是RAG的一种策略,它包含对检索到的文档和生成内容进行自我反思/自我评分

image

 简单if判断反射(简单反射代理)---》加上记忆(基于模型的反射代理)---》加上目标有规划能力(目标性代理)---》考虑实现目标的最佳方式 如边际效用递减(效用型代理)----》从过去经验中学习,由学习元素、评议员、性能元素和问题生成器(学习型代理)

 

posted @ 2026-09-06 20:21  卡皮巴拉  阅读(22)  评论(0)    收藏  举报