网站建设的什么是开发实施注意什么,怎么开发游戏软件赚钱,网站系统优化,网站建设 作用1. 为什么你的大模型“一问三不知”#xff1f;从DeepSeek的局限说起 最近DeepSeek确实火得不行#xff0c;我身边不少以前对AI不感冒的朋友#xff0c;现在聊天都开始问“你用DeepSeek了吗#xff1f;”。说实话#xff0c;DeepSeek在推理能力上真的把国产大模型拉到了一…1. 为什么你的大模型“一问三不知”从DeepSeek的局限说起最近DeepSeek确实火得不行我身边不少以前对AI不感冒的朋友现在聊天都开始问“你用DeepSeek了吗”。说实话DeepSeek在推理能力上真的把国产大模型拉到了一个新高度成本还低用起来确实香。但不知道你有没有遇到过这种情况你兴冲冲地问DeepSeek“今天菜市场的苹果多少钱一斤”它要么给你一个过时的、训练数据里的价格要么干脆告诉你“我无法获取实时信息”。这感觉就像你请了个百科全书式的学霸当生活助理结果他连楼下超市的菜价都查不到是不是有点憋屈这就是大模型自身的一个核心局限——知识固化和缺乏实时感知。像DeepSeek这样的大模型它的知识边界基本就停留在它最后一次训练数据更新的那个时间点。对于水果价格、天气、交通路况、电影排片这些瞬息万变的“垂直领域知识”和“实时信息”它就是个“睁眼瞎”。你直接调用它的API就像让一个闭门造车的学者去菜市场买菜他可能能跟你侃侃而谈苹果的营养价值但具体价格对不起不知道。那怎么办呢难道我们只能接受一个“知识渊博但脱离现实”的助手吗当然不是。每当我们遇到这种需要模型自己做判断、自己调用外部工具、自己决定下一步怎么走的复杂任务时就该Agent智能体登场了。你可以把Agent理解成大模型的“外置大脑”和“手脚”。大模型本身负责思考和规划而Agent则负责给它配上各种“传感器”查询工具和“执行器”操作工具让它能真正“动起来”去感知和改变外部世界。简单来说我们不是要换掉DeepSeek这个聪明的“大脑”而是要给它搭建一个更强大的“身体系统”。而这个搭建过程的核心框架就是我们今天要实战的ReAct。2. 拆解ReAct让大模型学会“三思而后行”ReAct这个名字听起来挺技术其实它的理念非常直观就是Reasoning推理和Acting行动的结合。这就像教一个聪明但缺乏经验的孩子解决问题不能直接给答案而是要引导他“先想再做再看结果再想下一步”。我举个例子你就明白了。假设你让一个只懂书本知识的孩子去帮你买咖啡。他可能知道咖啡是什么但不知道去哪买、怎么买。传统的单一指令“去买杯咖啡”肯定会失败。而ReAct的引导过程是这样的Thought思考孩子先想“我需要一杯咖啡。我应该先去找到卖咖啡的地方。我可以使用手机地图工具。”Action行动他打开手机地图APP搜索“最近的咖啡馆”。Observation观察地图显示步行200米有一家星巴克。Thought思考孩子接着想“我找到了地点。现在我需要知道怎么买我可以用支付工具。”Action行动他走向星巴克用手机支付买了一杯美式。Observation观察成功买到咖啡。Thought思考“任务完成可以回去交差了。”Final Answer最终答案把咖啡交给你。看到了吗ReAct通过一个固定的“思考-行动-观察”循环把一个大问题买咖啡拆解成了一系列小步骤找地点、支付并且在每一步都让“大脑”大模型根据上一步的“观察”结果来决定下一步的“行动”。这个框架完美地弥补了大模型缺乏执行力和实时感知的短板。在技术实现上ReAct通常通过一段精心设计的Prompt提示词来驱动大模型进入这个循环。这段Prompt会明确告诉模型“嘿你现在是个Agent你有一些工具可以用。当你遇到问题时请按照‘Thought/Action/Observation’这个格式来思考和行动。” 我们后面会看到这段堪称“封神”的Prompt模板。3. 实战准备搭建你的智能助手开发环境光说不练假把式咱们直接动手用DeepSeek和ReAct构建一个能查水果价格的智能生活助手。别担心我会把每一步都掰开揉碎了讲就算你是刚接触Python的新手跟着做也能跑起来。3.1 第一步获取DeepSeek的“通行证”API Key首先你得能调用DeepSeek模型。虽然DeepSeek官方提供了API但考虑到稳定性和易用性我强烈推荐通过阿里云百炼这样的平台来调用。它提供了完全兼容OpenAI API协议的DeepSeek模型服务稳定性和速度都更有保障对于个人开发者和小项目非常友好。操作很简单打开阿里云官网注册并登录。进入“百炼”产品页面在人工智能与机器学习分类下能找到。按照指引开通服务。通常新用户会有免费的额度足够我们做实验了。在控制台找到“API-KEY管理”创建一个新的API Key并妥善保存。这个Key就像你家的门禁卡千万别泄露。拿到API Key后我们在项目根目录创建一个名为.env的文件把Key放进去DASHSCOPE_API_KEY你的阿里云百炼API Key这样做的目的是把敏感信息隔离不写死在代码里更安全也更灵活。3.2 第二步安装必要的Python“工具箱”我们需要几个Python库来帮忙。打开你的终端命令行创建一个新的项目文件夹然后执行下面的安装命令。我建议你使用pip安装如果速度慢可以加上清华源-i https://pypi.tuna.tsinghua.edu.cn/simple。# 创建并进入项目目录 mkdir smart_life_assistant cd smart_life_assistant # 安装核心依赖 pip install openai python-dotenvopenai虽然名字叫openai但这个库实现了OpenAI的API调用协议。因为阿里云百炼兼容这个协议所以我们可以直接用这个库来调用DeepSeek非常方便。python-dotenv用来读取我们刚才创建的.env文件中的环境变量。安装完成后你的基础环境就准备好了。接下来我们来打造Agent最核心的部分——工具。4. 打造Agent的“瑞士军刀”定义与实现工具工具Tools是Agent的灵魂是它感知和操作世界的“手脚”。工具可以是任何东西一个查询天气的API、一个计算器函数、一个控制智能家居的接口或者像我们例子中一样一个查询水果价格的模拟函数。4.1 编写你的第一个工具函数我们来创建一个tools.py文件。这里我们会实现一个模拟查询水果单价的函数。在真实场景中这个函数内部可能是去调用一个生鲜电商的API但为了演示我们先“Mock”模拟一下。# tools.py def query_fruit_unit_price(fruit_name: str) - str: 查询水果单价模拟函数 :param fruit_name: 水果名称比如“苹果”、“香蕉” :return: 水果的单价字符串 # 一个简单的模拟数据库 price_map { 苹果: 5.8, # 模拟苹果5.8元/斤 香蕉: 3.2, # 模拟香蕉3.2元/斤 橘子: 4.5, 草莓: 25.0, } # 返回查询结果如果水果不存在则返回提示 return price_map.get(fruit_name, 抱歉暂未收录该水果的价格信息。)这个函数很简单你传入一个水果名字它返回一个模拟的价格。注意我特意把返回值设计成字符串这是因为大模型处理文本更在行。同时函数有清晰的文档字符串这很重要不仅是为了我们自己看稍后也会用来告诉大模型这个工具是干嘛的。4.2 如何告诉大模型“你会用什么工具”光有函数不行我们得用一种大模型能理解的方式告诉它“嗨我这里有个工具叫query_fruit_unit_price你可以用它来查水果价格用法是把水果名字传给我。”这就需要用到工具描述Tool Description。我们继续在tools.py文件中添加# tools.py (续) # 定义可供大模型调用的工具列表 TOOLS_DESCRIPTION [ { name: query_fruit_unit_price, # 工具名称必须和函数名一致 description: 当用户询问水果价格或者问题中涉及需要知道水果单价来计算总价时使用此工具。它可以查询指定种类水果的每斤/每个的单价。, # 清晰描述工具用途和场景 parameters: { # 描述工具需要的参数 type: object, properties: { fruit_name: { type: string, description: 水果的具体名称例如‘苹果’、‘香蕉’、‘草莓’。请确保名称是常见的中文水果名。, } }, required: [fruit_name] # 指明哪些参数是必须的 }, }, ]这个描述是一个标准的JSON结构它详细定义了工具的“使用说明书”。description字段写得越清晰、场景越具体大模型就越能准确地判断在什么时候该调用这个工具。parameters部分则严格定义了调用格式这能极大减少大模型“乱调用”或生成错误参数的情况。5. 构建Agent的“思维引导器”ReAct Prompt工程这是整个项目的核心魔法所在。我们需要一段高质量的Prompt来“催眠”DeepSeek让它进入ReAct的思考模式。幸运的是我们不需要从零开始发明轮子。LangChain社区已经提供了一个经过千锤百炼的ReAct Prompt模板我们稍作调整就能用。5.1 解析“封神”的Prompt模板我们来创建一个prompt.py文件并把这段核心模板放进去。我会逐段给你解释它的妙处。# prompt.py from typing import List, Dict # ReAct Prompt 核心模板 REACT_PROMPT_TEMPLATE 你是一个智能居家生活助手擅长通过使用工具来解答用户关于生活信息的问题。 你的思考必须严格遵循以下格式。 TOOLS: ------ 你可以使用以下工具 {tools} 为了使用工具你必须严格按照以下格式进行思考和执行Thought: 我需要思考当前是否需要使用工具来解决问题如果需要是哪个工具 Action: 需要执行的动作必须是 [{tool_names}] 中的一个 Action Input: 传递给工具的输入参数必须是合法的JSON格式然后你需要等待用户或系统返回给你一个 Observation观察结果也就是工具执行的结果。 ...这个 Thought/Action/Action Input/Observation 循环可以根据需要重复多次 当你有了最终答案可以回复给用户时或者你确定不需要使用任何工具时你必须使用以下格式Thought: 我需要思考当前是否需要使用工具来解决问题不需要。 Final Answer: [你给用户的最终回答]现在开始处理新的用户请求吧 新输入: {input} 这段Prompt干了以下几件关键事设定角色System Instruction开头就告诉模型“你是一个智能居家生活助手”给它定了性。明确工具列表{tools}是一个占位符运行时会被替换成我们之前定义的TOOLS_DESCRIPTION的详细文本。这让模型知道它“手头有什么武器”。规定思维格式这是最核心的部分。它强制模型必须按照“Thought - Action - Action Input”或者“Thought - Final Answer”的固定格式来输出。这种结构化输出是我们程序能够自动解析和执行的基石。交代任务最后把用户的问题通过{input}占位符喂给模型。5.2 动态组装Prompt我们需要一个函数把系统指令、用户问题、工具描述等动态地填充到这个模板里生成最终的Prompt。# prompt.py (续) def build_react_prompt(instructions: str, query: str, tool_desc: List[Dict], tool_names: List[str]) - str: 构造完整的ReAct Prompt :param instructions: 系统指令定义助手角色 :param query: 用户的提问 :param tool_desc: 外部工具描述列表 :param tool_names: 外部工具名称列表 :return: 组装好的React Prompt字符串 # 将工具描述列表格式化成清晰的文本 tools_text for tool in tool_desc: tools_text f- 工具名称{tool[name]}\n tools_text f 描述{tool[description]}\n tools_text f 参数{tool[parameters]}\n\n # 将工具名称列表连接成字符串用于Action部分的提示 tool_names_str , .join(tool_names) # 使用模板进行格式化 full_prompt REACT_PROMPT_TEMPLATE.format( instructionsinstructions, toolstools_text, tool_namestool_names_str, inputquery ) return full_prompt这个函数就像个自动装配车间把各个零件指令、问题、工具严丝合缝地装进ReAct这个“思维框架”里产出一个可以直接喂给大模型的完整指令。6. 连接大脑封装DeepSeek模型调用现在“思维框架”和“工具”都准备好了我们需要请出“大脑”——DeepSeek模型。我们来创建一个llm.py文件对模型调用做一个简单的封装让后续的Agent逻辑更清晰。# llm.py import os from typing import List, Dict import dotenv from openai import OpenAI class LLM: def __init__(self, model_name: str deepseek-v3): 初始化LLM客户端 :param model_name: 模型名称默认为 deepseek-v3 # 加载包含API Key的.env文件 dotenv.load_dotenv() # 创建OpenAI兼容的客户端指向阿里云百炼的端点 self.client OpenAI( api_keyos.getenv(DASHSCOPE_API_KEY), # 从环境变量读取Key base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1 # 阿里云百炼的兼容端点 ) self.model_name model_name def chat(self, messages: List[Dict]) - str: 发送消息到DeepSeek模型并获取回复 :param messages: 消息列表格式为 [{role: user, content: ...}, ...] :return: 模型返回的文本内容 try: response self.client.chat.completions.create( modelself.model_name, messagesmessages, temperature0.1, # 温度设低一点让输出更稳定、更可预测 streamFalse # 非流式输出一次性拿到完整结果 ) return response.choices[0].message.content except Exception as e: print(f调用大模型时出错: {e}) return None这个封装类做了几件事安全地加载API Key、配置好阿里云百炼的接入点、提供了一个简单的chat方法。注意我把temperature参数设得比较低0.1这是因为在Agent场景下我们希望模型的输出尽可能稳定、可预测减少“胡言乱语”破坏我们设定的输出格式。7. 让Agent“活”起来核心执行逻辑与解析最激动人心的部分来了我们将创建一个agent.py文件把前面所有的模块像拼乐高一样组装起来并实现ReAct的核心循环逻辑。7.1 初始化与启动# agent.py import json import re from llm import LLM from prompt import build_react_prompt from tools import TOOLS_DESCRIPTION, query_fruit_unit_price def main(): # 1. 定义助手角色和用户问题 system_instructions 你是一个热心且专业的居家生活助手擅长通过使用工具查询信息来帮助用户解决生活问题比如计算购物花费。 user_query 我想买2斤苹果和3斤香蕉请问一共需要多少钱 # 2. 准备工具信息 tool_descriptions TOOLS_DESCRIPTION tool_names [tool[name] for tool in tool_descriptions] # 提取所有工具名这里是 [query_fruit_unit_price] # 3. 构建ReAct Prompt prompt build_react_prompt( instructionssystem_instructions, queryuser_query, tool_desctool_descriptions, tool_namestool_names ) print( 构建的完整Prompt ) print(prompt) print( * 50) # 4. 初始化大模型 llm LLM(model_namedeepseek-v3) # 使用 deepseek-v3 模型 # 5. 初始化对话历史第一条消息就是我们构建的完整Prompt conversation_history [{role: user, content: prompt}]这里我们设定了场景用户要买2斤苹果和3斤香蕉问总价。系统指令强调了助手要“使用工具”。然后我们调用之前写好的函数生成了一个巨长的、包含所有规则的Prompt并把它作为第一条用户消息准备发送给DeepSeek。7.2 实现ReAct循环思考、行动、观察接下来是核心的循环逻辑。我们需要不断让模型思考解析它的输出调用工具再把结果反馈给它直到它给出最终答案。# agent.py (续 main 函数) max_steps 10 # 防止意外无限循环设置最大步数 current_step 0 while current_step max_steps: current_step 1 print(f\n--- 第 {current_step} 轮推理 ---) # A. 调用大模型进行“思考” model_response llm.chat(conversation_history) if model_response is None: print(模型调用失败退出。) break print(f模型原始回复:\n{model_response}\n) # B. 解析回复判断是最终答案还是需要行动 # 首先检查是否是最终答案格式 final_answer_match re.search(rFinal Answer:\s*(.*), model_response, re.DOTALL) if final_answer_match: final_answer final_answer_match.group(1).strip() print(f✅ 任务完成最终答案: {final_answer}) break # 跳出循环任务结束 # 如果不是最终答案则尝试解析行动指令 # 使用正则表达式匹配 Thought/Action/Action Input 模式 thought_match re.search(rThought:\s*(.*?)(?\nAction:|$), model_response, re.DOTALL) action_match re.search(rAction:\s*(\w), model_response) action_input_match re.search(rAction Input:\s*({.*?}), model_response, re.DOTALL) if not (action_match and action_input_match): print(⚠️ 无法解析出有效的Action指令模型可能未遵循格式。回复内容, model_response) break tool_to_use action_match.group(1) action_input_str action_input_match.group(1) print(f解析结果 - 思考: {thought_match.group(1) if thought_match else N/A}) print(f解析结果 - 行动: 调用工具 {tool_to_use}) print(f解析结果 - 输入: {action_input_str}) # C. 执行工具调用行动 observation None try: # 将Action Input从字符串解析为Python字典 params json.loads(action_input_str) if tool_to_use query_fruit_unit_price: fruit params.get(fruit_name) if fruit: observation query_fruit_unit_price(fruit) else: observation 错误工具调用参数中未找到 fruit_name。 else: observation f错误未知的工具名称 {tool_to_use}。 except json.JSONDecodeError: observation f错误无法解析Action Input为JSON格式。原始输入: {action_input_str} except Exception as e: observation f工具执行过程中发生错误: {e} print(f工具执行观察结果 (Observation): {observation}) # D. 将观察结果作为新消息加入历史供下一轮思考 conversation_history.append({role: assistant, content: model_response}) conversation_history.append({role: user, content: fObservation: {observation}}) # 简单的防呆如果观察结果已经是最终答案或错误可以提前结束 if 错误 in observation or current_step max_steps: print( 循环结束可能由于错误或达到最大步数。) break print(\n Agent 执行结束 ) if __name__ __main__: main()这段代码是Agent的“心脏”。它在一个循环中发送Prompt给模型获取回复。解析回复用正则表达式去匹配我们规定的格式。如果找到Final Answer就输出结果并结束。如果找到Action就提取要调用的工具名和参数。执行工具根据解析出的工具名调用对应的函数这里就是query_fruit_unit_price得到结果Observation。反馈结果把Observation以固定的格式Observation: ...追加到对话历史中。开始下一轮循环模型收到Observation后会基于这个新信息进行下一轮的Thought决定下一步是继续调用工具还是给出Final Answer。7.3 运行与结果分析现在在终端运行python agent.py你会看到类似下面的输出具体文本可能因模型略有差异 构建的完整Prompt 你是一个智能居家生活助手...很长省略 新输入: 我想买2斤苹果和3斤香蕉请问一共需要多少钱 -------------------------------------------------- --- 第 1 轮推理 --- 模型原始回复: Thought: 用户想知道购买2斤苹果和3斤香蕉的总价。要计算总价我需要知道苹果和香蕉的单价。我可以使用query_fruit_unit_price工具来查询这两种水果的单价。 Action: query_fruit_unit_price Action Input: {fruit_name: 苹果} 解析结果 - 思考: 用户想知道购买2斤苹果和3斤香蕉的总价。要计算总价我需要知道苹果和香蕉的单价。我可以使用query_fruit_unit_price工具来查询这两种水果的单价。 解析结果 - 行动: 调用工具 query_fruit_unit_price 解析结果 - 输入: {fruit_name: 苹果} 工具执行观察结果 (Observation): 5.8 --- 第 2 轮推理 --- 模型原始回复: Thought: 我查询到了苹果的单价是5.8元/斤。接下来我需要查询香蕉的单价。 Action: query_fruit_unit_price Action Input: {fruit_name: 香蕉} 解析结果 - 思考: 我查询到了苹果的单价是5.8元/斤。接下来我需要查询香蕉的单价。 解析结果 - 行动: 调用工具 query_fruit_unit_price 解析结果 - 输入: {fruit_name: 香蕉} 工具执行观察结果 (Observation): 3.2 --- 第 3 轮推理 --- 模型原始回复: Thought: 我已经获得了苹果5.8元/斤和香蕉3.2元/斤的单价。现在可以计算总价苹果总价 2斤 * 5.8元/斤 11.6元香蕉总价 3斤 * 3.2元/斤 9.6元合计 11.6 9.6 21.2元。我不再需要调用工具了。 Final Answer: 购买2斤苹果和3斤香蕉总计需要21.2元。 ✅ 任务完成最终答案: 购买2斤苹果和3斤香蕉总计需要21.2元。 Agent 执行结束 看Agent完美地运行了起来。它像我们设计的那样先“思考”需要单价然后“行动”调用工具查苹果价格得到“观察”结果后再“思考”需要查香蕉价格再次“行动”最后收集齐信息后“思考”计算出结果并给出“最终答案”。整个过程完全自动化逻辑清晰。8. 避坑指南与进阶思考第一次跑通这个Demo你可能会觉得成就感满满。但作为过来人我得跟你分享几个我踩过的坑和进阶思路让你少走弯路。坑1模型选择很重要我们用的是deepseek-v3而不是推理能力更强的deepseek-r1。为什么因为ReAct框架本身已经通过Prompt提供了非常强的思维链引导。deepseek-r1本身内置了复杂的思维链CoT逻辑有时反而会和我们外部的ReAct Prompt“打架”产生一些意想不到的、不遵循格式的输出。对于这种“框架驱动型”的Agent一个听话的、能稳定遵循指令的模型往往比一个“太有想法”的模型更可靠。坑2工具描述是门艺术你给工具的description写得好不好直接决定了Agent的智商。描述要具体、场景化。比如不要只写“查询水果价格”可以写成“当用户询问水果价格或问题中涉及需要知道水果单价来计算总价时使用此工具”。好的描述能极大提升模型调用工具的准确率。坑3参数解析的可靠性我们这个Demo用了正则表达式re模块来解析模型的输出。这在格式严格遵守时没问题但模型偶尔会“抽风”输出里多一个空格、换行或者JSON格式不标准正则就可能匹配失败。更健壮的做法是使用大模型原生的Function Calling功能。像OpenAI、DeepSeek的API都支持在请求中直接定义函数工具列表模型会以标准JSON格式返回它想调用的函数名和参数几乎不会出错。这是我们这个Demo可以优化的最主要方向。坑4增加记忆和上下文我们这个Agent是“单次任务”型的问完就结束。真正的助手需要记住之前的对话。你可以在conversation_history里保留更长的历史消息注意API有Token长度限制或者引入更复杂的记忆Memory模块比如向量数据库来存储和检索长期的对话关键信息让助手真正认识你。把这个基础框架搭起来之后你能做的事情就太多了。你可以把查询水果价格的Mock函数换成真正的天气API、地图导航API、智能家居控制接口。你可以定义多个工具让Agent自己决定在什么场景下用哪个。比如用户说“明天出门用带伞吗”Agent应该自动调用天气查询工具用户说“帮我把客厅的灯打开”Agent应该调用智能家居的控制工具。一个真正多功能、自主决策的智能生活助手就是这样一步步构建起来的。