欢迎来到我的厨房

👋嗨,我是Kevin,自然语言处理算法工程师👨🏻‍💻,不严肃跑者🏃,热爱生活的编程少年🧠,INFJ-A。

笔记是总结知识增援未来的自己,写作是对未来要认识你的人的自我介绍。

这个博客主要用来记录我的学习、生活、思考,你可以通过标签筛选你感兴趣的内容。

如果你想了解我,可以在About Me页面进行查看。

本博客是如何构建的feat. AI Coding

通过AI Coding构建了本博客,基于Notion作为CRM,使用Hugo主题进行部署。主要谈了我对于AI Coding的使用和思考。

2025-03-18

无限增长假设feat.瓶颈期

跑步计划失败的复盘,让我认识到无限增长假设,以及如何应对的问题,希望我的经历,能为你面对瓶颈期提供一些启发。

2025-03-01

我为自己制作了一个阅读工具

自己制作的read later和知识库管理工具

2025-01-13

AI时代像老板一样工作

在AI时代,AI工具就像“员工”一样,我们应该学会像老板一样工作,给“员工”安排好任务,提高整个”公司“的工作效率。

2024-11-29

Influence without authority,愤怒是可以控制的

通过亲身经历,结合职场,探讨influence without authority中重要的一点-愤怒是一种可以控制的情绪,而不是解决问题的有效手段。

2024-11-28

Agent Ⅱ 手搓一个Agent feat. Qwen-Agent

