【大模型学习笔记】Day4-6 智能体入门级搭建

前言:这几天学习理论知识较少,跟着网上的视频做了一些代码试写,从开始的调用大模型逐渐进阶到搭建简单的agent,实现提示词工程、agent工具开发、简单agent开发

轻松一刻:我最讨厌的两件事:一是写注释,二是别人不写注释。程序员最怕听到的三个字不是“有Bug”,而是……“你注释呢?”

知识点学习

工具调用与Agent类知识点

知识点1:什么是Function Calling(工具调用)?它在Agent系统中起什么作用?

Function Calling 是让大模型在对话中识别需要调用外部工具或函数,并生成结构化调用参数的能力。它在 Agent 系统中起到连接模型与外部世界的作用,让模型能获取实时数据、执行操作,从而完成单靠模型本身无法完成的任务。

知识点2:什么是ReAct模式?它与单纯的工具调用有什么不同?

ReAct 模式是让模型交替进行「推理」和「行动」:先思考下一步该做什么,再调用工具获取结果,然后根据结果继续推理。与单纯工具调用相比,ReAct 多了推理环节,能根据中间结果动态调整策略,处理更复杂的多步任务。

知识点3:什么是工具(Tool)描述?如何正确编写工具描述以提高模型调用的准确性?

工具描述是告诉模型「这个工具是做什么的、什么时候该用、参数怎么填」的说明文字。编写时要写清楚工具的功能适用场景参数含义格式要求,语言要简洁明确,避免歧义,这样模型才能准确判断何时调用以及如何传参。

知识点4:多工具场景下,模型如何决定调用哪个工具?优先级如何设定?

模型会根据用户意图和各个工具的描述,选择最匹配的那个工具来调用。优先级可以通过在工具描述中明确使用条件适用场景重要程度来设定,描述越清晰、条件越明确,模型就越容易做出正确选择。

知识点5:什么是工具调用循环(Tool Call Loop)?如何防止无限循环?

工具调用循环是指模型反复调用工具、获取结果、再继续调用的过程,直到完成任务。防止无限循环可以设置最大调用次数、增加超时机制,或在结果中检测到无进展时主动终止循环。

LangChain与框架类知识点

知识点6:LangChain的核心组件有哪些?它们分别解决什么问题?

LangChain 的核心组件包括模型(Model)提示词(Prompt)记忆(Memory)工具(Tool)链(Chain)。模型负责与大模型交互,提示词负责组织输入,记忆负责保存对话历史,工具负责连接外部能力,链负责把多个步骤串联起来完成复杂任务。

知识点7:什么是LCEL(LangChain Expression Language)?它的优势是什么?

LCEL 是 LangChain 提供的一种声明式表达式语言,用简洁的管道语法把组件串联成执行流程。它的优势是代码简洁、易于组合和复用,支持流式输出并行执行异步调用,还能自动处理重试回退,让复杂流程的构建和维护更高效。

知识点8:什么是Chain?Chain和Agent有什么区别?

Chain 是把多个处理步骤按固定顺序串联起来的执行流程,每一步做什么是预先定义好的。Agent 则更灵活,它能根据用户意图动态决定调用哪些工具、按什么顺序执行。简单说,Chain 是固定流程,Agent 是自主决策流程

知识点9:什么是Vector Store?在RAG系统中它扮演什么角色?

Vector Store 是专门存储和检索向量数据的数据库,把文本等内容转换成向量后存入其中,并支持按相似度快速检索。在 RAG 系统中,它负责保存知识库的向量索引,当用户提问时,系统先从 Vector Store 中检索出最相关的片段,再交给大模型生成回答,从而提升回答的准确性时效性

知识点10:什么是Embedding?如何选择Embedding模型?

Embedding 是把文本、图片等内容转换成高维向量表示的过程,让语义相近的内容在向量空间中距离更近。选择 Embedding 模型时,要考虑模型的语义理解能力支持的语言向量维度推理速度成本,并结合实际业务场景和检索效果进行测试对比。

