<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>LLM on 厨师海森堡的厨房</title>
    <link>https://kevinchen1994.github.io/categories/llm/</link>
    <description>Recent content in LLM on 厨师海森堡的厨房</description>
    <image>
      <title>厨师海森堡的厨房</title>
      <url>https://kevinchen1994.github.io/images/profile.jpg</url>
      <link>https://kevinchen1994.github.io/images/profile.jpg</link>
    </image>
    <generator>Hugo -- 0.161.1</generator>
    <language>zh-cn</language>
    <lastBuildDate>Fri, 21 Jun 2024 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://kevinchen1994.github.io/categories/llm/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Agent Ⅱ 手搓一个Agent feat. Qwen-Agent</title>
      <link>https://kevinchen1994.github.io/posts/agent--%E6%89%8B%E6%90%93%E4%B8%80%E4%B8%AAagent-feat.-qwen-agent/</link>
      <pubDate>Fri, 21 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://kevinchen1994.github.io/posts/agent--%E6%89%8B%E6%90%93%E4%B8%80%E4%B8%AAagent-feat.-qwen-agent/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;上一篇文章介绍了关于Agent的一些相关内容，这篇文章来动手实现一个Agent。目前比较流行的Agent开发框架有很多，比如可视化的字节的扣子，还有代码实现的babyagi、AutoGPT，因为我用qwen用的比较多，正好我最近看到qwen也开源了一套框架，qwen-agents，封装了工具、助手和一些规划的方法，使用起来比较方便，那就用这套框架实现一个简单的Agent。&lt;/p&gt;
&lt;h2 id=&#34;agent设计开发&#34;&gt;Agent设计开发&lt;/h2&gt;
&lt;p&gt;既然是Agent，那就让他做一个LLM不能直接实现的任务，我这边有一个北京的房价表格，我们可以让Agent帮我们分析一下房价，最后生成一个图标来展示每平米的价格。&lt;/p&gt;
&lt;p&gt;因为这个任务需要多步骤才能实现，所以我们可以使用上篇文章中将的ReAct的思路，让模型自己规划任务，根据每一次的执行结果来调整任务，并且可以利用代码助手来帮助他实现目标。&lt;/p&gt;
&lt;p&gt;先配置LLM，这里可以使用阿里的api，也可以使用第三方的api，只要与openAI库兼容就可以。我这里尝试了付费的qwen-max和免费的Qwen2-7B-Instruct。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;llm_cfg &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# 使用 DashScope 提供的模型服务：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# &amp;#39;model&amp;#39;: &amp;#39;qwen-max&amp;#39;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# &amp;#39;model_server&amp;#39;: &amp;#39;dashscope&amp;#39;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# &amp;#39;api_key&amp;#39;: &amp;#39;EMPTY&amp;#39;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# 如果这里没有设置 &amp;#39;api_key&amp;#39;，它将读取 `DASHSCOPE_API_KEY` 环境变量。&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# 使用与 OpenAI API 兼容的模型服务，例如 vLLM 或 Ollama：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;model&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;alibaba/Qwen2-7B-Instruct&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;model_server&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;http://localhost:8000/v1&amp;#39;&lt;/span&gt;,  &lt;span style=&#34;color:#75715e&#34;&gt;# base_url，也称为 api_base&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;api_key&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;EMPTY&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# （可选） LLM 的超参数：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;generate_cfg&amp;#39;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;top_p&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后去定义我们的Agent，因为框架封装的很方便了，所以几行代码就可以实现。&lt;/p&gt;
&lt;p&gt;可以看到我们只需要配置Agent能够使用的工具，以及Agent的名称，他能做什么就可以了。工具方面我这边只使用了代码解释器，框架还封装了很多其他的工具，比如联网搜索、图片生成（需要api支持）、RAG等。框架也支持自定义工具，可以根据自己的需要实现特定功能的工具。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;init_agent_service&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    llm_cfg &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tools &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;code_interpreter&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bot &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; agents&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;ReActChat(llm&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;llm_cfg,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;house price analyzer&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           description&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;You are a house price analyzer, you can run code to analyze house price.&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           function_list&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;tools)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; bot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后就可以配置测试的方法了，可以通过命令行进行测试，也可以通过GUI进行测试，框架基于gradio开发了很方便的GUI方法，我就选择GUI来进行测试。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Agent Ⅰ Introduction</title>
      <link>https://kevinchen1994.github.io/posts/agent--introduction/</link>
      <pubDate>Thu, 20 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://kevinchen1994.github.io/posts/agent--introduction/</guid>
      <description>&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;