前言 上一篇文章介绍了关于Agent的一些相关内容,这篇文章来动手实现一个Agent。目前比较流行的Agent开发框架有很多,比如可视化的字节的扣子,还有代码实现的babyagi、AutoGPT,因为我用qwen用的比较多,正好我最近看到qwen也开源了一套框架,qwen-agents,封装了工具、助手和一些规划的方法,使用起来比较方便,那就用这套框架实现一个简单的Agent。 Agent设计开发 既然是Agent,那就让他做一个LLM不能直接实现的任务,我这边有一个北京的房价表格,我们可以让Agent帮我们分析一下房价,最后生成一个图标来展示每平米的价格。 因为这个任务需要多步骤才能实现,所以我们可以使用上篇文章中将的ReAct的思路,让模型自己规划任务,根据每一次的执行结果来调整任务,并且可以利用代码助手来帮助他实现目标。 先配置LLM,这里可以使用阿里的api,也可以使用第三方的api,只要与openAI库兼容就可以。我这里尝试了付费的qwen-max和免费的Qwen2-7B-Instruct。 llm_cfg = { # 使用 DashScope 提供的模型服务: # 'model': 'qwen-max', # 'model_server': 'dashscope', # 'api_key': 'EMPTY', # 如果这里没有设置 'api_key',它将读取 `DASHSCOPE_API_KEY` 环境变量。 # 使用与 OpenAI API 兼容的模型服务,例如 vLLM 或 Ollama: 'model': 'alibaba/Qwen2-7B-Instruct', 'model_server': 'http://localhost:8000/v1', # base_url,也称为 api_base 'api_key': 'EMPTY', # (可选) LLM 的超参数: 'generate_cfg': { 'top_p': 0.8 } } 然后去定义我们的Agent,因为框架封装的很方便了,所以几行代码就可以实现。 可以看到我们只需要配置Agent能够使用的工具,以及Agent的名称,他能做什么就可以了。工具方面我这边只使用了代码解释器,框架还封装了很多其他的工具,比如联网搜索、图片生成(需要api支持)、RAG等。框架也支持自定义工具,可以根据自己的需要实现特定功能的工具。 def init_agent_service(): llm_cfg = { } tools = ['code_interpreter'] bot = agents.ReActChat(llm=llm_cfg, name='house price analyzer', description='You are a house price analyzer, you can run code to analyze house price.', function_list=tools) return bot 然后就可以配置测试的方法了,可以通过命令行进行测试,也可以通过GUI进行测试,框架基于gradio开发了很方便的GUI方法,我就选择GUI来进行测试。 ...

2024-06-21

Agent Ⅰ Introduction

Overview 随着ChatGPT的流行,我们似乎觉得LLM能够帮我们解决任何问题,但是长时间使用下来,有一些问题LLM并不能很好的解决,比如我想让LLM基于一次考试后的全班试卷帮我统计某个班级的最高分、最低分、平均分,并且针对考试较差的学生提出针对性的建议。目前所有的LLM都无法直接做到,因为首先全班所有的试卷就已经够长了,LLM的上下文长度可能都不够,再就是LLM并不擅长做关于数字的内容,因为数字对于他来说就是token,他有可能并不清楚数字token之间的关系。 那这个问题怎么解决呢,那就是通过Agent来解决,我们让LLM作为大脑,让其拥有记忆功能来存储试卷内容,还可能让其调用工具,让其学会计算,对于他也不会的知识点,他还可以上网搜索学会了再来辅导学生。这是不是就有人工智能那味儿了。 Agent能够通过构建LLM与规划、记忆、工具和执行来完成复杂的任务,LLM在其中扮演的就是大脑的角色,通过将复杂任务进行拆解,并且通过调用工具和存储来逐一解决小任务,最终完成复杂的任务。Agent能够大大提升LLM的实用性,让其不仅仅是一个只会对话的模型,而是有了规划和思考的能力。 下图为Agent的构成的概要。 Memory 人类的大脑中有多种记忆模式,比如短期记忆,用于存储当下的一些信息,例如我们现在与人对话的上下文,还有长期记忆,用于存储我们的知识体系。Agent也是一样,短期记忆用于存储当前会话的上下文,一般通过模型的上下文窗口来解决,长期记忆用于存储知识库和历史行为,一般通过外部存储来解决。 短期记忆受模型上下文窗口限制,所以不会太长,随着上下文长度的增长,对于显存的占用也会同步增加,所以这部分我们尽量控制的短一些,如果是超长的上下文,我们也可以将其转换为长期记忆来存储。 长期记忆其实也就是RAG,我们通过外部向量存储知识库,可以快速检索和访问,因为向量库相对比较便宜,所以我们可以存储大量的知识以供Agent使用,并且向量库的内容我们还可以经常更新,让模型在不调整参数的同时就拥有了比较新的知识。 Planning 无反馈规划 对于复杂的任务将其进行拆解能够帮助Agent更好的进行执行。 对于LLM来说,他并不会主动将任务进行拆解,我们可以通过CoT(Chain of Though)让其进行拆解复杂任务,“let’s think step by step”就是一句魔法咒语,在prompt开头添加这句话,能够让模型分步骤解决问题,从而获得更高的准确率。 在CoT的基础上,还有ToT(Tree of Though)的方法,通过在每一步探索多个可能得路径,形成树状结构,再通过DFS或者BSF来评估每个步骤的有效性。 还有一种方法是LLM+P,也就是通过外部规划期来进行长期规划,这种方法先将问题转化为PDDL格式,然后利用规划期生成方案,最终将这一方案转换为自然语言。本质上,规划步骤被外包给外部工具,假设特定领域的 PDDL 和合适的规划器可用,这在某些机器人设置中很常见,但在许多其他领域并不常见。 有反馈规划 如果模型规划有问题也不能很好的解决复杂的问题,所以我们可以让Agent通过反馈来进行规划,以纠正以前的错误,这对于解决复杂的任务有着至关重要的作用,毕竟人类在解决复杂问题时也会通过复盘来迭代自己的方法。姚顺雨大佬的两篇论文就是解决这个问题。 ReAct通过结合特定任务的离散动作与语言描述,实现了LLM中融合推理和执行的能力。离散动作能够与现实环境进行交互,语言米哦啊哈苏则可能促进LLM产生基于自然语言的推理路径。这种策略不仅提高了LLM处理复杂问题的能力,还通过与外部环境直接交互,增强了模型在真实世界中的适应性和灵活性。 具体的就是通过一下prompt模板,让LLM思考其Though、Action、Observation。 Thought: ... Action: ... Observation: ... ... (Repeated many times) 下图可以看到使用ReAct后的效果,并且对比了只使用推理(reason)和只使用执行(act)的区别。在使用了推理+执行后,模型可以很好的规划这个任务,并且根据每一步的结果来规划下一步需要做什么,最终得到正确的答案。 传统的强化学习学习大量的训练样本和计算资源来让模型从错误中进行学习,Reflexion提出了一种新的框架,不通过更新模型的权重,而是通过自然语言的反馈来增强模型从错误中学习。 Reflexion有一个标准的RL设置,其中简历模型提供简单的二元奖励,动作空间遵守ReAct中的设置,其中特定于任务的动作空间通过语言进行增强,以实现复杂的推理步骤。每一次执行,执行者(Actor)都会基于观察状态生成文本和动作,执行后,评估者(Evaluator)会对执行者生成的内容计算奖励分数,自我反思模型(Self-reflection)会生成口头自我反思提示以协助执行者进行改进,对于效率低下的规划,因为会存储在长期记忆中,所以会被识别到一直没有完成,这时自我反思模型会考虑将其停止。 Tools 曾几何时,人们普遍认为“使用工具”是人和动物最大的区别,虽然现在人们不这么认为了,但是人类文明发展史很大程度上就是一部人类发明工具帮助人类做事情的历史。如果Agent也能像人类一样使用工具就能够大大提升LLM的能力范围。 比如LLM对数字不够敏感,可能很多加减法都会做错,但是如果他能够调用计算器,那多复杂的运算也能够准确的计算出来。还有很多工具,像是网页浏览、写代码、画图、调用API等等,都能够有效的提升LLM的能力。 以下是一些LLM使用工具的方法: MRKL(Modular Reasoning, Knowledge and Language)包含一组专家模块,LLM作为路由器将查询路由到最合适的专家模块。 TALM(Tool Augmented Language Models)和Toolformer都是对LLM进行微调,让其学会使用外部工具API。 HuggingGPT是一个使用ChatGPT作为任务规划器的框架,根据模型描述选择HuggingFace平台中可用的模型,并根据执行结果总结响应。 Challenges Agent虽然可以帮我们解决复杂的任务,但是仍然有很多限制和挑战。 LLM的上下文长度有限,对于复杂的任务,需要记录很多步骤、指令、工具介绍等情况,很容易把上下文窗口占满从而影响Agent的能力。 在planning阶段如果出错,那Agent就很难得到正确的答案,或者走很多弯路,对资源消耗比较大,目前没有完美的解决方案。 自然语言的可靠性,当前的Agent都是依赖自然语言作为LLM与其他组件交流的工具,然而自然语言容易有歧义,文本格式错误也可能导致理解错误,所以成功率并不高。 Summary 从相信LLM无所不能,到高频使用后的去魅,再到Agent解决复杂的问题,让我更加了解了LLM的能力边界,LLM更适合做一个大脑,通过结合不同的模块发挥更大的作用,但是目前来看局限性比较大,很多场景需要人工的设置一些规则才能让Agent有好的表现,所以未来还有很长的路要走,不过我们可以想一想目前哪些任务我们可以交给Agent去做,从而提高我们的效率,让我们更专注于做一些价值更高的事情。 Citation LLM Powered Autonomous Agents ...

2024-06-20

KVCache feat. 单向注意力VS双向注意力

前言 在使用大模型进行推理时我们都会觉得模型的推理速度比较慢,当前也有很多推理加速的方法,像是模型量化、FlashAttention、使用更好的GPU、KVCache等,今天我们就来聊聊KVCache是怎么回事,我会从transformer decoder的推理过程开始,到为什么KVCache可以加速模型推理,以及具体的效果进行介绍。 Transformer的self-attention机制 目前的大模型都是基于Transformer的decoder架构进行设计的,所以先把著名的self-attention公式抛出来。 由于大模型使用的是decoder,所以在计算时会mask掉当前token的后边的token,例如当前为token_n,mask矩阵会mask掉n之后的所有token值,目的是防止解码过程中看到答案。 下图是GPT2的解码过程,给定输入,模型预测下一个token,然后在下一步中使用上一步预测的token作为输入再次进行预测。图来源:https://jalammar.github.io/illustrated-gpt2/ 我们来逐步计算一下解码的过程。 因为decoder中的self-attention是masked self-attention,所以在计算时需要注意进行mask。 我们将q和k的计算整理成矩阵,可以得到以下公式。 展开的话就是这样的一个矩阵。 对于token_1,Attention_1(Q,K,V)=softmax(\frac{Q_1K^T_1}{\sqrt{d_k}})\vec{V_1} 对于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} 对于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} 可以看到在token_2推理的过程中,K_1、V_1是重复使用的;可以看到在token_3推理的过程中,K_1、V_1、K_2、V_2是重复使用的。 还可以看出来,每次计算attention只需要使用当前的Q即可,并不需要之前的向量。 所以我们就可以把之前计算过的K、V缓存起来,这就是今天我们要介绍的KVCache。 KVCache的作用 现在我们就可以给KVCache进行定义了,在decoder-only架构中,通过缓存解码过程中的K、V,来避免重复计算,从而达到推理加速的效果。 下图清晰了对比了使用KVCache和不使用KVCache的区别,图来源https://medium.com/@joaolages/kv-caching-explained-276520203249 实现细节 在huggingface的transformers中,通过modelling_gpt2.py可以看到具体的实现细节。 query = self._split_heads(query, self.num_heads, self.head_dim) key = self._split_heads(key, self.num_heads, self.head_dim) value = self._split_heads(value, self.num_heads, self.head_dim) # 通过layer_past来传递上一次计算的key value if layer_past is not None: past_key, past_value = layer_past # 通过拼接来得到最新的key 和 value key = torch.cat((past_key, key), dim=-2) value = torch.cat((past_value, value), dim=-2) if use_cache is True: present = (key, value) else: present = None 在transformers中使用KVCache对比 在Transformers中进行对比开启KVCache后的效果。 ...

2024-06-12

把手弄脏

上周我写了一篇关于有目的的阅读、学习和工作的文章,主要是为了解决低效率的问题。这周,我想谈谈具体的行动问题,即如何动手实践。在这个过程中,我想到了一系列的关键词:把手弄脏、手感、知行合一、输入输出。接下来,我将结合我阅读的一些文章,详细来聊聊我的想法,主要以阅读和写作为例。 作为一个每天接受大量输入的人,我也有一些输出,比如每周写周记,平时记录灵感和想法在flomo中,或者在个人博客上更新成熟的观点。然而,目前我的输出远远少于输入,这导致了无法形成输入与输出的闭环。有时即使有写作的想法,也迟迟不能动笔,不知道如何开始,或担心被打断等。 我记得看过一个观点:越分享你的观点,你的观点就越成熟。很多时候,我们害怕自己的观点不够成熟,或羞于表达,就把它们藏在心里,久而久之可能就忘了。如果你把它们分享出来,不仅能帮助你梳理自己的想法,还能通过与他人的讨论不断完善和成熟这些观点。 写作是让思想更加锐利的工具。即使你脑子里的想法再多,如果不写下来,也难以清晰地梳理。因此,写作是一种将脑海中的网状知识转化为树状结构的方法,能够让你理清思路,使思想更有条理。 孟岩的文章和播客中提到了费曼学习法,其核心思想是通过教授他人来发现自己理解上的不足。教授的对象最好是对你讲述的知识完全不了解的人,甚至是小朋友,用尽量简单的语言。如果你能让对方理解这些知识,就说明你真的掌握了,否则就是没有完全掌握。同样,如果你能通过文字清晰地表达知识或想法,让大家理解,这也是利用费曼学习法减少知识的缝隙的方式。 我们看到很多优秀的人,他们的文章和讲话总是能引起共鸣,这其实是经过多次刻意练习的结果。很早之前,我在知乎上看到半佛回答过如何锻炼写作能力的问题。他建议每天在知乎热榜里找到一个问题,写下一个回答,不用在意对错,坚持一段时间,无论什么话题都会有写不完的话。这种方法就是刻意练习。 辉哥说过,周更比日更更难,月更更不容易。所以,开始写作首先应该是面向自己,把自己当作唯一的读者,谈论任何话题和观点,不用担心别人的看法,这样更容易进入心流状态,轻松写完一篇文章。时机成熟时,再决定是否发表。 携隐Melody也提到,通过输出倒逼输入,想要保持成长速度,就要多输出。她建议每天写作,控制在800-1000字,这样既不会花费太多时间,也足够表达观点。随着短内容的积累,再去写长篇大论会容易得多。养成每天输出的习惯后,你自然而然就会想接下来我会写什么,你就会主动去学习一些知识来丰富自己的资源库,这也就达到了输出倒逼输入的目的。 这些写作的方法可以泛化到其他任务,比如学习和工作。如果你掌握的知识与实际操作之间存在gap,就需要动手去实践,把手弄脏,这样才能形成闭环,使知识掌握得更加牢固。 参考资料 阅读思考行动的闭环 把自己当成唯一读者 知识的缝隙 输出倒逼输入

2024-05-21

带有目的的阅读、学习、工作

前言 这篇文章主要是来讨论在平时的阅读、学习和工作中如何保证高效率且有意义,文章分类我放在了时间管理中,主要原因是高效率的前提是时间管理要做好,否则就是空谈了。时间管理这个类别我应该会持续更新,因为在这方面我感觉自己做的还不够,还有好多要学习的地方,接下来有了新的感悟我会总结下来。 分析自身 在上一篇文章中我提到了通过『判断信息是否与我有关』和『信息是否接近真相』来过滤信息源,这能大大减少我在无效信息上花费的时间,另外我还会使用日历来进行管理我每天的日程,最近我分析了我这两个月的日程安排,看上去似乎是满满当当,但是确实没有章法,很多事情被我安排的东一榔头西一棒槌,那么我就很难在这些事情上进入心流状态,完成的效果也不尽如人意。 有一篇文章讲的是『深度阅读为何如此重要』,给了我挺大的启发,文章的主要观点是我们注意力比较分散时,就无法完整的感知这个世界,也很难把充分的注意力集中到困难的事情上,从而难以进行深度思考。不光是阅读,学习和工作应该是一样的道理,只有把全部的注意力集中到当前的事情上,才能进入心流状态,从而高质高效的完成。 很明显我的日程安排把我的注意力打散了,在按照日程进行执行的时候,通常只是执行且没有目的,所以我需要想办法去解决这个问题。 目的是什么 之前提过FOMO这种心态,我觉得通过上篇文章中的过滤信息源的方法已经很好的解决了我的FOMO心态,但是仍然不够彻底,那就结合目的来彻底解决。之所以会产生FOMO,无非是你想了解全部的信息,那目的就是获取尽可能多的信息,但是这有意义吗?你掌握的这些信息经过1年、5年或者10年以后基本没有任何价值,甚至在当下来看,也只能作为与人交流的谈资而已。 所以我们的目的是有问题的,对于资讯类的信息,我们的目的应该是了解即可,在阅读时只需要了解标题就够了,这花不了5秒钟,当然这可能会对注意力造成危害,这个问题后边我们会谈。 对于非资讯类的信息,这时候我们的目的就是判断有用的信息源,将信息汇总起来,通过我们的判断原则,如果与我有关且信息接近真相,那就把文章收集起来,在专门的阅读时间再读。 好的,这就是我们在『浏览』信息时需要做的事情了,现在来回答注意力的问题。之所以我这里会使用『浏览』这个词,是因为我们当下的目的并不是深度阅读,而是过滤信息,如果在过滤信息的同时进行深入阅读,很有可能我们的注意力又被打散,导致深度阅读不够深度,那我们的时间就又被浪费了。浏览信息我们尽量在碎片化时间进行,这时候我们的注意力本身就是涣散的,不需要集中精力进行思考,相信长期坚持下来,这套过滤信息的方法我们会掌握熟练,达到一种几乎不用过多的思考就能筛选信息的能力。 学习和工作是类似的思路,我们的目的就是提前做好准备,让学习和工作的冷启动变的容易,我们使用碎片化时间规划我们的安排,准备学习和工作的资料,为深度学习和工作做好准备。 带着目的执行任务 在我们整块的时间,我们会进行深度的阅读、学习和工作。这时候我们的目的就会根据具体的任务而变化,比如阅读,我们的目的是尽可能深入的了解一个行业,学习的目的是尽可能多的学习一个算法等等。 我们还需要对任务进行拆解,因为人的专注力是有限的,你不可能在很短的时间内完成一项重大的任务,那我们将比较大的任务拆解成小任务,也就相当于给每一个小任务设定了一个目标,带着这样的目的去执行任务的时候,我们就不会东一榔头西一棒槌,会很容易的进入心流状态,高效率的完成当前的任务。 最后一点就是识别到哪些工作是无意义的,课代表的视频说了90%的工作都是无意义的,徐老师还提到,面对海量信息,我们需要培养批判性思维,形成自己的判断框架,以便有效筛选出有价值的信息。可能我们识别哪些任务是否有意义有些困难,那就需要我们尽可能的多思考,我们的目的是什么,《高效能人士的七个习惯》中提到了『以终为始』,就是这个道理。通过最终的目的来判断我们的任务是否有意义,不要为了完成任务而完成任务。 总结 这篇文章相比于上一篇时间管理的文章,丰富了信息筛选的方法,信息筛选的目的是为了深度阅读做准备。我们弄清了我们的目的以后,在行动时就更能掌控自己的注意力,更快的进入心流的状态,高效的利用时间。

2024-05-17