大模型“进化论”:从“玩具”到“工具”,Agent、RAG、Qwen架构深度剖析与实操
🤖🔥 大模型“进化论”:从“玩具”到“工具”,Agent、RAG、Qwen架构深度剖析与实操
嗨,大家好!👋 我是Jason,一个在AI世界里摸爬滚打的“探险家”!🤠 最近,我深入研究了大模型Agent、RAG和Qwen这三大“神器”,感觉自己的认知边界又被拓宽了!🌍 但同时,我也产生了更多的疑问、更深的思考,甚至是一些“细思极恐”的担忧……😱 今天,我就把这些“所思所想”和“所学所用”,毫无保留地分享给大家。准备好了吗?我们要开始“头脑风暴”了!🌪️
引言:大模型的“光荣与梦想”,“现实与骨感” 🌟🦴
ChatGPT、InternLM2、Qwen……这些响当当的名字,代表了大模型时代的“光荣与梦想”。✨ 它们能写出以假乱真的文章,能生成栩栩如生的图像,能与人进行流畅的对话,仿佛拥有了“无限可能”。但是!(没错,又来了个“但是”!)当我们剥开大模型华丽的外衣,深入到它的“骨骼”和“血肉”,就会发现,现实往往比梦想更“骨感”。
大模型最令人诟病的,莫过于“幻觉”(hallucination)问题。它们会一本正经地胡说八道,编造出根本不存在的事实,而且还“理直气壮”,让人哭笑不得。😂 这究竟是为什么呢?
深层原因:数据的“原罪”与模型的“无知”
大模型的“知识”,来源于浩如烟海的训练数据。但这些数据,就像一个“大杂烩”,里面既有“珍馐美味”,也有“残羹冷炙”,甚至还有“过期变质”的……🤢
- 过时 ⏳:信息时代,日新月异。今天的新闻,明天就可能变成“历史”。大模型的“记忆”,却可能停留在“过去”,无法跟上时代的步伐。这难道不是一种“刻舟求剑”吗?
- 片面 🗺️:数据采集的范围、方式,都可能存在偏差。大模型就像戴着“有色眼镜”看世界,只能看到“局部”,而无法窥见“全貌”。这和“盲人摸象”又有什么区别?
- 错误 ❌:数据本身就可能存在错误、谬误、谣言……大模型“不加辨别”地吸收,结果只能是“以讹传讹”,越错越离谱。这难道不是一种“数字病毒”的传播吗?
- 虚构 👻:大模型强大的生成能力,是一把“双刃剑”。它能创造出优美的诗歌,也能编造出虚假的故事。当“创造力”变成了“欺骗”,我们又该如何应对?
更可怕的是,大模型并不知道自己“不知道”!🤯 即使面对完全陌生的问题,它也会“强行”给出一个答案,而且还“自信满满”,仿佛自己是“无所不知”的“先知”。这难道不是一种“数字版的皇帝新装”吗?
面对大模型的“阿喀琉斯之踵”,Agent和RAG技术应运而生。它们就像给大模型装上了“智慧的翅膀”,让AI的能力实现了“质的飞跃”!🚀
第一部分:InternLM2 + ReAct = 给大模型装上“手脚”,让它“动”起来!🏃♂️🧠
-
核心挑战: 大模型被“困”在了“数字世界”里,无法与现实世界互动。它就像一个“宅男”,只会在自己的“小天地”里“自娱自乐”,而无法真正地“改变世界”。
-
革命性方案: Agent!给大模型装上“手”和“脚”,让它能感知环境、执行任务、影响现实!这才是AI的“正确打开方式”!
-
ReAct的精髓: Reasoning + Acting = 思考 + 行动。这不仅仅是两个单词的简单相加,而是一种全新的“范式”!它让大模型像人类一样,边思考,边行动,在实践中不断学习、调整、优化。
-
ReAct vs. CoT:告别“纸上谈兵”!
- CoT (Chain-of-Thought) 只能“想”,不能“动”。遇到超出“知识范围”的问题,就只能“干瞪眼”。😵
- ReAct 能“行动”!💪 通过调用各种工具(比如搜索引擎、计算器、API……),获取信息,解决问题,实现目标!
-
手搓Agent三部曲(代码在手,天下我有!💻):
-
大脑(模型): 选择InternLM2,它强大的推理能力,是Agent的“智慧源泉”!🧠
# 导入必要的库 import torch from transformers import AutoTokenizer, AutoModelForCausalLM from typing import List # 定义BaseModel类 class BaseModel: def __init__(self, path: str = '') -> None: self.path = path def chat(self, prompt: str, history: List[dict]): pass def load_model(self): pass # 定义InternLM2Chat类,继承自BaseModel class InternLM2Chat(BaseModel): def __init__(self, path: str = '') -> None: super().__init__(path) self.load_model() def load_model(self): print('================ Loading model ================') self.tokenizer = AutoTokenizer.from_pretrained(self.path, trust_remote_code=True) self.model = AutoModelForCausalLM.from_pretrained(self.path, torch_dtype=torch.float16, trust_remote_code=True).cuda().eval() print('================ Model loaded ================') def chat(self, prompt: str, history: List[dict], meta_instruction:str ='') -> str: response, history = self.model.chat(self.tokenizer, prompt, history, temperature=0.1, meta_instruction=meta_instruction) return response, history # 加载模型 # path = '/root/share/model_repos/internlm2-chat-7b' # 替换为你的模型路径 # model = InternLM2Chat(path) -
工具箱: 以Google搜索为例(调用Serper API),让Agent能获取最新的信息,告别“信息茧房”!🧰
# tools.py import requests import json from typing import List, Dict # 你的Serper API Key SERPER_API_KEY = "YOUR_SERPER_API_KEY" # 替换为你的API Key class Tools: def __init__(self) -> None: self.tool_config = self._tools() def _tools(self) -> List[Dict]: tools = [ { 'name_for_human': '谷歌搜索', 'name_for_model': 'google_search', 'description_for_model': '谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。', 'parameters': [ { 'name': 'search_query', 'description': '搜索关键词或短语', 'required': True, 'schema': {'type': 'string'}, } ], } ] return tools def google_search(self, search_query: str) -> str: """ 使用Serper API进行Google搜索 """ url = "https://google.serper.dev/search" payload = json.dumps({"q": search_query}) headers = {'X-API-KEY': SERPER_API_KEY, 'Content-Type': 'application/json'} response = requests.request("POST", url, headers=headers, data=payload) return response.text -
组装Agent: 实现ReAct的核心逻辑(代码片段,精华中的精华!):
# Agent.py from tools import Tools from BaseModel import BaseModel, InternLM2Chat import json, re #ReAct Prompt 模板 REACT_PROMPT = """ Answer the following questions as best you can. You have access to the following tools: {tool_descs} Use the following format: Question: the input question you must answer Thought: you should always think about what to do Action: the action to take, should be one of [{tool_names}] Action Input: the input to the action Observation: the result of the action ... (this Thought/Action/Action Input/Observation can be repeated zero or more times) Thought: I now know the final answer Final Answer: the final answer to the original input question Begin! """ # 工具描述模板 TOOL_DESC = """{name_for_human}: Call this tool to interact with the {name_for_human} API. What is the {name_for_human} API useful for? {description_for_model} Parameters: {parameters} Format the arguments as a JSON object.""" class Agent: def __init__(self, model: BaseModel, tools: Tools) -> None: self.model = model self.tools = tools self.system_prompt = self.build_system_prompt() def build_system_prompt(self) -> str: """ 构建system_prompt """ tool_descs = [] tool_names = [] for tool in self.tools.tool_config: tool_descs.append(TOOL_DESC.format(**tool)) tool_names.append(tool['name_for_model']) tool_descs = '\n\n'.join(tool_descs) tool_names = ','.join(tool_names) sys_prompt = REACT_PROMPT.format(tool_descs=tool_descs, tool_names=tool_names) return sys_prompt def parse_latest_plugin_call(self, text: str) -> tuple[str, str] | None: """ 从模型的输出中解析工具名称和参数 """ plugin_name_match = re.search(r'Action: (\w+)', text) plugin_args_match = re.search(r'Action Input: (.*)', text, re.DOTALL) if plugin_name_match and plugin_args_match: plugin_name = plugin_name_match.group(1) plugin_args = plugin_args_match.group(1).strip() return plugin_name, plugin_args else: return None def call_plugin(self, plugin_name: str, plugin_args: str) -> str: """ 调用工具 """ if plugin_name == 'google_search': try: plugin_args = json.loads(plugin_args) search_query = plugin_args['search_query'] result = self.tools.google_search(search_query) return result except json.JSONDecodeError: return "Error: Invalid JSON format for plugin arguments." except KeyError: return "Error: Missing 'search_query' parameter for google_search." else: return f"Error: Unknown plugin name: {plugin_name}" def text_completion(self, text: str, history=[]) -> str: prompt = f"Question: {text}\n" # 首次对话 response, history = self.model.chat(prompt, history, meta_instruction=self.system_prompt) # print(f"model output: {response}") # 解析模型输出,获取工具名称和参数 plugin_call = self.parse_latest_plugin_call(response) if plugin_call: plugin_name, plugin_args = plugin_call # 调用工具 plugin_response = self.call_plugin(plugin_name, plugin_args) # print(f"plugin_response: {plugin_response}") # 构造第二次对话的输入 prompt = f"{response}\nObservation: {plugin_response}\n" response, history = self.model.chat(prompt, history) # print(f"model output: {response}") # 提取最终答案 final_answer_match = re.search(r'Final Answer: (.*)', response, re.DOTALL) if final_answer_match: final_answer = final_answer_match.group(1).strip() return final_answer, history else: return "未找到最终答案", history else: # 提取最终答案 final_answer_match = re.search(r'Final Answer: (.*)', response, re.DOTALL) if final_answer_match: final_answer = final_answer_match.group(1).strip() return final_answer, history else: return response, history# 运行Agent! from Agent import Agent from tools import Tools from BaseModel import InternLM2Chat # 加载模型和工具 model_path = '/root/share/model_repos/internlm2-chat-7b' # 替换为你的模型路径 model = InternLM2Chat(model_path) tools = Tools() # 创建Agent agent = Agent(model, tools) # 与Agent对话 history = [] response, history = agent.text_completion('你好', history) print(response) response, history = agent.text_completion('周杰伦是谁?', history) print(response) response, history = agent.text_completion('他的第一张专辑是什么?', history) print(response)
-
-
进阶玩法:让Agent“更上一层楼”!
- 更多工具:维基百科、天气预报、地图导航、代码解释器……只有你想不到,没有Agent做不到!
- 更强大的Agent:多轮对话(让Agent记住“上下文”),多模态(让Agent能“看图说话”、“听音辨曲”),自主学习(让Agent在实践中不断“进化”)……
- SOP (Standard Operating Procedure):给Agent制定“行为准则”,让它的行动更规范、更可控、更安全。
第二部分:TinyRAG:给LLM装上“外挂大脑”,让它“博学多才”!📚🔍
-
核心挑战: LLM的“知识”是“静态”的,容易过时、片面、出错。它就像一本“百科全书”,虽然内容丰富,但更新速度慢,而且可能存在错误。
-
颠覆性方案: RAG (Retrieval-Augmented Generation)!给LLM配备一个“超级外挂大脑”和一个“智能检索系统”,让它能随时随地获取最新、最准确、最全面的知识!
-
RAG的核心思想: 提问 -> 检索相关信息 -> 整合信息与问题 -> LLM生成答案。这不仅仅是一个“流程”,更是一种“哲学”:让LLM从“闭门造车”走向“博采众长”!
-
RAG的“超能力”:
- 知识实时更新:告别“信息滞后”!
- 掌握专业知识:成为“领域专家”!
- 减少“胡说八道”:让答案更可靠!
- 答案可追溯:让LLM的“思考过程”更透明!
-
TinyRAG:告别“黑盒”,自己动手,丰衣足食!💪
- 透明:RAG的每一个“零件”,都清晰可见!
- 可控:你可以根据自己的需求,随意“定制”!
- 深入:亲手构建RAG,让你对它的理解,远超“纸上谈兵”!
-
TinyRAG核心流程:
- 用户提问
- 文档检索(向量化、索引、相似度搜索)
- 答案生成(整合检索结果与问题,LLM生成)
-
对比实验:有RAG vs. 无RAG,效果“天壤之别”!
- 无RAG:LLM只能“凭记忆”回答,容易出错,或者直接“认怂”。
- 有RAG:LLM能结合检索到的信息,给出更全面、更深入、更准确的答案!
-
RAG的“局限”与“未来”:
- 检索质量是“生命线”:如果检索到的信息不靠谱,RAG的效果会大打折扣。
- 计算成本是“拦路虎”:RAG需要额外的检索步骤,会增加计算量和响应时间。
- 信息过载是“绊脚石”:过多的检索结果,可能会干扰LLM的生成过程。
- 未来:多模态RAG(融合文本、图像、音频等多种信息),个性化RAG(根据用户的兴趣和需求定制检索策略),可控RAG(让用户能干预检索和生成过程)……
第三部分:Qwen深度解剖:揭开通义千问大模型的“神秘面纱”!🏗️🛠️
-
Qwen的“过人之处”: Qwen不仅仅是Llama 2的“模仿者”,更是“超越者”!🚀 它在Llama 2的基础上,进行了大胆的创新和优化,实现了性能和效率的“双提升”!
-
架构“鸟瞰图”: 继承Llama 2的“优良传统”,并“发扬光大”:
-
Tokenizer(分词器):采用先进的BPE算法,支持多语言,为跨语言理解奠定基础。
# 假设的Tokenizer代码示例(简化版) class BPETokenizer: def __init__(self, vocab_file): self.vocab = self.load_vocab(vocab_file) def load_vocab(self, vocab_file): # 从文件中加载词汇表 with open(vocab_file, 'r', encoding='utf-8') as f: vocab = json.load(f) return vocab def tokenize(self, text): # 将文本转换为token序列 tokens = [] # ... (省略BPE算法的具体实现) return tokens def convert_tokens_to_ids(self, tokens): # 将token序列转换为id序列 return [self.vocab[token] for token in tokens] -
Embedding(嵌入层):将离散的token(词)映射到高维连续空间,捕捉词汇之间的语义关系。
# 假设的Embedding层代码示例(简化版) import torch import torch.nn as nn class EmbeddingLayer(nn.Module): def __init__(self, vocab_size, embedding_dim): super().__init__() self.embedding = nn.Embedding(vocab_size, embedding_dim) def forward(self, input_ids): # input_ids: [batch_size, seq_length] return self.embedding(input_ids) # output: [batch_size, seq_length, embedding_dim] -
Decoder堆叠:由多个Decoder Layer组成,每个Layer都负责处理不同层次的信息。
class Qwen2DecoderLayer(nn.Module): def __init__(self, config): super().__init__() self.self_attn = Qwen2Attention(config) # 引入GQA,性能倍增 self.mlp = Qwen2MLP(config) # 门控机制,非线性表达 self.input_layernorm = RMSNorm(...) # 前置归一,训练稳如磐石 self.post_attention_layernorm = RMSNorm(...) # 双重保障 -
RMSNorm(均方根归一化):替代LayerNorm,实现更稳定、更高效的训练。
class RMSNorm(nn.Module): def forward(self, x): variance = x.pow(2).mean(-1, keepdim=True) return x * torch.rsqrt(variance + self.eps) * self.weight -
注意力机制:引入GQA(分组查询注意力)和Flash Attention优化,兼顾速度和性能。
def repeat_kv(hidden_states, n_rep): # 告别简单复制,拥抱高效expand+reshape,实现KV共享 hidden_states = hidden_states[:, :, None, :, :].expand(...) return hidden_states.reshape(...)
-
-
核心组件“显微镜”:
-
Decoder Layer: 模型的核心“引擎”!
-
代码 + 详细流程(残差连接、Pre/Post-RMSNorm、GQA、门控FFN)
# 假设的Decoder Layer前向传播代码示例(简化版) def forward(self, hidden_states, attention_mask=None): # 1. 残差连接 + 前置RMSNorm residual = hidden_states hidden_states = self.input_layernorm(hidden_states) # 2. GQA注意力计算 attn_output = self.self_attn(hidden_states, attention_mask=attention_mask) # 3. 二次残差连接 hidden_states = residual + attn_output # 4. 后置RMSNorm + 门控FFN residual = hidden_states hidden_states = self.post_attention_layernorm(hidden_states) mlp_output = self.mlp(hidden_states) hidden_states = residual + mlp_output return hidden_states -
Pre-LN vs. Post-LN: Qwen选择了Pre-LN,提高了训练稳定性,但可能牺牲了一点模型容量。(这是一个“权衡”,没有绝对的“对”与“错”。)
-
-
注意力机制: 模型的“眼睛”和“耳朵”!
-
GQA: 速度与性能的“平衡大师”!(表格对比MHA、MQA、GQA,优缺点一目了然)
类型 计算复杂度 KV Cache占用 适用场景 MHA (多头) O(n²d) 100% 小模型,性能至上 MQA (多查询) O(n²d/k) 1/k 推理优化,资源受限 GQA (分组) O(n²d/k) 1/k 性能与效率兼得 -
RoPE: 旋转位置编码,让模型能处理超长文本!(线性内插特性,是RoPE的“独门绝技”!)
class Qwen2RotaryEmbedding(nn.Module): def __init__(self, dim, max_len=32768, base=10000): super().__init__() inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim)) self.register_buffer("inv_freq", inv_freq) def forward(self, x, seq_len): t = torch.arange(seq_len, device=x.device) freqs = torch.outer(t, self.inv_freq) return torch.cos(freqs), torch.sin(freqs)
-
-
门控MLP: 模型的“神经中枢”!
-
并行计算,提高效率!
# 假设的并行计算代码示例(简化版) gate = self.gate_proj(x) # [dim -> intermediate] up = self.up_proj(x) # [dim -> intermediate] -
SILU激活函数,引入非线性,增强表达能力!
# 使用SILU激活函数 import torch.nn.functional as F output = F.silu(gate) * up -
元素级相乘,精细控制信息流!
# 假设的门控MLP前向传播代码示例(简化版) class Qwen2MLP(nn.Module): def forward(self, x): gate = self.gate_proj(x) # [dim -> intermediate] up = self.up_proj(x) # [dim -> intermediate] return self.down_proj(F.silu(gate) * up) # 门控魔法,精妙绝伦
-
-
-
关键实现细节:
-
RMSNorm: 为什么Qwen选择了RMSNorm,而不是LayerNorm?因为它更适合生成任务,计算量更小,数值更稳定!
-
注意力掩码: 如何让模型“只看该看的东西”?答案是:因果掩码!(在指令微调阶段,还可以尝试因果掩码 + 局部注意力掩码,实现更精细的控制!)
# 生成式任务的因果掩码:只看过去,不看未来 attention_mask = torch.full( (seq_len, seq_len), fill_value=float("-inf"), ).triu(diagonal=1)
-
-
工程实践:
- 显存优化:如何用有限的资源,训练更大的模型?梯度检查点技术,了解一下!
- 量化部署:如何让模型“瘦身”,跑得更快?AWQ量化,值得一试!(但要注意RMSNorm的特殊缩放因子!)
- 训练加速:如何让训练“飞”起来?Flash Attention 2,让你的GPU“火力全开”!
- 可解释性:如何让模型不再是“黑盒”?注意力图可视化,让你“看”到模型的“思考过程”!
总结与行动指南:
经过这次“深度”+“广度”+“批判”+“反思”的学习,我深刻地认识到:
- 大模型不是“万能药”,但它绝对是AI领域的一场“革命”!
- Agent和RAG是让大模型“落地”的关键技术,它们让AI从“空中楼阁”走向“现实应用”。
- 深入理解模型架构,是“玩转”大模型的前提。只有“知其然”,才能“知其所以然”,才能更好地应用、改进、创新!
现在,是时候行动起来了!💪
- 动手实践: 运行本文提供的代码,亲手搭建Agent和RAG,体验AI的“魔力”!
- 独立思考: 提出你自己的“质疑”、“反思”、“批判”,让你的思维“火花”四溅!
- 持续探索: 关注大模型领域的最新进展,保持学习的热情,成为AI时代的“先行者”!
最后,别忘了给这篇文章点个赞👍,分享给你的朋友们!💖 让我们一起,在AI的浪潮中,勇往直前,探索未知,创造未来!
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)