&lt;p&gt;随着ChatGPT的流行，我们似乎觉得LLM能够帮我们解决任何问题，但是长时间使用下来，有一些问题LLM并不能很好的解决，比如我想让LLM基于一次考试后的全班试卷帮我统计某个班级的最高分、最低分、平均分，并且针对考试较差的学生提出针对性的建议。目前所有的LLM都无法直接做到，因为首先全班所有的试卷就已经够长了，LLM的上下文长度可能都不够，再就是LLM并不擅长做关于数字的内容，因为数字对于他来说就是token，他有可能并不清楚数字token之间的关系。&lt;/p&gt;
&lt;p&gt;那这个问题怎么解决呢，那就是通过Agent来解决，我们让LLM作为大脑，让其拥有记忆功能来存储试卷内容，还可能让其调用工具，让其学会计算，对于他也不会的知识点，他还可以上网搜索学会了再来辅导学生。这是不是就有人工智能那味儿了。&lt;/p&gt;
&lt;p&gt;Agent能够通过构建LLM与规划、记忆、工具和执行来完成复杂的任务，LLM在其中扮演的就是大脑的角色，通过将复杂任务进行拆解，并且通过调用工具和存储来逐一解决小任务，最终完成复杂的任务。Agent能够大大提升LLM的实用性，让其不仅仅是一个只会对话的模型，而是有了规划和思考的能力。&lt;/p&gt;
&lt;p&gt;下图为Agent的构成的概要。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://kevinchen1994.github.io/images/notion_88cd957e-d2df-4ab4-9061-75f0e794111001e26f63-8eec-47b0-99ef-0ddcd7aba4ec.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;memory&#34;&gt;Memory&lt;/h2&gt;
&lt;p&gt;人类的大脑中有多种记忆模式，比如短期记忆，用于存储当下的一些信息，例如我们现在与人对话的上下文，还有长期记忆，用于存储我们的知识体系。Agent也是一样，短期记忆用于存储当前会话的上下文，一般通过模型的上下文窗口来解决，长期记忆用于存储知识库和历史行为，一般通过外部存储来解决。&lt;/p&gt;
&lt;p&gt;短期记忆受模型上下文窗口限制，所以不会太长，随着上下文长度的增长，对于显存的占用也会同步增加，所以这部分我们尽量控制的短一些，如果是超长的上下文，我们也可以将其转换为长期记忆来存储。&lt;/p&gt;
&lt;p&gt;长期记忆其实也就是RAG，我们通过外部向量存储知识库，可以快速检索和访问，因为向量库相对比较便宜，所以我们可以存储大量的知识以供Agent使用，并且向量库的内容我们还可以经常更新，让模型在不调整参数的同时就拥有了比较新的知识。&lt;/p&gt;
&lt;h2 id=&#34;planning&#34;&gt;Planning&lt;/h2&gt;
&lt;h3 id=&#34;无反馈规划&#34;&gt;无反馈规划&lt;/h3&gt;
&lt;p&gt;对于复杂的任务将其进行拆解能够帮助Agent更好的进行执行。&lt;/p&gt;
&lt;p&gt;对于LLM来说，他并不会主动将任务进行拆解，我们可以通过CoT（Chain of Though）让其进行拆解复杂任务，“let&amp;rsquo;s think step by step”就是一句魔法咒语，在prompt开头添加这句话，能够让模型分步骤解决问题，从而获得更高的准确率。&lt;/p&gt;
&lt;p&gt;在CoT的基础上，还有ToT（Tree of Though）的方法，通过在每一步探索多个可能得路径，形成树状结构，再通过DFS或者BSF来评估每个步骤的有效性。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://kevinchen1994.github.io/images/notion_c4759741-9120-4592-b9f4-82e2dd9f16c3caad19c9-e75d-4e81-a654-d8b7605df700.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;还有一种方法是LLM+P，也就是通过外部规划期来进行长期规划，这种方法先将问题转化为PDDL格式，然后利用规划期生成方案，最终将这一方案转换为自然语言。本质上，规划步骤被外包给外部工具，假设特定领域的 PDDL 和合适的规划器可用，这在某些机器人设置中很常见，但在许多其他领域并不常见。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://kevinchen1994.github.io/images/notion_e989527c-f740-4b26-9e9d-5d90973bee420687d74d-ec28-4124-984b-192ba7e82461.jpg&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;有反馈规划&#34;&gt;有反馈规划&lt;/h3&gt;
&lt;p&gt;如果模型规划有问题也不能很好的解决复杂的问题，所以我们可以让Agent通过反馈来进行规划，以纠正以前的错误，这对于解决复杂的任务有着至关重要的作用，毕竟人类在解决复杂问题时也会通过复盘来迭代自己的方法。姚顺雨大佬的两篇论文就是解决这个问题。&lt;/p&gt;
&lt;p&gt;ReAct通过结合特定任务的离散动作与语言描述，实现了LLM中融合推理和执行的能力。离散动作能够与现实环境进行交互，语言米哦啊哈苏则可能促进LLM产生基于自然语言的推理路径。这种策略不仅提高了LLM处理复杂问题的能力，还通过与外部环境直接交互，增强了模型在真实世界中的适应性和灵活性。&lt;/p&gt;
&lt;p&gt;具体的就是通过一下prompt模板，让LLM思考其Though、Action、Observation。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Thought: ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Action: ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Observation: ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;... (Repeated many times)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;下图可以看到使用ReAct后的效果，并且对比了只使用推理（reason）和只使用执行（act）的区别。在使用了推理+执行后，模型可以很好的规划这个任务，并且根据每一步的结果来规划下一步需要做什么，最终得到正确的答案。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://kevinchen1994.github.io/images/notion_bf6a889b-de49-447a-9a36-0f5b9ea32822a490c953-a74c-4835-a670-96188bc1f16f.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;传统的强化学习学习大量的训练样本和计算资源来让模型从错误中进行学习，Reflexion提出了一种新的框架，不通过更新模型的权重，而是通过自然语言的反馈来增强模型从错误中学习。&lt;/p&gt;
&lt;p&gt;Reflexion有一个标准的RL设置，其中简历模型提供简单的二元奖励，动作空间遵守ReAct中的设置，其中特定于任务的动作空间通过语言进行增强，以实现复杂的推理步骤。每一次执行，执行者（Actor）都会基于观察状态生成文本和动作，执行后，评估者（Evaluator）会对执行者生成的内容计算奖励分数，自我反思模型（Self-reflection）会生成口头自我反思提示以协助执行者进行改进，对于效率低下的规划，因为会存储在长期记忆中，所以会被识别到一直没有完成，这时自我反思模型会考虑将其停止。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://kevinchen1994.github.io/images/notion_05698073-909a-4d1b-89bf-2756f5cfcc41076884f4-ee09-41cf-ae0d-6b39bd7e0f27.jpg&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;tools&#34;&gt;Tools&lt;/h2&gt;
&lt;p&gt;曾几何时，人们普遍认为“使用工具”是人和动物最大的区别，虽然现在人们不这么认为了，但是人类文明发展史很大程度上就是一部人类发明工具帮助人类做事情的历史。如果Agent也能像人类一样使用工具就能够大大提升LLM的能力范围。&lt;/p&gt;
&lt;p&gt;比如LLM对数字不够敏感，可能很多加减法都会做错，但是如果他能够调用计算器，那多复杂的运算也能够准确的计算出来。还有很多工具，像是网页浏览、写代码、画图、调用API等等，都能够有效的提升LLM的能力。&lt;/p&gt;
&lt;p&gt;以下是一些LLM使用工具的方法：&lt;/p&gt;
&lt;p&gt;MRKL（Modular Reasoning, Knowledge and Language）包含一组专家模块，LLM作为路由器将查询路由到最合适的专家模块。&lt;/p&gt;
&lt;p&gt;TALM（Tool Augmented Language Models）和Toolformer都是对LLM进行微调，让其学会使用外部工具API。&lt;/p&gt;
&lt;p&gt;HuggingGPT是一个使用ChatGPT作为任务规划器的框架，根据模型描述选择HuggingFace平台中可用的模型，并根据执行结果总结响应。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://kevinchen1994.github.io/images/notion_10baf165-a7b7-4b36-b9cb-3be7f8ce551f56d6065a-8a9f-4353-b13b-18c5ab114ade.jpg&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;challenges&#34;&gt;Challenges&lt;/h2&gt;
&lt;p&gt;Agent虽然可以帮我们解决复杂的任务，但是仍然有很多限制和挑战。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LLM的上下文长度有限，对于复杂的任务，需要记录很多步骤、指令、工具介绍等情况，很容易把上下文窗口占满从而影响Agent的能力。&lt;/li&gt;
&lt;li&gt;在planning阶段如果出错，那Agent就很难得到正确的答案，或者走很多弯路，对资源消耗比较大，目前没有完美的解决方案。&lt;/li&gt;
&lt;li&gt;自然语言的可靠性，当前的Agent都是依赖自然语言作为LLM与其他组件交流的工具，然而自然语言容易有歧义，文本格式错误也可能导致理解错误，所以成功率并不高。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;从相信LLM无所不能，到高频使用后的去魅，再到Agent解决复杂的问题，让我更加了解了LLM的能力边界，LLM更适合做一个大脑，通过结合不同的模块发挥更大的作用，但是目前来看局限性比较大，很多场景需要人工的设置一些规则才能让Agent有好的表现，所以未来还有很长的路要走，不过我们可以想一想目前哪些任务我们可以交给Agent去做，从而提高我们的效率，让我们更专注于做一些价值更高的事情。&lt;/p&gt;
&lt;h2 id=&#34;citation&#34;&gt;Citation&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://lilianweng.github.io/posts/2023-06-23-agent/&#34;&gt;LLM Powered Autonomous Agents&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>KVCache feat. 单向注意力VS双向注意力</title>
      <link>https://kevinchen1994.github.io/posts/kvcache-feat.-%E5%8D%95%E5%90%91%E6%B3%A8%E6%84%8F%E5%8A%9Bvs%E5%8F%8C%E5%90%91%E6%B3%A8%E6%84%8F%E5%8A%9B/</link>
      <pubDate>Wed, 12 Jun 2024 00:00:00 +0000</pubDate>
      <guid>https://kevinchen1994.github.io/posts/kvcache-feat.-%E5%8D%95%E5%90%91%E6%B3%A8%E6%84%8F%E5%8A%9Bvs%E5%8F%8C%E5%90%91%E6%B3%A8%E6%84%8F%E5%8A%9B/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;在使用大模型进行推理时我们都会觉得模型的推理速度比较慢，当前也有很多推理加速的方法，像是模型量化、FlashAttention、使用更好的GPU、KVCache等，今天我们就来聊聊KVCache是怎么回事，我会从transformer decoder的推理过程开始，到为什么KVCache可以加速模型推理，以及具体的效果进行介绍。&lt;/p&gt;