实战代码

1、天气查询工具开发

import os
import json
import requests
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage
from dotenv import load_dotenv
import ssl
from requests.adapters import HTTPAdapter
import gradio as gr

load_dotenv()

class TLSAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        kwargs['ssl_version'] = ssl.PROTOCOL_TLSv1_2  # 强制 TLS 1.2
        return super().init_poolmanager(*args, **kwargs)

@tool
def get_weather(city: str) -> str:
    """查询指定城市的当前天气信息,包括温度、天气状况、湿度、风速。
    当用户询问某个城市或地区的天气、气温、冷不冷、热不热、下不下雨时,使用此工具。
    Args:
        city: 要查询天气的城市名称,例如"北京"、"上海"、"长沙"、"广州"
    """
    print("需要查询的城市:", city)
    try:
        url = f"https://wttr.in/{city}?format=j1&lang=zh"
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
            ""
        }
        # 使用自定义适配器
        session = requests.Session()
        session.mount('https://', TLSAdapter())
        resp = session.get(url, timeout=10, headers=headers)

        # resp = requests.get(url, timeout=10, headers=headers)
        print("爬取成功")
        resp.raise_for_status()
        data = resp.json()
        # print(data)
        current = data["current_condition"][0]
        area = data["nearest_area"][0]
        return (
            f"{area['areaName'][0]['value']}天气\n"
            f"天气:{current['weatherDesc'][0]['value']}\n"
            f"温度:{current['temp_C']}°C(体感{current['FeelsLikeC']}°C)\n"
            f"湿度:{current['humidity']}%\n"
            f"风速:{current['windspeedKmph']}km/h"
        )
    except Exception as e:
        print(f"请求失败,错误信息:{e}")
        return (
            f"{city}天气(模拟数据,网络不通时显示)\n"
            "天气:晴,温度:28°C(体感30°C),湿度:65%,风速:12km/h"
        )
tools = [get_weather]
tool_map = {t.name: t for t in tools}

# --- 初始化 LLM 并绑定工具 ---

llm = ChatOpenAI(
    model=os.getenv("DATA_MODEL"),
    base_url=os.getenv("DATA_BASE_URL"),
    api_key=os.getenv("DATA_API_KEY"),
    temperature=0,
)

llm_with_tools = llm.bind_tools(tools)

# --------------ReAct 循环(核心!)-------------------
def run_agent(user_input: str, verbose: bool = True) -> str:
    """
    Args:
        user_input(用户的提问)
        verbose:是否记录每一步,此处默认为True
    """
    messages = [HumanMessage(content=user_input)]
    # 此处记录用户问题以及每一步循环的ai回答

    for step in range(5):
        response: AIMessage = llm_with_tools.invoke(messages)
        messages.append(response)
        if not response.tool_calls:
            return response.content
        # 此处判断,如果大模型没有调用任何工具,说明大模型觉得获得的信息已经够了,可以直接回答用户了,返回结果
        if verbose:
            for tc in response.tool_calls:
                print(f"【步骤{step+1}】调用工具:{tc['name']},参数:{json.dumps(tc['args'], ensure_ascii=False)}")

        for tc in response.tool_calls:
            tool_result = tool_map[tc["name"]].invoke(tc["args"])
            if verbose:
                print(f"【步骤{step+1}】工具返回:{str(tool_result)[:60]}...")
            messages.append(ToolMessage(content=str(tool_result), tool_call_id=tc["id"]))
    return "处理次数超限,请换个问题。"


demo = gr.Interface(fn=run_agent, inputs="text", outputs="text")
if __name__ == "__main__":
    demo.launch()

其中核心代码如下:

封装了一个工具用@tool装饰,在函数定义里写清楚工具描述,避免歧义(这一步很重要)

