Agent 核心机制解析:基于 ReAct 模式的智能旅行助手实战

发布时间:2026/10/31 1:41:22
Agent 核心机制解析:基于 ReAct 模式的智能旅行助手实战 Agent 核心机制解析基于 ReAct 模式的智能旅行助手实战一、概述本文以chapter1_agent_demo.py为实战案例深入剖析 Agent 的核心工作机制。这是一个智能旅行助手的简化实现通过模拟工具 真实 LLM 调用展示了一个完整 Agent 的 Thought-Action-Observation 循环。学习目标理解 Agent 的ReAct工作流程掌握LLM 配置与上下文累积的原理区分系统提示词与用户提示词的作用熟悉外部工具的引入与调用流程理解循环执行的意义与实现二、ReAct 工作流程详解2.1 什么是 ReActReAct Reasoning Acting这是一种让大模型能够「思考」并「行动」的模式核心思想是用户请求 → 思考(Reason) → 行动(Action) → 观察(Observation) → 思考(Reason) → ...不断循环直到任务完成。2.2 完整工作流程图┌─────────────────────────────────────────────────────────────┐ │ ReAct 循环流程 │ └─────────────────────────────────────────────────────────────┘ ┌──────────────────┐ │ 用户请求输入 │ └────────┬─────────┘ ▼ ┌──────────────────┐ │ 构建完整上下文 │ ← prompt_history 累积历史 │ (系统提示词 │ │ 用户请求 │ │ 历史对话) │ └────────┬─────────┘ ▼ ┌──────────────────┐ │ 调用 LLM │ ← 获取 Thought Action │ OpenAI API │ └────────┬─────────┘ ▼ ┌──────────────────┐ │ 解析 Action │ │ 正则提取工具名 │ │ 和参数 │ └────────┬─────────┘ ▼ ┌──────────────────┐ │ 判断: 工具调用 │────Yes────► 调用工具 ──► 获取 Observation │ 还是结束? │ │ └────────┬─────────┘ │ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ 输出最终答案 │◄────────│ 返回循环继续思考 │ │ Finish[答案] │ └──────────────────┘ └──────────────────┘ ### 2.3 代码中的循环实现 python for i in range(5): # 最多循环5次防止无限循环 # 1. 构建上下文 full_prompt \n.join(prompt_history) # 2. 调用 LLM llm_output llm_client.generate(full_prompt, system_promptAGENT_SYSTEM_PROMPT) # 3. 解析 Action action_match re.search(rAction: (.*), llm_output, re.DOTALL) # 4. 判断结束还是继续 if action_str.startswith(Finish): break # 任务完成退出循环 else: # 调用工具获取 Observation继续循环三、LLM 配置3.1 为什么要 LLM 配置LLM 是 Agent 的「大脑」负责理解用户意图制定执行计划决定下一步行动生成最终回答3.2 代码中的 LLM 配置fromopenaiimportOpenAIclassOpenAICompatibleClient:def__init__(self,model:str,api_key:str,base_url:str):self.modelmodel# 模型标识self.clientOpenAI(# API 客户端api_keyapi_key,base_urlbase_url)defgenerate(self,prompt:str,system_prompt:str)-str:messages[{role:system,content:system_prompt},# 系统提示词{role:user,content:prompt}# 用户输入]responseself.client.chat.completions.create(modelself.model,messagesmessages,streamFalse)returnresponse.choices[0].message.content3.3 关键配置参数参数作用示例值model指定使用的模型deepseek-chatapi_keyAPI 认证密钥sk-xxxxxbase_urlAPI 服务地址3.4 调用方式# 实例化客户端llmOpenAICompatibleClient(model,api_key,base_url)# 调用生成llm_outputllm.generate(prompt用户的问题,system_prompt系统提示词)四、上下文累积机制4.1 什么是上下文上下文 让 LLM 知道「之前发生了什么」LLM 本身没有记忆每次调用都是独立的。通过prompt_history我们为 LLM 构建了一个「会话记忆」。4.2 prompt_history 的结构prompt_history[f用户请求:{user_prompt}]# 第1项初始请求# 循环中不断追加foriinrange(5):# ... LLM 调用 ...prompt_history.append(llm_output)# 第2、4、6...项LLM 的输出# ... 工具调用 ...prompt_history.append(fObservation:{observation})# 第3、5、7...项工具结果4.3 完整的 prompt_history 示例假设用户问「北京天气和景点」[ 用户请求: 你好请帮我查询一下今天北京的天气然后根据天气推荐一个合适的旅游景点。, Thought: 用户想知道北京天气然后根据天气推荐景点。我应该先查询天气。 Action: get_weather(city\北京\), Observation: 北京当前天气晴天26摄氏度, Thought: 北京是晴天适合去故宫或长城。我需要调用景点推荐工具。 Action: get_attraction(city\北京\, weather\晴天\), Observation: 根据您的情况为您推荐推荐故宫明清皇宫门票60元和长城世界奇迹建议提前预约, Thought: 已经获取到天气和景点信息可以给用户最终回答了。 Action: Finish[北京今天天气晴朗26摄氏度。建议您去故宫和长城游玩...] ]4.4 为什么同时追加 llm_output 和 observation追加内容作用目的llm_outputLLM 的 Thought Action让下次 LLM 看到自己的推理过程实现自我修正observation工具执行结果让 LLM 知道真实世界的状态类比就像人类解决问题时会同时记住「我怎么想的」和「实际发生了什么」。4.5 上下文累积的代码实现full_prompt\n.join(prompt_history)# 拼接所有历史为单个字符串llm_outputllm_client.generate(full_prompt,# 累积的上下文system_promptAGENT_SYSTEM_PROMPT# 系统提示词)五、系统提示词与用户提示词5.1 两者的本质区别对比项系统提示词 (System Prompt)用户提示词 (User Prompt)定义给 LLM 的「角色说明」和「行为规范」用户实际的「问题或请求」位置messages[0]固定不变messages[1]每次变化作用告诉 LLM 「你是谁该怎么做」告诉 LLM 「要做什么」变化频率通常固定每次对话都可能不同5.2 代码中的实现messages[{role:system,content:system_prompt},# 固定角色{role:user,content:prompt}# 变化的问题]5.3 系统提示词的设计AGENT_SYSTEM_PROMPT 你是一个智能旅行助手。你的任务是分析用户的请求并使用可用工具一步步地解决问题。 # 可用工具: - get_weather(city: str): 查询指定城市的天气。 - get_attraction(city: str, weather: str): 根据城市和天气推荐旅游景点。 # 输出格式要求: 你的每次回复必须严格遵循以下格式包含一对Thought和Action Thought: [你的思考过程和下一步计划] Action: [你要执行的具体行动] Action的格式必须是以下之一 1. 调用工具function_name(arg_namearg_value) 2. 结束任务Finish[最终答案] # 重要提示: - 每次只输出一对Thought-Action - Action必须在同一行不要换行 - 当收集到足够信息可以回答用户问题时必须使用 Action: Finish[最终答案] 格式结束 5.4 系统提示词的组成┌─────────────────────────────────────────────────────────┐ │ 系统提示词结构 │ ├─────────────────────────────────────────────────────────┤ │ 1. 角色定义 │ │ 你是一个智能旅行助手 │ │ │ │ 2. 工具说明 │ │ 可用工具: get_weather, get_attraction │ │ │ │ 3. 输出格式规范 │ │ Thought: ... \n Action: ... │ 4. 约束条件 │ │ 每次只输出一对Thought-Action │ │ Action必须在同一行 │ │ 使用Finish[答案]结束 └─────────────────────────────────────────────────────────┘5.5 用户提示词的作用用户提示词是驱动整个流程的动力user_prompt你好请帮我查询一下今天北京的天气然后根据天气推荐一个合适的旅游景点。它决定了LLM 第一次思考的方向需要调用哪些工具何时可以结束任务六、LLM 输出的处理6.1 为什么需要处理 LLM 输出LLM 返回的是自然语言文本但程序需要知道下一步要执行什么动作提取工具名和参数判断任务是否完成6.2 正则表达式解析# 1. 提取 Action 部分action_matchre.search(rAction: (.*),llm_output,re.DOTALL)# re.DOTALL 让 . 能匹配换行符# 2. 判断是 Finish 还是工具调用ifaction_str.startswith(Finish):# 提取最终答案final_answerre.match(rFinish\[(.*)\],action_str).group(1)else:# 3. 提取工具名tool_namere.search(r(\w)\(,action_str).group(1)# 例如: get_weather(city北京) → 提取 get_weather# 4. 提取参数args_strre.search(r\((.*)\),action_str).group# 例如: city北京 → 提取 city北京kwargsdict(re.findall(r(\w)([^]*),args_str))# 解析为字典: {city: 北京}6.3 解析流程图LLM 输出: ┌────────────────────────────────────────────────────────┐ │ Thought: 我需要查询北京的天气 │ │ Action: get_weather(city北京) │ └────────────────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────────────────┐ │ 正则提取 Action │ │ action_match.group(1) get_weather(city\北京\) │ └────────────────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────────────────┐ │ 工具名提取: tool_name get_weather │ │ 参数提取: kwargs {city: 北京} │ └────────────────────────────────────────────────────────┘6.4 为什么只处理 Action不处理 Thought部分作用处理方式Thought给人看的理解 LLM 思考过程只作为文本追加到历史Action给程序执行的决定下一步行动正则解析程序化执行设计思想Thought 是透明化 AI 思考过程Action 是实际执行的接口。七、外部工具的引入与调用7.1 为什么要引入外部工具LLM 的局限不知道实时信息天气、股票、新闻等无法执行操作查数据库、发邮件等工具的作用为 LLM 补全信息 赋予行动能力7.2 工具的定义方式# 方式1模拟工具写死数据方便测试defget_weather(city:str)-str:weather_data{北京:晴天26摄氏度,上海:小雨22摄氏度,# ...}returnf{city}当前天气{weather_data[city]}# 方式2注册到工具字典available_tools{get_weather:get_weather,get_attraction:get_attraction,}7.3 工具调用的完整流程1. LLM 输出 Action: get_weather(city北京) 2. 代码解析: tool_name get_weather kwargs {city: 北京} 3. 检查工具是否存在: if tool_name in available_tools: # True 4. 调用工具: observation available_tools[tool_name](**kwargs) # 即: get_weather(city北京) 5. 获取结果: observation 北京当前天气晴天26摄氏度 6. 追加到历史: prompt_history.append(fObservation: {observation})7.4 工具调用的代码实现iftool_nameinavailable_tools:observationavailable_tools[tool_name](**kwargs)# 解包参数调用else:observationf错误: 未定义的工具 {tool_name}7.5 工具返回值的处理工具返回值会作为Observation追加到历史供下一次 LLM 调用Observation:北京当前天气晴天26摄氏度LLM 会根据这个「观察结果」决定下一步行动。八、循环执行机制8.1 为什么需要循环因为复杂任务无法一步完成用户我想去北京旅游 │ ├── 步骤1查天气 ──→ 晴天 │ ├── 步骤2推荐景点 ──→ 故宫、长城 │ └── 步骤3给出建议 ──→ 完成8.2 循环控制foriinrange(5):# 最多执行5次防止无限循环# ... 思考、行动、观察 ...ifaction_str.startswith(Finish):break# 任务完成主动退出8.3 循环终止条件条件说明Action: Finish[答案]正常完成LLM 认为任务已达成循环次数达到上限i 5防止死循环Action 解析失败加入错误观察继续尝试8.4 循环的作用多次推理复杂问题分解为多个简单步骤自我修正如果某步错误后续步骤可以纠正信息累积每次循环获取新信息逐步接近答案九、完整执行流程9.1 场景查询北京天气和景点用户输入: 你好请帮我查询一下今天北京的天气然后根据天气推荐一个合适的旅游景点。9.2 第一轮循环┌─────────────────────────────────────────────────────────┐ │ 循环 1 │ ├─────────────────────────────────────────────────────────┤ │ 输入: 用户请求 │ │ │ │ LLM 输出: │ │ Thought: 用户想了解北京天气和景点推荐。我应该先查询天气。 │ │ Action: get_weather(city北京) │ │ │ │ 工具调用: get_weather(city北京) │ │ 工具返回: 北京当前天气晴天26摄氏度 │ │ │ │ Observation: 北京当前天气晴天26摄氏度 │ └─────────────────────────────────────────────────────────┘9.3 第二轮循环┌─────────────────────────────────────────────────────────┐ │ 循环 2 │ ├─────────────────────────────────────────────────────────┤ │ 输入: 用户请求 LLM输出 Observation │ │ │ │ LLM 输出: │ │ Thought: 北京是晴天适合去故宫或长城。我需要调用景点推荐。│ │ Action: get_attraction(city北京, weather晴天) │ │ 工具调用: get_attraction(city北京, weather晴天) │ │ 工具返回: 根据您的情况为您推荐故宫和长城 │ │ │ │ Observation: 根据您的情况为您推荐故宫和长城 │ └─────────────────────────────────────────────────────────┘9.4 第三轮循环┌─────────────────────────────────────────────────────────┐ │ 循环 3 │ ├─────────────────────────────────────────────────────────┤ │ 输入: 完整历史 │ │ │ │ LLM 输出: │ │ Thought: 已获取天气和景点信息可以给用户最终回答了。 │ │ Action: Finish[北京今天天气晴朗26摄氏度。建议您去故宫 │ │ 和长城游玩。故宫门票60元长城建议提前预约。] │ │ │ │ ✓ 任务完成退出循环 │ └─────────────────────────────────────────────────────────┘十、核心设计思想总结10.1 架构概览┌─────────────────────────────────────────────────────────────┐ │ 用户请求 │ └──────────────────────────┬──── │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ LLM (大脑) │ │ - 理解任务 │ │ - 制定计划 │ │ - 决策行动 │ └──────────────────────────┬──────────────────────────────────┘──────────────────────────────┘ │ ┌────────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────────┐ ┌──────────┐ │ 工具1 │ │ 工具2 │ │ 工具3 │ │ get_weather│ │ get_attraction│ │ ... │ └──────────┘ └──────────────┘ └──────────┘ │ │ │ └────────────────┼────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ Observation (反馈) │ │ 天气是晴天 推荐故宫和长城 │ └──────────────────────────┬──────────────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ 继续思考 or 结束任务 │ └─────────────────────────┘10.2 关键知识点知识点核心要点ReAct 模式Thought-Action-Observation 循环LLM 配置model、api_key、base_url 三要素上下文累积prompt_history 保存完整对话历史系统提示词固定的角色定义和行为规范用户提示词变化的任务输入输出解析正则提取 Action执行工具或结束任务工具调用字典注册 动态调用 结果反馈循环执行分解复杂任务支持自我修正10.3 设计原则职责分离Thought 给人看Action 给机器执行信息透明完整的 prompt_history 让 LLM 拥有记忆反馈闭环每次工具调用都生成 Observation 供 LLM 参考安全防护循环次数限制防止无限执行十一、附录11.1 完整代码结构chapter1_agent_demo.py ├── AGENT_SYSTEM_PROMPT # 系统提示词 ├── get_weather() # 天气工具Mock ├── get_attraction() # 景点工具Mock ├── available_tools # 工具注册表 ├── OpenAICompatibleClient # LLM 客户端 └── run_agent() # 主循环12.2 关键正则表达式正则作用示例rAction: (.*)提取 Action 行Action: get_weather(city北京)r(\w)\(提取工具名get_weatherr\((.*)\)提取参数部分city北京r(\w)([^]*)解析参数{city: 北京}rFinish\[(.*)\]提取最终答案Finish[北京天气晴朗...]chapter1_agent_demo.pyAGENT_SYSTEM_PROMPT 你是一个智能旅行助手。你的任务是分析用户的请求并使用可用工具一步步地解决问题。 # 可用工具: - get_weather(city: str): 查询指定城市的天气。 - get_attraction(city: str, weather: str): 根据城市和天气推荐旅游景点。 # 输出格式要求: 你的每次回复必须严格遵循以下格式包含一对Thought和Action Thought: [你的思考过程和下一步计划] Action: [你要执行的具体行动] Action的格式必须是以下之一 1. 调用工具function_name(arg_namearg_value) 2. 结束任务Finish[最终答案] # 重要提示: - 每次只输出一对Thought-Action - Action必须在同一行不要换行 - 当收集到足够信息可以回答用户问题时必须使用 Action: Finish[最终答案] 格式结束 请开始吧 def get_weather(city: str) - str: 获取天气的模拟函数写死数据方便测试 weather_data { 北京: 晴天26摄氏度, 上海: 小雨22摄氏度, 广州: 多云28摄氏度, 深圳: 晴天30摄氏度, 成都: 阴天20摄氏度, 杭州: 小雨24摄氏度, } if city in weather_data: return f{city}当前天气{weather_data[city]} return f{city}当前天气晴天25摄氏度默认 def get_attraction(city: str, weather: str) - str: 获取景点的模拟函数写死数据方便测试 attractions { 北京: { 晴天: 推荐故宫明清皇宫门票60元和长城世界奇迹建议提前预约, 小雨: 推荐国家博物馆免费周一闭馆和798艺术区室内文艺打卡地, 阴天: 推荐颐和园皇家园林湖光山色和天坛古代祭天建筑, 多云: 推荐故宫和颐和园, 默认: 推荐故宫和长城, }, 上海: { 晴天: 推荐外滩万国建筑博览和东方明珠浦东地标, 小雨: 推荐上海博物馆免费周一闭馆和田子坊老上海风情, 阴天: 推荐豫园古典园林和南京路步行街, 多云: 推荐外滩和豫园, 默认: 推荐外滩和东方明珠, }, 广州: { 晴天: 推荐广州塔小蛮腰夜景超美和白云山羊城第一高峰, 小雨: 推荐陈家祠岭南建筑艺术和北京路步行街千年古道, 阴天: 推荐沙面岛欧陆风情建筑群和珠江夜游, 多云: 推荐广州塔和沙面岛, 默认: 推荐广州塔和白云山, }, 深圳: { 晴天: 推荐世界之窗不出国门的环球旅行和东部华侨城生态旅游, 小雨: 推荐深圳博物馆免费和华强北商业街科技产品, 阴天: 推荐欢乐谷大型主题乐园和东门老街深圳商业起源地, 多云: 推荐世界之窗和东部华侨城, 默认: 推荐世界之窗和东部华侨城, }, 成都: { 晴天: 推荐大熊猫繁育研究基地国宝家园和宽窄巷子老成都生活, 小雨: 推荐武侯祠三国文化和锦里古街夜景超美, 阴天: 推荐杜甫草堂诗圣故居和春熙路时尚购物, 多云: 推荐大熊猫基地和宽窄巷子, 默认: 推荐大熊猫基地和宽窄巷子, }, 杭州: { 晴天: 推荐西湖人间天堂十景各异和灵隐寺千年古刹, 小雨: 推荐宋城千古情演出和河坊街老杭州风情, 阴天: 推荐西溪湿地城市绿肺和雷峰塔西湖最佳观景点, 多云: 推荐西湖和灵隐寺, 默认: 推荐西湖和灵隐寺, }, } 杭州: { 晴天: 推荐西湖人间天堂十景各异和灵隐寺千年古刹, 小雨: 推荐宋城千古情演出和河坊街老杭州风情, 阴天: 推荐西溪湿地城市绿肺和雷峰塔西湖最佳观景点, 多云: 推荐西湖和灵隐寺, 默认: 推荐西湖和灵隐寺, }, } city_attractions attractions.get(city, attractions[北京]) weather_key weather if weather in city_attractions else 默认 return f根据您的情况为您推荐{city_attractions.get(weather_key, city_attractions[默认])} available_tools { get_weather: get_weather, get_attraction: get_attraction, } from openai import OpenAI class OpenAICompatibleClient: 调用真实大模型需配置 API def __init__(self, model: str, api_key: str, base_url: str): self.model model self.client OpenAI(api_keyapi_key, base_urlbase_url) def generate(self, prompt: str, system_prompt: str) - str: 调用大模型 API print([OpenAICompatibleClient] 正在调用大模型...) try: messages [ {role: system, content: system_prompt}, {role: user, content: prompt} ] response self.client.chat.completions.create( modelself.model, messagesmessages, streamFalse ) answer response.choices[0].message.content print([OpenAICompatibleClient] 大模型响应成功) return answer except Exception as e: print(f[OpenAICompatibleClient] 调用失败: {e}) return f错误调用语言模型服务时出错。 import re def run_agent(user_prompt: str, llm_client): 运行 Agent 的主循环 print( * 60) print(* 智能旅行助手 Agent工具Mock LLM真实调用) print( * 60) print(f\n 用户请求: {user_prompt}\n) prompt_history [f用户请求: {user_prompt}] for i in range(5): print(f\n{-*60}) print(f循环 {i1}) print(f{-*60}) full_prompt \n.join(prompt_history) llm_output llm_client.generate(full_prompt, system_promptAGENT_SYSTEM_PROMPT) print(f\n[LLM 输出]) print(llm_output) prompt_history.append(llm_output) action_match re.search(rAction: (.*), llm_output, re.DOTALL) if not action_match: observation 错误: 未能解析到 Action 字段 print(f\n[观察] {observation}) prompt_history.append(fObservation: {observation}) continue action_str action_match.group(1).strip() if action_str.startswith(Finish): final_answer re.match(rFinish\[(.*)\], action_str).group(1) print(f\n*** 任务完成) print(f最终答案: {final_answer}) break tool_name re.search(r(\w)\(, action_str).group(1) args_str re.search(r\((.*)\), action_str).group(1) kwargs dict(re.findall(r(\w)([^]*), args_str)) print(f\n[调用工具] {tool_name}) print(f[参数] {kwargs}) if tool_name in available_tools: observation available_tools[tool_name](**kwargs) else: observation f错误: 未定义的工具 {tool_name} print(f\n[工具返回] {observation}) prompt_history.append(fObservation: {observation}) print(\n * 60) print(对话历史:) print( * 60) for i, msg in enumerate(prompt_history, 1): print(f\n[{i}] {msg}) return prompt_history if __name__ __main__: print(\n ~ * 50) print(\n开始测试 Agent...\n) API_KEY BASE_URL MODEL_ID t llm OpenAICompatibleClient( modelMODEL_ID, api_keyAPI_KEY, base_urlBASE_URL ) user_prompt 你好请帮我查询一下今天北京的天气然后根据天气推荐一个合适的旅游景点。 run_agent(user_prompt, llm) print(\n ~ * 50) print(\n测试完成\n)十一、总结初始化‌用户原始提问进入 prompt_history作为初始用户侧唯一内容。2‌. 拼接上下文‌系统提示词 全量历史从用户提问起的所有 Thought/Action/Observation拼接成 full_prompt传给 LLM。‌3. LLM 输出‌LLM 输出 llm_output包含 Thought推理过程 Action执行指令。‌4. 程序解析 Action‌‌ 若 Action 是 Finish[答案]‌程序通过正则表达式从 Action 字符串中‌截取方括号内的内容‌作为最终答案。‌ 直接输出该答案给用户‌循环终止。‌ 全程无工具调用也不产生任何 Observation‌。‌ 若 Action 是普通工具调用指令‌先把本轮 ThoughtAction 追加进 prompt_history。再进入 execute_action 执行工具拿到 tool_result。把 tool_result 包装成 Observation追加进 prompt_history。‌ 循环迭代‌回到第2步带着更新后的全量历史重新调用 LLM。‌终止条件‌命中 Finish ‌或‌ 达到最大循环次数上限如5次防死循环。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询