&lt;h2 id=&#34;transformer的self-attention机制&#34;&gt;Transformer的self-attention机制&lt;/h2&gt;
&lt;p&gt;目前的大模型都是基于Transformer的decoder架构进行设计的，所以先把著名的self-attention公式抛出来。&lt;/p&gt;
&lt;p&gt;由于大模型使用的是decoder，所以在计算时会mask掉当前token的后边的token，例如当前为token_n，mask矩阵会mask掉n之后的所有token值，目的是防止解码过程中看到答案。&lt;/p&gt;
&lt;p&gt;下图是GPT2的解码过程，给定输入，模型预测下一个token，然后在下一步中使用上一步预测的token作为输入再次进行预测。图来源：&lt;a href=&#34;https://jalammar.github.io/illustrated-gpt2/&#34;&gt;https://jalammar.github.io/illustrated-gpt2/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://kevinchen1994.github.io/images/notion_4057612f-0c72-4a90-a7ee-7b28e0d726dc56e50bbd-2997-4f89-bfeb-a27377d1c666.gif&#34;&gt;&lt;/p&gt;
&lt;p&gt;我们来逐步计算一下解码的过程。&lt;/p&gt;
&lt;p&gt;因为decoder中的self-attention是masked self-attention，所以在计算时需要注意进行mask。&lt;/p&gt;
&lt;p&gt;我们将q和k的计算整理成矩阵，可以得到以下公式。&lt;/p&gt;
&lt;p&gt;展开的话就是这样的一个矩阵。&lt;/p&gt;
&lt;p&gt;对于token_1，Attention_1(Q,K,V)=softmax(\frac{Q_1K^T_1}{\sqrt{d_k}})\vec{V_1}&lt;/p&gt;
&lt;p&gt;对于token_2，Attention_2(Q,K,V)=softmax(\frac{Q_2K^T_1}{\sqrt{d_k}})\vec{V_1}+softmax(\frac{Q_2K^T_2}{\sqrt{d_k}})\vec{V_2}&lt;/p&gt;
&lt;p&gt;对于token_3，Attention_3(Q,K,V)=softmax(\frac{Q_3K^T_1}{\sqrt{d_k}})\vec{V_1}+softmax(\frac{Q_3K^T_2}{\sqrt{d_k}})\vec{V_2}+softmax(\frac{Q_3K^T_3}{\sqrt{d_k}})\vec{V_3}&lt;/p&gt;
&lt;p&gt;可以看到在token_2推理的过程中，K_1、V_1是重复使用的；可以看到在token_3推理的过程中，K_1、V_1、K_2、V_2是重复使用的。&lt;/p&gt;
&lt;p&gt;还可以看出来，每次计算attention只需要使用当前的Q即可，并不需要之前的向量。&lt;/p&gt;
&lt;p&gt;所以我们就可以把之前计算过的K、V缓存起来，这就是今天我们要介绍的KVCache。&lt;/p&gt;
&lt;h2 id=&#34;kvcache的作用&#34;&gt;KVCache的作用&lt;/h2&gt;
&lt;p&gt;现在我们就可以给KVCache进行定义了，在decoder-only架构中，通过缓存解码过程中的K、V，来避免重复计算，从而达到推理加速的效果。&lt;/p&gt;
&lt;p&gt;下图清晰了对比了使用KVCache和不使用KVCache的区别，图来源&lt;a href=&#34;https://medium.com/@joaolages/kv-caching-explained-276520203249&#34;&gt;https://medium.com/@joaolages/kv-caching-explained-276520203249&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://kevinchen1994.github.io/images/notion_2772e1c2-6780-4c33-a6aa-75a1b091219d9109d308-9ff2-4e32-8ffd-f1fd908c98a1.gif&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;实现细节&#34;&gt;实现细节&lt;/h2&gt;
&lt;p&gt;在huggingface的transformers中，通过modelling_gpt2.py可以看到具体的实现细节。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        query &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;_split_heads(query, self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;num_heads, self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;head_dim)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        key &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;_split_heads(key, self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;num_heads, self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;head_dim)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        value &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;_split_heads(value, self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;num_heads, self&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;head_dim)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#75715e&#34;&gt;# 通过layer_past来传递上一次计算的key value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; layer_past &lt;span style=&#34;color:#f92672&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            past_key, past_value &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; layer_past
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;# 通过拼接来得到最新的key 和 value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            key &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; torch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;cat((past_key, key), dim&lt;span style=&#34;color:#f92672&#34;&gt;=-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            value &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; torch&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;cat((past_value, value), dim&lt;span style=&#34;color:#f92672&#34;&gt;=-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; use_cache &lt;span style=&#34;color:#f92672&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            present &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (key, value)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            present &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;在transformers中使用kvcache对比&#34;&gt;在transformers中使用KVCache对比&lt;/h2&gt;
&lt;p&gt;在Transformers中进行对比开启KVCache后的效果。&lt;/p&gt;</description>
    </item>
    <item>
      <title>RAG技术知识点扫盲</title>
      <link>https://kevinchen1994.github.io/posts/rag%E6%8A%80%E6%9C%AF%E7%9F%A5%E8%AF%86%E7%82%B9%E6%89%AB%E7%9B%B2/</link>
      <pubDate>Thu, 25 Jan 2024 00:00:00 +0000</pubDate>
      <guid>https://kevinchen1994.github.io/posts/rag%E6%8A%80%E6%9C%AF%E7%9F%A5%E8%AF%86%E7%82%B9%E6%89%AB%E7%9B%B2/</guid>
      <description>RAG这个词听过很多次，我只是了解他大概是做什么的，今天看到一篇文章详细介绍了RAG的流程和基本原理，觉得很不错，就照着写了这篇文章，算是一种记录和知识扫盲吧。</description>
    </item>
    <item>
      <title>Mixtral 8x7B MoE模型笔记</title>
      <link>https://kevinchen1994.github.io/posts/mixtral-8x7b-moe%E6%A8%A1%E5%9E%8B%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Fri, 05 Jan 2024 00:00:00 +0000</pubDate>
      <guid>https://kevinchen1994.github.io/posts/mixtral-8x7b-moe%E6%A8%A1%E5%9E%8B%E7%AC%94%E8%AE%B0/</guid>
      <description>随着 Mixtral 8x7B 的推出，一种称为混合专家模型 (Mixed Expert Models，简称 MoEs) 的 Transformer 模型在开源人工智能社区引起了广泛关注。</description>
    </item>
    <item>
      <title>大模型的分词算法</title>
      <link>https://kevinchen1994.github.io/posts/%E5%A4%A7%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%88%86%E8%AF%8D%E7%AE%97%E6%B3%95/</link>
      <pubDate>Wed, 06 Dec 2023 00:00:00 +0000</pubDate>
      <guid>https://kevinchen1994.github.io/posts/%E5%A4%A7%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%88%86%E8%AF%8D%E7%AE%97%E6%B3%95/</guid>
      <description>大模型如何读懂自然语言，需要我们将文本转成机器能读懂的数字，这篇文章介绍了一些从文本到数字的算法。</description>
    </item>
    <item>
      <title>PEFT</title>
      <link>https://kevinchen1994.github.io/posts/peft/</link>
      <pubDate>Fri, 25 Aug 2023 00:00:00 +0000</pubDate>
      <guid>https://kevinchen1994.github.io/posts/peft/</guid>
      <description>对于大模型微调起来不仅需要很多计算资源（GPU），还需要大量的训练时间，PEFT通过高效微调模型，使得我们可以使用单卡去训练比较大的LLM。</description>
    </item>
    <item>
      <title>GPT系列语言模型</title>
      <link>https://kevinchen1994.github.io/posts/gpt%E7%B3%BB%E5%88%97%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B/</link>
      <pubDate>Wed, 16 Aug 2023 00:00:00 +0000</pubDate>
      <guid>https://kevinchen1994.github.io/posts/gpt%E7%B3%BB%E5%88%97%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B/</guid>
      <description>科普，无技术技术分享，像讲故事一样根据时间线来介绍GPT1到GPT4。</description>
    </item>
  </channel>
</rss>