在工具get_weather里用requests爬取天气网站信息,让大模型有了能获取天气的能力

@tool
def get_weather(city: str) -> str:
    """查询指定城市的当前天气信息,包括温度、天气状况、湿度、风速。
    当用户询问某个城市或地区的天气、气温、冷不冷、热不热、下不下雨时,使用此工具。
    Args:
        city: 要查询天气的城市名称,例如"北京"、"上海"、"长沙"、"广州"
    """
    print("需要查询的城市:", city)
    try:
        url = f"https://wttr.in/{city}?format=j1&lang=zh"
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
            ""
        }
        # 使用自定义适配器
        session = requests.Session()
        session.mount('https://', TLSAdapter())
        resp = session.get(url, timeout=10, headers=headers)

        # resp = requests.get(url, timeout=10, headers=headers)
        print("爬取成功")
        resp.raise_for_status()
        data = resp.json()
        # print(data)
        current = data["current_condition"][0]
        area = data["nearest_area"][0]
        return (
            f"{area['areaName'][0]['value']}天气\n"
            f"天气:{current['weatherDesc'][0]['value']}\n"
            f"温度:{current['temp_C']}°C(体感{current['FeelsLikeC']}°C)\n"
            f"湿度:{current['humidity']}%\n"
            f"风速:{current['windspeedKmph']}km/h"
        )
    except Exception as e:
        print(f"请求失败,错误信息:{e}")
        return (
            f"{city}天气(模拟数据,网络不通时显示)\n"
            "天气:晴,温度:28°C(体感30°C),湿度:65%,风速:12km/h"
        )
tools = [get_weather]
tool_map = {t.name: t for t in tools}

2、天气查询工具进阶(agent开发,让大模型有短期记忆,能记住用户前面所说的话)

在1的基础上调用改为如下方代码

这段代码在1的基础上,定义了一个agent,并通过定义类WeatherChat的办法,实现循环调用和清空记忆,其中self.messages里会存储着每一次的对话,让大模型在每次调用时都知道之前说了什么,在每轮循环里用agent.invoke的方式存储每一轮对话。


# 在001的基础上创建1个带记忆的agent:
# create_agent 是langchain给的官方agent创建工具
agent = create_agent(
    model= llm,
    tools = tools,
    system_prompt = """
        你是天气小助手,专业友好。
            1、问天气必须调用get_wheather工具,不要编造
            2、问答简洁自然,根据温度给穿衣建议(<10度保暖,>30度防暑)
            3、用户没说城市时礼貌询问
            4、非天气问题礼貌说明你主要提供天气服务
    
    """,

)

class WeatherChat:
    """多轮对话会话:自己维护消息历史"""
    def __init__(self):
        self.messages = []  # 消息列表,存所有历史
    def send(self, user_input: str) -> str:
        """发送用户消息,返回助手回答"""
        # 1. 把用户消息加入历史
        self.messages.append(HumanMessage(content=user_input))

        # 2. 调用agent(传入完整历史)
        result = agent.invoke({"messages": self.messages})

        # 3. 用agent返回的完整消息列表更新历史(包含工具调用过程)
        self.messages = result["messages"]

        # 4. 最后一条就是最终回答
        return self.messages[-1].content

    def clear(self):
        """清空对话"""
        self.messages = []

if __name__ == "__main__":
    print("=" * 50)
    print("天气助手 进阶版(多轮对话版)")
    print("命令:quit 退出 | clear 清空对话")
    print("=" * 50)

    chat = WeatherChat()

    while True:
        user_input = input("\n你: ").strip()
        if not user_input:
            continue
        if user_input.lower() in ("quit", "exit", "q"):
            print("再见!")
            break
        if user_input.lower() == "clear":
            chat.clear()
            print("对话已清空,重新开始~")
            continue

        answer = chat.send(user_input)
        print(f"助手: {answer}")

结果截图:

写到这里,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值