[{"content":"在白嫖cloudfare worker和搭建 公网服务的时候发现api.cloudflare.com无法访问了于是乎又搭了一个worker，大家看到了可以直接用：ddns.nb404.cn\n访问它就相当于访问.cloudflare.com，又可以愉快白嫖了！\n原文链接: cloudflare的api无法访问问题 作者: lixusocool\n","permalink":"http://nb404.cn/posts/cloudflare%E7%9A%84api%E6%97%A0%E6%B3%95%E8%AE%BF%E9%97%AE%E9%97%AE%E9%A2%98/","summary":"\u003cp\u003e在白嫖cloudfare worker和搭建 公网服务的时候发现api.cloudflare.com无法访问了于是乎又搭了一个worker，大家看到了可以直接用：ddns.nb404.cn\u003c/p\u003e\n\u003cp\u003e访问它就相当于访问.cloudflare.com，又可以愉快白嫖了！\u003cimg loading=\"lazy\" src=\"/posts/images/0b6a26f42d3b4ce48d1f29b9616bc027.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/160194640?spm=1011.2415.3001.5331\"\u003ecloudflare的api无法访问问题\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"cloudflare的api无法访问问题"},{"content":"今天我们聊一个近期 AI 圈里的热门话题 — 和 Agent**。**\n一提到 AI，大家总说“让 AI 帮我干活”，可真要让 AI 落地做事，离不开 Workflow 与 。这俩到底在 AI 里扮演了什么角色，又有什么区别？\n今天我们就来详细聊聊**，揭开 AI 自动化的秘密**。\n1 Workflow：深耕多年的“流程老管家” Workflow，也叫。很多人以为它是 AI 带火的新词，其实它早就在各行业成熟应用了。比如：\n职场人熟悉的审批流：请假时，从提交申请到审批通过，每一步都有固定顺序，缺一不可； 程序员常用的持续集成：代码提交后，自动触发编译→测试→部署，全程按预设步骤走，无需人工干预； 这些场景的本质就是提前把规则写死，严格按照预设步骤执行。就像工厂里的流水线，螺丝拧几圈、零件放哪里，早就定好了，工人只要按流程走就行。\n它的核心工作流也不复杂，主要分为四步：\n触发：谁来启动这条流程？ 满足某个条件就自动开跑，比如点击提交、到达某个时间点、检测到有文件上传。\n编排：接下来按哪条路走？ 先做什么、后做什么，遇到不同情况走哪条分支，都提前设计好，相当于流程的“路线图”。\n执行：具体怎么干活？ 按照路线图真正去办事：比如提交后的发送消息通知、计算汇总数据、调用外部接口等，把每一步操作落地。\n结束：怎么收尾？ 流程跑完后，再把结果告知相关人，更新状态、保存记录，让这件事有一个完整闭环。\n可以说，传统 Workflow 就像一套按部就班、严谨执行的固定“剧本”，不会自主思考、也不会灵活变通。\n而当 AI 时代到来，Workflow 也迎来了新的角色与价值。\nAI 的落地离不开（LLM），但大模型再智能，也只是一个擅长理解生成、却不懂统筹调度的“超级大脑”。当我们需要把零散的思考变成可执行的步骤时，就需要一个统一调度的角色 — Workflow。它会决定什么时候调用大模型、让它处理什么内容、结果传给谁、下一步怎么走。\n正是这样，传统工作流才真正具备了理解意图、生成内容的智能能力，升级为 AI Workflow。\n比如 AI 智能客服，它的流程非常清晰：\n用户咨询 → 大模型识别意图 → 生成应对答案 → 回复用户。\n还有常用的 AI 生成社交文案的流程：\n输入需求 → 大模型提取关键词 → 生成文案 → 人工微调 → 发布\n在这些场景里，Workflow****把控全程节奏，大模型承担最耗时的理解与生成工作，把人从重复劳动中解放出来，效率大幅提升。\n不过，AI 加持后的 Workflow 虽然高效，也有明显局限：它只能按固定流程执行，一旦遇到没有预设规则、需要灵活判断的开放式任务，比如规划一场兼顾预算、喜好和出行体验的周末旅行，就难以胜任。\n这时候，能自主思考、自主决策的智能体 Agent，就登场了。\n2 Agent：AI 时代才起飞的智能体 如果说 Workflow 是“你教我怎么做，我就怎么做”，那 Agent 就是“你告诉我要什么，我自己想怎么做”。\n它最大的特点就是能自己思考、自己规划、主动解决问题，但早期的 Agent 没有这么智能，直到近几年**大语言模型的成熟，才迎来真正爆发。**大模型让 Agent 首次拥有了三个关键能力：\n理解能力：能听懂你模糊的自然语言，精准抓住你的真实需求； 推理能力：能自己思考、分析、判断，而不是只按固定规则走； 学习能力：能从海量信息里学习知识，不用人一条条写规则。 这些能力就像给 Agent 装上了会思考的“大脑”，但这还不够，想要 Agent 真正独立完成任务，还需要另外两样东西：\n第一会“动手” — 工具调用\n大模型虽然擅长思考与推理，但只能依靠历史****训练数据，无法主动获取实时信息、对接外部系统。\nAgent 在大模型的基础上，通过工具调用机制（比如 、LlamaIndex 这类框架），给大模型装上了“手脚” — 能调用外部 API、连接外部系统，把大模型“脑子”里的想法，真正落地。\n第二会“记住” — 记忆与状态\n大模型没有持久记忆能力，很难记住之前的内容，以至于每次对话都像重新开始。\nAgent 则专门开辟了一块“记忆空间”（本质是一套可读写的存储，比如数据库或向量库），把你的偏好、历史对话、任务进度都存在里面。从而做到连贯思考、不丢上下文。\n最终在大模型****+ 工具 + 记忆的共同支撑下，Agent 真正具备了自主完成任务的能力。在接到任务后，它会完整经历四步：\n理解任务：先搞清楚要做什么？ 先把模糊的需求变成清晰的目标。比如“根据这篇文档做成 10 道面试题”，Agent 会先明确：目标是“出题”，材料是“当前文档”，风格是“面试”。\n制定计划：这事儿拆成几步来做？ 拿到目标后，它再拆解步骤、规划路径：先通读文档 → 挑关键知识点 → 为每个点设计问题 → 再统一调整难度和表述。\n这里的执行步骤不是提前写死的，而是 Agent 在运行过程中动态推理出来的。\n行动与观察：先做哪一步，结果怎么样？ 接着按照计划执行，边做边看结果。同时根据结果不断更新自己判断：信息够不够？方向对不对？需不需要换个工具或改计划？也就是「思考 → 调用工具 → 看结果 → 再思考」的循环。\n评估与收尾：可以交差了吗？ 最后等执行结束，对结果进行评估：检查是否达标、内容是否完整，必要时再继续迭代优化，直到符合预期后，把结果交付给你。\n这套闭环让 Agent 彻底摆脱了“规则束缚”，能像人类一样灵活应对复杂、未知的任务。也正是凭借这种能力，Agent 成为了今天各类 AI 产品的核心组成，我们日常用到的很多产品，都有它的身影，比如：\n全能 AI 助手：豆包、ChatGPT 等，能帮我们规划生活、处理工作、解决各种日常问题； 智能开发工具：Cursor、Claude 等，辅助程序员写代码、查 Bug、分析复杂项目，大幅提升研发效率。 可以说，Agent 让 AI 从被动执行真正走向了主动解决问题，这也是为什么它能在短短几年内引爆整个 AI 行业。\n3 Workflow 与 Agent：AI 时代的协同共生 虽然 Agent 比 Workflow 更智能、更灵活，但二者并非相互替代，而是能力互补、协同共生。\nWorkflow 稳定可靠却缺乏灵活思考，Agent 聪明自主却难以完全把控。两者结合，才是当下 AI 自动化的最佳实践：\n面对复杂、模糊、开放的任务：比如规划周末旅行、整理文档出题，交给 Agent 去思考和决策； 面对确定、重复、需要稳定落地的任务：比如固定发送日报、自动编译测试，交给 Workflow 去执行和兜底。 最终形成一套以大语言模型为大脑、Agent 主导决策、Workflow 保障执行的融合架构，这也是目前主流 AI 应用的核心设计思路。一个完整的架构如图所示：\n我们只有理解这些核心组件的配合与协同机制，才能更清晰地看懂 AI 如何真正落地、如何真正为我们所用。\n那么，初学者想快速上手、落地自己的 AI 应用，该怎么选工具？\n这里给大家推荐两类最实用、最容易上手的工具：\n如果是想零代码/低代码、追求快速搭建，推荐可视化编排：\nDify：偏企业业务，适合做稳定可靠的内部 AI 应用，比如知识库、自动化审批。 Coze（扣子）：字节出品，偏轻量化、拖拽简单、插件丰富，适合大众快速创作，比如 AI 助手、小程序。 如果是有一定开发基础、想做更深度的定制，推荐代码框架：\nLangGraph：专注于单个复杂 Agent 的执行流程控制，擅长实现多步骤、可循环、带状态的 Agent 逻辑。 AutoGen：专注于多个 Agent 之间的协同合作，支持多个 Agent 角色对话、互相校验、共同完成复杂任务。 建议先从可视化工具上手理解逻辑，再逐步尝试代码框架深入定制，这是一条最稳妥、最高效的学习路径。\n最后想说，AI 行业每天都在涌现新名词、新概念。但万变不离其宗，关键是沉下心来建立体系化认知。只有夯实基础、稳步提升能力，才能在快速迭代的 AI 浪潮中跟上步伐，从容落地。\n原文链接: 一文读懂AI自动化核心：Workflow与Agent的区别，建议收藏 作者: 和老莫一起学AI\n","permalink":"http://nb404.cn/posts/%E4%B8%80%E6%96%87%E8%AF%BB%E6%87%82ai%E8%87%AA%E5%8A%A8%E5%8C%96%E6%A0%B8%E5%BF%83workflow%E4%B8%8Eagent%E7%9A%84%E5%8C%BA%E5%88%AB%E5%BB%BA%E8%AE%AE%E6%94%B6%E8%97%8F/","summary":"\u003cp\u003e今天我们聊一个近期 AI 圈里的热门话题 —  \u003cstrong\u003e和 Agent\u003c/strong\u003e**。**\u003c/p\u003e\n\u003cp\u003e一提到 AI，大家总说“让 AI 帮我干活”，可真要让 AI 落地做事，离不开 Workflow 与 。这俩到底在 AI 里扮演了什么角色，又有什么区别？\u003c/p\u003e\n\u003cp\u003e今天我们就来详细聊聊**，揭开 AI 自动化的秘密**。\u003c/p\u003e\n\u003ch2 id=\"1-workflow深耕多年的流程老管家\"\u003e1 Workflow：深耕多年的“流程老管家”\u003c/h2\u003e\n\u003cp\u003eWorkflow，也叫。很多人以为它是 AI 带火的新词，其实它早就在各行业成熟应用了。比如：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e职场人熟悉的审批流：请假时，从提交申请到审批通过，每一步都有固定顺序，缺一不可；\u003c/li\u003e\n\u003cli\u003e程序员常用的持续集成：代码提交后，自动触发编译→测试→部署，全程按预设步骤走，无需人工干预；\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg alt=\"在这里插入图片描述\" loading=\"lazy\" src=\"/posts/images/0a24fbf3c0e943e9b84b7e5302909a5a.png\"\u003e\u003c/p\u003e\n\u003cp\u003e这些场景的本质就是\u003cstrong\u003e提前把规则写死，严格按照预设步骤执行\u003c/strong\u003e。就像工厂里的流水线，螺丝拧几圈、零件放哪里，早就定好了，工人只要按流程走就行。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"在这里插入图片描述\" loading=\"lazy\" src=\"/posts/images/1e91fe3e3e0e4e658f5484af134f1349.png\"\u003e\u003c/p\u003e\n\u003cp\u003e它的核心工作流也不复杂，主要分为四步：\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e触发：谁来启动这条流程？\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e满足某个条件就自动开跑，比如点击提交、到达某个时间点、检测到有文件上传。\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e编排：接下来按哪条路走？\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e先做什么、后做什么，遇到不同情况走哪条分支，都提前设计好，相当于流程的“路线图”。\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e执行：具体怎么干活？\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e按照路线图真正去办事：比如提交后的发送消息通知、计算汇总数据、调用外部接口等，把每一步操作落地。\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e结束：怎么收尾？\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e流程跑完后，再把结果告知相关人，更新状态、保存记录，让这件事有一个完整闭环。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"图片\" loading=\"lazy\" src=\"/posts/images/b49c0893795978ce1081352a83924c48.jpeg\"\u003e\u003c/p\u003e\n\u003cp\u003e可以说，传统 Workflow 就像一套\u003cstrong\u003e按部就班、严谨执行\u003c/strong\u003e的固定“剧本”，不会自主思考、也不会灵活变通。\u003c/p\u003e\n\u003cp\u003e而当 AI 时代到来，\u003cstrong\u003eWorkflow 也迎来了新的角色与价值\u003c/strong\u003e。\u003c/p\u003e\n\u003cp\u003eAI 的落地离不开（LLM），但大模型再智能，也只是一个擅长理解生成、却不懂统筹调度的“超级大脑”。当我们需要把零散的思考变成可执行的步骤时，就需要一个统一调度的角色 — \u003cstrong\u003eWorkflow\u003c/strong\u003e。它会决定什么时候调用大模型、让它处理什么内容、结果传给谁、下一步怎么走。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"图片\" loading=\"lazy\" src=\"/posts/images/845196dfae63f07c575e213569d9c251.jpeg\"\u003e\u003c/p\u003e\n\u003cp\u003e正是这样，传统工作流才真正具备了理解意图、生成内容的智能能力，升级为 AI Workflow。\u003c/p\u003e\n\u003cp\u003e比如 AI 智能客服，它的流程非常清晰：\u003c/p\u003e\n\u003cp\u003e用户咨询 → 大模型识别意图 → 生成应对答案 → 回复用户。\u003c/p\u003e\n\u003cp\u003e还有常用的 AI 生成社交文案的流程：\u003c/p\u003e\n\u003cp\u003e输入需求 → 大模型提取关键词 → 生成文案 → 人工微调 → 发布\u003c/p\u003e","title":"一文读懂AI自动化核心：Workflow与Agent的区别，建议收藏"},{"content":"\n跨平台、功能丰富、极快：重新定义AI上下文通信的优先紧凑文本输出。\n对于者来说，在开发AI Agent时与浏览器交互是一个频繁的过程。让AI Agent更高效地操作浏览器是一个具有挑战性的问题。最近，在搜索AI测试解决方案时，我发现了Vercel开源的agent-browser，这是一款专为AI Agent设计的自动化CLI。\nagent-的特性：\n基于引用：快照返回带有引用的可访问树。 Agent优先：高效利用AI上下文，节省token。 会话：支持多个具有独立身份验证的隔离浏览器实例。 功能完整：支持超过50个命令，包括导航、表单操作和截图。 跨平台：支持macOS、Linux和Windows平台。 1、安装agent-browser 在安装agent-browser之前，请确保您的计算机上已安装Node.js。\n在命令行中输入以下命令。-g选项表示全局安装。\nnpm install -g agent-browser 成功安装agent-browser CLI后，继续输入命令agent-browser install，这将开始下载Chromium浏览器。\n安装Chromium浏览器...\r需要安装以下软件包：\rplaywright@1.58.2\r确定继续？(y) y 成功安装Chromium浏览器后，命令行将输出成功安装的消息。\n正在下载Chrome for Testing 145.0.7632.6 (playwright chromium v1208)...\r162.3 MiB [====================] 100% 0.0s\r...\r✓ Chromium安装成功 2、使用agent-browser 2.1 打开网页 agent-browser open https://agent-browser.dev/ 输出：\n✓ 无头浏览器自动化 for AI\rhttps://agent-browser.dev/ 2.2 获取当前网页的可访问树 agent-browser snapshot -i 输出：\n- 链接 \u0026#34;Made with love by Vercel\u0026#34; [ref=e1]\r- 链接 \u0026#34;agent-browser\u0026#34; [ref=e2]\r- 链接 \u0026#34;16k\u0026#34; [ref=e3]\r- 链接 \u0026#34;npm\u0026#34; [ref=e4]\r...\r- 按钮 \u0026#34;Ask AI\u0026#34; [ref=e26] 2.3 使用引用进行交互 agent-browser click @e3 输出：\n✓ 完成 2.4 截图 agent-browser screenshot ./page.png 输出：\n✓ 截图已保存到 ./page.png 2.5 关闭浏览器 agent-browser close 输出：\n✓ 浏览器已关闭 3、安装Skills agent-browser是一款专为AI Agent设计的CLI。结合AI Agent，您可以轻松地浏览器操作。\n安装agent-browser 后，您可以在Cursor、Claude Code或中控制浏览器，执行您想要的任务。\nnpx skills add vercel-labs/agent-browser --skill agent-browser 由于我的电脑上已经安装了Claude Code和LM Studio，并且下载了qwen3.5-35b-a3b模型，我使用以下命令启动Claude：\nclaude --model qwen3.5-35b-a3b 然后输入截图任务。Claude将开始执行任务并在命令行中显示执行过程：\n❯ 保存 https://agent-browser.dev/ 网页的截图到当前目录。\r⎿ 初始化中…\r⎿ 无效的工具参数\r⏺ Skill(agent-browser)\r⎿ 成功加载skill · 2个工具允许\r⏺ 我将导航到网页并截图。\r⏺ Bash(agent-browser open https://agent-browser.dev \u0026amp;\u0026amp;\ragent-browser wait --load networkidle \u0026amp;\u0026amp; agent-browser\rscreenshot screenshot.png)\r⎿ ✓ 无头浏览器自动化 for AI\rhttps://agent-browser.dev/\r⎿ ✓ 完成\r⎿ 截图已保存到screenshot.png 4、结束语 本文仅介绍了 agent-browser的一些功能。它还可以控制iOS模拟器中的Safari浏览器来执行移动测试任务。此外，它支持CDP模式，让您可以轻松连接到本地或远程浏览器。\n除了agent-browser skill外，它还提供与dogfood、electron和slack相关的skills。如果您感兴趣，可以阅读官方agent-browser文档了解更多详情。\n原文链接：Agent-browser浏览器自动化CLI - 汇智网\n原文链接: Agent-browser浏览器自动化CLI 作者: 新缸中之脑\n","permalink":"http://nb404.cn/posts/agent-browser%E6%B5%8F%E8%A7%88%E5%99%A8%E8%87%AA%E5%8A%A8%E5%8C%96cli/","summary":"\u003cp\u003e\u003cimg alt=\"Agent-browser浏览器自动化CLI\" loading=\"lazy\" src=\"/posts/images/dda43e169ec7fb82843208de562fb30d.webp\"\u003e\u003c/p\u003e\n\u003cp\u003e跨平台、功能丰富、极快：重新定义AI上下文通信的优先紧凑文本输出。\u003c/p\u003e\n\u003cp\u003e对于者来说，在开发AI Agent时与浏览器交互是一个频繁的过程。让AI Agent更高效地操作浏览器是一个具有挑战性的问题。最近，在搜索AI测试解决方案时，我发现了Vercel开源的agent-browser，这是一款专为AI Agent设计的自动化CLI。\u003c/p\u003e\n\u003cp\u003eagent-的特性：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e基于引用\u003c/strong\u003e：快照返回带有引用的可访问树。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAgent优先\u003c/strong\u003e：高效利用AI上下文，节省token。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e会话\u003c/strong\u003e：支持多个具有独立身份验证的隔离浏览器实例。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e功能完整\u003c/strong\u003e：支持超过50个命令，包括导航、表单操作和截图。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e跨平台\u003c/strong\u003e：支持macOS、Linux和Windows平台。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"1安装agent-browser\"\u003e1、安装agent-browser\u003c/h3\u003e\n\u003cblockquote\u003e\n\u003cp\u003e在安装agent-browser之前，请确保您的计算机上已安装Node.js。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e在命令行中输入以下命令。\u003ccode\u003e-g\u003c/code\u003e选项表示全局安装。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003enpm install -g agent-browser\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e成功安装agent-browser CLI后，继续输入命令\u003ccode\u003eagent-browser install\u003c/code\u003e，这将开始下载Chromium浏览器。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e安装Chromium浏览器...\r\n需要安装以下软件包：\r\nplaywright@1.58.2\r\n确定继续？(y) y\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e成功安装Chromium浏览器后，命令行将输出成功安装的消息。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e正在下载Chrome for Testing 145.0.7632.6 (playwright chromium v1208)...\r\n162.3 MiB [====================] 100% 0.0s\r\n...\r\n✓ Chromium安装成功\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"2使用agent-browser\"\u003e2、使用agent-browser\u003c/h3\u003e\n\u003ch4 id=\"21-打开网页\"\u003e2.1 打开网页\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eagent-browser open https://agent-browser.dev/\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e输出：\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e✓ 无头浏览器自动化 for AI\r\n  https://agent-browser.dev/\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"22-获取当前网页的可访问树\"\u003e2.2 获取当前网页的可访问树\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eagent-browser snapshot -i\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e输出：\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e- 链接 \u0026#34;Made with love by Vercel\u0026#34; [ref=e1]\r\n- 链接 \u0026#34;agent-browser\u0026#34; [ref=e2]\r\n- 链接 \u0026#34;16k\u0026#34; [ref=e3]\r\n- 链接 \u0026#34;npm\u0026#34; [ref=e4]\r\n...\r\n- 按钮 \u0026#34;Ask AI\u0026#34; [ref=e26]\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"23-使用引用进行交互\"\u003e2.3 使用引用进行交互\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eagent-browser click @e3\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e输出：\u003c/p\u003e","title":"Agent-browser浏览器自动化CLI"},{"content":" 问题类型 占比 可预防性 过热降频/关机 40% ⭐⭐⭐⭐⭐（加风扇即可） 电源不足 25% ⭐⭐⭐⭐（换好电源） 内核/驱动崩溃 20% ⭐⭐⭐（升级内核） 内存/存储故障 10% ⭐⭐（依赖硬件质量） 工具/配置错误 5% ⭐⭐⭐⭐（规范操作） 原文链接: 开发板常见问题 作者: lixusocool\n","permalink":"http://nb404.cn/posts/%E5%BC%80%E5%8F%91%E6%9D%BF%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98/","summary":"\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e问题类型\u003c/th\u003e\n          \u003cth\u003e占比\u003c/th\u003e\n          \u003cth\u003e可预防性\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e过热降频/关机\u003c/td\u003e\n          \u003ctd\u003e40%\u003c/td\u003e\n          \u003ctd\u003e⭐⭐⭐⭐⭐（加风扇即可）\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e电源不足\u003c/td\u003e\n          \u003ctd\u003e25%\u003c/td\u003e\n          \u003ctd\u003e⭐⭐⭐⭐（换好电源）\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e内核/驱动崩溃\u003c/td\u003e\n          \u003ctd\u003e20%\u003c/td\u003e\n          \u003ctd\u003e⭐⭐⭐（升级内核）\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e内存/存储故障\u003c/td\u003e\n          \u003ctd\u003e10%\u003c/td\u003e\n          \u003ctd\u003e⭐⭐（依赖硬件质量）\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e工具/配置错误\u003c/td\u003e\n          \u003ctd\u003e5%\u003c/td\u003e\n          \u003ctd\u003e⭐⭐⭐⭐（规范操作）\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/158649520?spm=1001.2014.3001.5502\"\u003e开发板常见问题\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"开发板常见问题"},{"content":" 优点 缺点 brower-use 使用官网SDK写一个python的api，挺好用的能识别网页绿色框框数量 官网api收费，使用免费的api不太好用github的部署麻烦，没有成功 magentic-ui-fara7B 部署简单成功也能识别绿色框框 调用的qubrid的api，几下就用完了。。。需要设置docker的普通用户权限 原文链接: 浏览器自动化agent体验（brower-use，magentic-ui-fara7B） 作者: lixusocool\n","permalink":"http://nb404.cn/posts/%E6%B5%8F%E8%A7%88%E5%99%A8%E8%87%AA%E5%8A%A8%E5%8C%96agent%E4%BD%93%E9%AA%8Cbrower-usemagentic-ui-fara7b/","summary":"\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e\u003c/th\u003e\n          \u003cth\u003e优点\u003c/th\u003e\n          \u003cth\u003e缺点\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003ebrower-use\u003c/td\u003e\n          \u003ctd\u003e使用官网SDK写一个python的api，挺好用的能识别网页绿色框框数量\u003c/td\u003e\n          \u003ctd\u003e官网api收费，使用免费的api不太好用github的部署麻烦，没有成功\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003emagentic-ui-fara7B\u003c/td\u003e\n          \u003ctd\u003e部署简单成功也能识别绿色框框\u003c/td\u003e\n          \u003ctd\u003e调用的qubrid的api，几下就用完了。。。需要设置docker的普通用户权限\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/158617112?spm=1001.2014.3001.5502\"\u003e浏览器自动化agent体验（brower-use，magentic-ui-fara7B）\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"浏览器自动化agent体验（brower-use，magentic-ui-fara7B）"},{"content":"花了我两三天，结果还是好的达到了我的预期 (o゜▽゜)o☆[BINGO!]\n先看下效果：\n如图所示脚本运行可以自动点击join按钮和滑动按钮，按时签到薅羊毛！\n我采用的是pyautogui+方式，非传统自动化工具如Selenium和Playwright，不过使用了DrissionPage来获取缺口图和背景图。\n已经适配windows和debian系统，最新的浏览器（其他没试）。\n分享源码给大家一起学习测试使用（不可用做非法用途！发生的非法事件与本人无关特此声明）\n：https://github.com/haolixu/geetest-auto\n：https://gitee.com/haolixu/geetest-auto\n那个依赖我没搞定，尝试了pip \u0026gt; requirements.txt和pipreqs . \u0026ndash;encoding=utf-8 \u0026ndash;force\n但是没啥用。。。还是缺依赖，你们有什么好的方法吗？\n需要注意的是浏览器需要设置一下：\nwin：D:\\浏览器\\QQBrowser\\QQBrowser.exe -sc=desktopshortcut -fixlaunch=0 \u0026mdash;debugging-port=9222\n：/usr/bin/qqbrowser-browser-stable %U -sc=desktopshortcut -fixlaunch=0 \u0026ndash;remote-debugging-port=9222\n原文链接: 成功破解geetestv4极验滑动验证码 作者: lixusocool\n","permalink":"http://nb404.cn/posts/%E6%88%90%E5%8A%9F%E7%A0%B4%E8%A7%A3geetestv4%E6%9E%81%E9%AA%8C%E6%BB%91%E5%8A%A8%E9%AA%8C%E8%AF%81%E7%A0%81/","summary":"\u003cp\u003e花了我两三天，结果还是好的达到了我的预期 (o゜▽゜)o☆[BINGO!]\u003c/p\u003e\n\u003cp\u003e先看下效果：\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/22e843018a6542dbacb9bf8888be20e5.gif\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/bd13ae3ce8fd4f6481bba8cde1b29923.png\"\u003e\u003c/p\u003e\n\u003cp\u003e如图所示脚本运行可以自动点击join按钮和滑动按钮，按时签到薅羊毛！\u003c/p\u003e\n\u003cp\u003e我采用的是pyautogui+方式，非传统自动化工具如\u003cstrong\u003eSelenium和Playwright，\u003cstrong\u003e不过使用了\u003c/strong\u003eDrissionPage\u003c/strong\u003e来获取缺口图和背景图。\u003c/p\u003e\n\u003cp\u003e已经适配windows和debian系统，最新的浏览器（其他没试）。\u003c/p\u003e\n\u003cp\u003e分享源码给大家一起学习测试使用（不可用做非法用途！发生的非法事件与本人无关特此声明）\u003c/p\u003e\n\u003cp\u003e：\u003ca href=\"https://github.com/haolixu/geetest-auto\"\u003ehttps://github.com/haolixu/geetest-auto\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e：\u003ca href=\"https://gitee.com/haolixu/geetest-auto\"\u003ehttps://gitee.com/haolixu/geetest-auto\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e那个依赖我没搞定，尝试了pip  \u0026gt; requirements.txt和pipreqs . \u0026ndash;encoding=utf-8 \u0026ndash;force\u003c/p\u003e\n\u003cp\u003e但是没啥用。。。还是缺依赖，你们有什么好的方法吗？\u003c/p\u003e\n\u003cp\u003e需要注意的是浏览器需要设置一下：\u003c/p\u003e\n\u003cp\u003ewin：D:\\浏览器\\QQBrowser\\QQBrowser.exe -sc=desktopshortcut -fixlaunch=0 \u0026mdash;debugging-port=9222\u003c/p\u003e\n\u003cp\u003e：/usr/bin/qqbrowser-browser-stable %U   -sc=desktopshortcut -fixlaunch=0 \u0026ndash;remote-debugging-port=9222\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/66481d475ca94ddb89b46e72a3375d02.png\"\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/021c0a97225e40d78fca6bcb9d33b535.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/158128351?spm=1001.2014.3001.5502\"\u003e成功破解geetestv4极验滑动验证码\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"成功破解geetestv4极验滑动验证码"},{"content":" 干货分享，感谢您的阅读！\n随着大语言（Large Language Model，LLM）能力的持续提升，业界对“让模型真正做事”的期待，已经从单轮对话生成文本，转向了具备自主决策、工具调用与多步执行能力的 Agent（智能体）系统。\n在这一演进过程中，一个逐渐清晰的共识是：Agent 并不是“更强的大模型”，而是“以大模型为大脑，外部系统为四肢”的工程系统。\n记忆、规划、、行动执行，这些能力本质上并不来自模型本身，而是通过工程框架将模型与外部能力进行组织、编排与约束的结果。正是在这一背景下，围绕 Agent 的研究与工程实践迅速发展，催生了诸如 ReAct、Auto-GPT、LangGraph、MetaGPT 等一系列方法与框架。\n我们将聚焦于 ModelScope-Agent 这一由阿里云魔搭社区推出的 框架，从能力结构、运行机制、典型任务示例与工程实践角度，系统解析如何基于该框架构建一个可扩展、可落地的 Agent 应用。\n一、为什么 Agent 不等于？ 在深入 -Agent 之前，有必要先澄清一个常见误区：Agent ≠ 更大的模型 ≠ 多轮 Prompt。\n从系统架构视角来看，一个可用的 Agent 至少包含以下几个核心组件：\n推理核心（LLM）：负责理解用户意图、进行任务拆解、生成行动决策。 工具系统（Tools / Plugins）：提供模型无法直接完成的能力，如搜索、计算、生成图片、调用 API 等。 执行与调度层（Executor / Orchestrator）：将模型输出的“意图”转化为真实的函数调用或外部服务请求。 记忆系统（Memory）：保存历史对话、中间结果、长期偏好，用于后续决策参考。 规划与反思机制（Planning \u0026amp; Reflection）：用于多步骤任务拆解、执行顺序安排，以及失败后的自我修正。 从这个角度看，Agent 是一个系统工程问题，而不是单一模型能力问题。ModelScope-Agent 正是试图在工程层面，为这些能力提供一套可组合、可扩展的实现框架。\n二、ModelScope-Agent 框架概览 ModelScope-Agent 是魔搭社区推出的一个 通用 Agent 开发框架，其目标并非“封装一个黑盒 Agent”，而是提供：\n标准化的 Agent 抽象 灵活的工具接入机制 可插拔的记忆与规划模块 面向多模态任务的统一调用方式 从系统结构上看（如下图所示，老版本结构，仅供参考）：\n利用ModelScope-Agent框架开发的Agent，除了可以提供文本创作之外，还能生成图片、视频、语音等内容。单个Agent具有角色扮演、LLM调用、工具使用、规划、记忆等能力。 技术上主要具有以下特点：\n简单的Agent实现流程：仅需指定角色描述、大模型名称、工具名列表，即可实现一个Agent应用，框架内部自动实现工具使用、规划、记忆等工作流的编排。 丰富的模型和工具：框架内置丰富的大模型接口，例如Dashscope和Modelscope模型接口，OpenAI模型接口等。内置丰富的工具，例如代码运行、天气查询、文生图、网页解析等，方便定制专属Agent。 统一的接口和高扩展性：框架具有清晰的工具、大模型注册机制，方便用户扩展能力更加丰富的Agent应用。 低耦合性：开发者可以方便地直接使用内置的工具、大模型、记忆等组件，而不需要绑定更上层的Agent。 三、ModelScope-Agent 的核心能力解析 （一）内容生成能力 与许多只聚焦文本任务的 Agent 框架不同，ModelScope-Agent 天然支持多模态工具接入，使 Agent 能够完成：\n文本生成与总结 图像生成与编辑 语音合成 视频生成 在实际体验中，你可以通过自然语言直接描述目标，例如：\n“帮我生成一个 10 秒的卡通风格短视频，主题是‘小熊学习编程’。”\nAgent 会自动识别这是一个视频生成任务，并调用对应的 video-generation 插件完成执行。这一过程对用户是透明的，但对开发者而言，插件调用路径是可控、可替换的。\n（二）单 Agent 的复合能力结构 基于 ModelScope-Agent 构建的单个 Agent，通常具备以下能力集合：\n角色设定（Role / Persona） LLM 调用与上下文管理 工具选择与参数构造 任务规划与步骤拆解 短期与长期记忆管理 这使得 Agent 不再只是“问一句答一句”，而是可以承担类似“助理”“执行者”“创作伙伴”的角色。\n四、典型任务场景解析 （一）完成一个简单任务：直接工具调用 最基础的 Agent 使用方式，是让模型直接生成可执行动作。\n例如，用户通过对话要求生成一个视频，Agent 会：\n解析用户意图（视频生成） 选择合适的插件 自动构造参数 调用插件并返回结果 虽然生成的视频可能较为简单，但它清晰地展示了 “自然语言 → 工具调用 → 可视化结果” 的完整链路。更重要的是，这种链路是可扩展的——如果你有更好的视频生成模型，只需替换插件实现即可。\n（二）完成多步骤复合任务：规划与调度 Agent 真正体现价值的场景，往往是一句话中包含多个子任务。\n例如：\n在这一场景下，Agent 需要完成：\n任务拆解（生成20字以内的广告词 → 生成音频 → 制作视频） 执行顺序规划 中间结果保存 不同工具的多次调用 目前这个在线演示工具的能力比较基础，因此我们可以要求模型只生成20个字以内的广告词，语音合成的模型能力比较稳定，语音效果较好。\n（三）多轮对话中的参数提取与记忆利用 默认情况下，ModelScope-Agent 内置记忆机制，可以从历史对话中提取关键信息，用于后续工具调用。\n例如：\n第一轮：用户生成一个故事 第二轮：用户让 Agent 总结标题 第三轮：用户要求“根据刚才的故事生成视频” 在第三步中，Agent 需要从历史上下文中提取故事内容作为视频生成参数。这一过程本质上涉及：\n对话记忆管理 参数抽取 工具调用上下文构建 这一能力是许多 AIGC 产品（如儿童故事应用）得以实现“连贯体验”的关键。\n（四）基于检索工具的问答能力 ModelScope-Agent 可以加载：\n知识库检索插件 搜索引擎插件（如modelscope_search） 当模型判断当前问题超出自身知识或需要实时信息时，会主动调用检索工具，再基于检索结果生成答案。这一模式与 RAG（Retrieval-Augmented ）高度一致，但在 Agent 框架下，检索本身被视为一种“工具行为”。\n五、ModelScope-Agent 已集成工具生态 目前，ModelScope-Agent 已集成大量官方工具，包括但不限于：\n网页搜索与浏览 代码解释器 天气查询 图像生成与增强 视频生成 语音合成 图像理解（Qwen-VL） 工具 工具地址 API-KEY配置 web_browser 网页浏览 web_search 网页搜索 code_interpreter 代码解释器 amap_weather 高德天气 AMAP_TOKEN 需要在环境变量中进行配置 image_gen Wanx 图像生成 DASHSCOPE_API_KEY 需要在环境变量中进行配置 qwen_vl Qwen-VL 图像识别 DASHSCOPE_API_KEY 需要在环境变量中进行配置 speech-generation 语音生成 MODELSCOPE_API_TOKEN 需要在环境变量中进行配置 video-generation 视频生成 MODELSCOPE_API_TOKEN 需要在环境变量中进行配置 text-address 地理编码 MODELSCOPE_API_TOKEN 需要在环境变量中进行配置 wordart_texture_generation 创意文字 DASHSCOPE_API_KEY 需要在环境变量中进行配置 style_repaint 人像风格重绘 DASHSCOPE_API_KEY 需要在环境变量中进行配置 image_enhancement 追影放大镜 DASHSCOPE_API_KEY 需要在环境变量中进行配置 同时，框架也支持第三方工具（如 LangChain Tool）的接入。这种设计，使 Agent 的能力边界不再由模型决定，而是由工具生态决定。\n六、如何体验与上手 （一）在线体验 你可以直接通过魔搭社区的在线空间体验 ModelScope-Agent，无需本地环境配置。\n（二）本地运行 对于开发者而言，更推荐直接克隆项目代码，在本地运行 ./examples 中的示例，通过阅读与修改代码来理解 Agent 的实际执行流程。 项目地址：\n七、总结：ModelScope-Agent 的工程价值 综合来看，ModelScope-Agent 的核心价值不在于“是否比其他 Agent 框架更强”，而在于：\n提供了可落地的工程实现 降低了 Agent 系统的开发门槛 对多模态任务有良好支持 具备清晰的扩展路径 对于希望将 Agent 能力真正引入业务系统的团队而言，它更像是一套Agent 基础设施模板，而不是一个一次性工具。\n与延伸阅读 https://edu.aliyun.com/course/3126500/lesson/342570389 ​​​​​​https://github.com/modelscope/modelscope-agent https://modelscope.cn https://arxiv.org/abs/2210.03629 （ReAct 论文） https://arxiv.org/abs/2303.17580 （Auto-GPT） https://arxiv.org/abs/2305.10601 （Plan-and-Solve） https://arxiv.org/abs/2310.08560 （Agent Survey） https://python.langchain.com/docs/modules/agents https://lilianweng.github.io/posts/2023-06-23-agent/ https://arxiv.org/abs/2005.11401 （RAG 原始论文） https://github.com/geekan/MetaGPT https://github.com/langchain-ai/langgraph https://huggingface.co/docs/transformers/agents 原文链接: 基于 ModelScope-Agent 框架构建可落地的大模型 Agent 应用实践 作者: 张彦峰ZYF\n","permalink":"http://nb404.cn/posts/%E5%9F%BA%E4%BA%8E_modelscope-agent_%E6%A1%86%E6%9E%B6%E6%9E%84%E5%BB%BA%E5%8F%AF%E8%90%BD%E5%9C%B0%E7%9A%84%E5%A4%A7%E6%A8%A1%E5%9E%8B_agent_%E5%BA%94%E7%94%A8%E5%AE%9E%E8%B7%B5/","summary":"\u003chr\u003e\n\u003cp\u003e干货分享，感谢您的阅读！\u003c/p\u003e\n\u003cp\u003e随着大语言（Large Language Model，LLM）能力的持续提升，业界对“让模型真正做事”的期待，已经从\u003cstrong\u003e单轮对话生成文本\u003c/strong\u003e，转向了\u003cstrong\u003e具备自主决策、工具调用与多步执行能力的 Agent（智能体）系统\u003c/strong\u003e。\u003c/p\u003e\n\u003cp\u003e在这一演进过程中，一个逐渐清晰的共识是：\u003cstrong\u003eAgent 并不是“更强的大模型”，而是“以大模型为大脑，外部系统为四肢”的工程系统。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e记忆、规划、、行动执行，这些能力本质上并不来自模型本身，而是通过工程框架将模型与外部能力进行组织、编排与约束的结果。正是在这一背景下，围绕  Agent 的研究与工程实践迅速发展，催生了诸如 \u003cstrong\u003eReAct、Auto-GPT、LangGraph、MetaGPT\u003c/strong\u003e 等一系列方法与框架。\u003c/p\u003e\n\u003cp\u003e我们将聚焦于 \u003cstrong\u003eModelScope-Agent\u003c/strong\u003e 这一由阿里云魔搭社区推出的  框架，从\u003cstrong\u003e能力结构、运行机制、典型任务示例与工程实践角度\u003c/strong\u003e，系统解析如何基于该框架构建一个可扩展、可落地的 Agent 应用。\u003c/p\u003e\n\u003ch2 id=\"一为什么-agent-不等于\"\u003e一、为什么 Agent 不等于？\u003c/h2\u003e\n\u003cp\u003e在深入 -Agent 之前，有必要先澄清一个常见误区：\u003cstrong\u003eAgent ≠ 更大的模型 ≠ 多轮 Prompt。\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e从系统架构视角来看，一个可用的 Agent 至少包含以下几个核心组件：\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003e推理核心（LLM）\u003c/strong\u003e：负责理解用户意图、进行任务拆解、生成行动决策。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e工具系统（Tools / Plugins）\u003c/strong\u003e：提供模型无法直接完成的能力，如搜索、计算、生成图片、调用 API 等。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e执行与调度层（Executor / Orchestrator）\u003c/strong\u003e：将模型输出的“意图”转化为真实的函数调用或外部服务请求。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e记忆系统（Memory）\u003c/strong\u003e：保存历史对话、中间结果、长期偏好，用于后续决策参考。\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e规划与反思机制（Planning \u0026amp; Reflection）\u003c/strong\u003e：用于多步骤任务拆解、执行顺序安排，以及失败后的自我修正。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e从这个角度看，\u003cstrong\u003eAgent 是一个系统工程问题，而不是单一模型能力问题\u003c/strong\u003e。ModelScope-Agent 正是试图在工程层面，为这些能力提供一套可组合、可扩展的实现框架。\u003c/p\u003e\n\u003ch2 id=\"二modelscope-agent-框架概览\"\u003e二、ModelScope-Agent 框架概览\u003c/h2\u003e\n\u003cp\u003eModelScope-Agent 是魔搭社区推出的一个 \u003cstrong\u003e通用 Agent 开发框架\u003c/strong\u003e，其目标并非“封装一个黑盒 Agent”，而是提供：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e标准化的 Agent 抽象\u003c/li\u003e\n\u003cli\u003e灵活的工具接入机制\u003c/li\u003e\n\u003cli\u003e可插拔的记忆与规划模块\u003c/li\u003e\n\u003cli\u003e面向多模态任务的统一调用方式\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e从系统结构上看（如下图所示，老版本结构，仅供参考）：\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/681d8cabd9e34416ab89416cd4f2156b.png\"\u003e\u003c/p\u003e\n\u003cp\u003e利用ModelScope-Agent框架开发的Agent，除了可以提供文本创作之外，还能生成图片、视频、语音等内容。单个Agent具有角色扮演、LLM调用、工具使用、规划、记忆等能力。 技术上主要具有以下特点：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e简单的Agent实现流程：仅需指定角色描述、大模型名称、工具名列表，即可实现一个Agent应用，框架内部自动实现工具使用、规划、记忆等工作流的编排。\u003c/li\u003e\n\u003cli\u003e丰富的模型和工具：框架内置丰富的大模型接口，例如Dashscope和Modelscope模型接口，OpenAI模型接口等。内置丰富的工具，例如代码运行、天气查询、文生图、网页解析等，方便定制专属Agent。\u003c/li\u003e\n\u003cli\u003e统一的接口和高扩展性：框架具有清晰的工具、大模型注册机制，方便用户扩展能力更加丰富的Agent应用。\u003c/li\u003e\n\u003cli\u003e低耦合性：开发者可以方便地直接使用内置的工具、大模型、记忆等组件，而不需要绑定更上层的Agent。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"三modelscope-agent-的核心能力解析\"\u003e三、ModelScope-Agent 的核心能力解析\u003c/h2\u003e\n\u003ch3 id=\"一内容生成能力\"\u003e（一）内容生成能力\u003c/h3\u003e\n\u003cp\u003e与许多只聚焦文本任务的 Agent 框架不同，ModelScope-Agent 天然支持多模态工具接入，使 Agent 能够完成：\u003c/p\u003e","title":"基于 ModelScope-Agent 框架构建可落地的大模型 Agent 应用实践"},{"content":"做记忆模块搭建的相关研发工作，一开始认为agent的记忆就是维护上下文，应该和chatbot的对话管理差不多，但真的做一段时间之后，才发现和对话管理相比还是区别比较大的，而且记忆模块对agent的实现效果以及后期可扩展性有比较重要的影响。\nagent记忆与chatbot上下文的区别 我们拿agent记忆与上下文来作下比较，暂且不考虑长期记忆，就拿短期记忆来作对比，短期记忆(工作记忆)主要就是维护上下文，更官方一点的说法就是上下文工程，那chabot的对话管理不是也是在维护上下文吗？那两者有什么区别呢？\n目标 agent记忆和chatbot上下文的目标看上去是一致的:给LLM/agent添加合适的状态来做下一步的决策。但是从服务对象，组织形式和维护重点的扩展来看有比较大的区别。\n服务对象 虽然两者都算是人机交互，拿服务的对象都可以算作是人，但从现阶段的主要技术实现来看，服务对象还是存在差异的。\nchatbot的服务对象是人这个毋庸置疑，做图灵测试也是为了验证对面和你说话的那个AI，有没有可能骗过你，而从让你以为它是个人，chatbot展开的多轮对话也是围绕人的实际需求展开。\nagent虽然也存在与人的交互，agentic workflow中一般也会有人工输入的节点，但现阶段我们搭建agent的主要任务，更多时候是在自动完成一个复杂任务，因此服务对象可以认为是复杂任务。\n组织形式 从组织形式上来看，由于agent具备了行动能力，所以和chabot产生了组织形式的不同。\nchatbot主要的构成是一问一答的形式，包括我们调用大模型api一般也遵循这个结构，可以表示为{[q0,a0],[q1,a1],\u0026hellip;[qt,at]}。\nagent记忆的构成以最常见的react模式为例，主要是动作(tool)和动作结果(tool_result)的时序集合，可以表示为{a0,o0,a1,01,\u0026hellip;at,ot}。\n维护重点 对于记忆和上下文，很重要的一个功能是维护，但维护的侧重点也是有所不同的。\nchabot的上下文虽然也存在前后关联，不会每一轮都紧密联系，但会存在频繁的意图切换，如何理解意图并且实现有效的意图切换识别是上下文维护的重点。\n而agent记忆的每一个步骤都是按迭代规划进行的，缺失某个步骤或跳过某个步骤都可能会导致任务失败，因此它的维护重点是如何在有限的窗口中记录对下一步决策产生影响的所需关键信息。\n另外agent和chatbot还存在一个很大不同的点是的必要性。对于chatbot，长期记忆主要是记住个人信息和偏好用于个性化服务。而对于agent，长期记忆需要通过情景记忆来记住之前的迭代轨迹，这样不仅能通过检索的方式来获取与当前决策相关的上下文信息，还可以实现经验复用，在下一次遇到类似任务时，可以将之前的经验作为参考,马普所今年2月份发这篇论文时候就指出情景记忆是当前agent所缺少的[1]。\nagent短期记忆-业界技术分享 anthropic anthropic提到agent在长程任务上的三种管理上下文方式[2]包括:压缩,结构化笔记和采用子agent架构。\n压缩通过对上下文关键内容的提取，改写和无关内容删除实现上下文瘦身；\n结构化笔记是把关键信息以结构化形式存入笔记，让agent可以阅读到关键信息；\n子agent架构则是通过子agent维护自己的独立上下文再将关键结果返回主agent实现上下文解耦。\noepnai openai的短期记忆管理[3]则是围绕agent sdk来谈到管理短期记忆的两个主要方式:裁剪（trimming）和压缩（summarizing）。\n压缩和anthropic的compact是一样的，裁剪就是把旧的历史信息直接剪掉。\ntrimming的好处是实现比较简单，延时友好而且不会引入偏移信息（相比压缩），但缺点也显而易见，裁剪的内容可能包含当前决策需要的信息，所以一般适用于任务独立，上下文关联不大，低延迟要求场景。\nlangchain \u0026amp; manus langchain与最近的一次交流[4]提到manus的三种上下文管理方式:reduce ，offload context和isolate context。\nreduce context包括将工具执行结果进行压缩放在窗口内，而降完整结果保存在文件系统中，在上下文触发窗口限制时对整个轨迹进行整体压缩；\ncontext isolate类似于anthropic的sub agent方法，但细分为两种方式：对于简单任务main agent通过function call的方式将指令传递给子agent，子agent在自己的窗口执行任务；而对于复杂任务，子agent会和主agent共享上下文。\ncontext offloading和anthropic的结构化笔记虽然都是将内容存入文件，但处理思路不一样。manus的方式是将大多数操作卸载到沙盒层，在沙盒中通过bash工具就可以实现多样化的文件读写操作，这样就可以把工具执行结果保存到文件，在需要时通过bash的grep等查询命令进行访问。另外manus的这个设计相当于把大部分先验知识文件化，让agent按需通过读取文件内容获取先验来指导行动，anthropic的skill实现应该也是类似的思路。\nagent记忆-项目实践 初版记忆实现 在实际搭建agent时，工具模块，记忆模块，提示词模块是三个重要的基础模块。工具模块和提示词模块相对简单或者说比较成熟的方案，而记忆模块的搭建则有不同的设计思路和实现方式，但核心思路一致 - \u0026ldquo;给agent提供恰当的上下文\u0026rdquo;，但难就难在\u0026quot;恰当\u0026quot;，首先受限于LLM的上下文窗口，所以累计上下文就不能过长。\n另外上下文中堆积无关或者重复的内容不但会影响推理规划，也是不经济的。还有一个重要原因是上下文中的内容对于agent来说不是等权重的，对于当前决策而言，有的内容相对其它内容就会更重要，类似于需要一个attention机制来选择关键信息，那以什么形式来管理上下文获取更相信的信息加入就尤为关键了。\n在近期的一个agent项目实践中，实现记忆模块的初始版本，设定的原则是\u0026quot;状态是记忆的投影\u0026quot;，以记忆作为事实的唯一来源，同时要求不在agent中维护状态，把记忆事实作为状态来源，放入agent的上下文中让agent自己进行决策。思路看上去是没有问题，但实际测试后就发现想简单了。\n对于agent而言本身依赖的LLM是无状态的，所以agent也可以认为是无状态的，但是记忆的目的就是为了让agent具有状态。在初版的实现里，每一轮迭代都把obs写入工作记忆，同时读取当前轮之前的工作记忆中的结构化历史信息，把obs作为上下文唯一来源，直接注入到下一轮迭代的上下文，这样做是比较省事，但是一旦agent内部迭代出现问题，因为obs和工作记忆之间的这种耦合设计，很难追溯问题来源。\n第二版记忆重构优化 在发现第一版的问题后，开始进行第二版改进。第二版的改进主要是基于看到的相关的技术博客和论文，重新设计了记忆方案。首先记忆模块的目录设计应该把短期记忆和长期记忆做清晰分划分，维护当前agent迭代执行任务所需上下文的就是短期记忆(工作记忆)，而记录完整迭代过程的是长期记忆（情景记忆），产生对应产出的也是长期记忆(语义记忆)。其中比较容易混淆的是工作记忆和情景记忆，从持久化的角度来说，把工作记忆持久化就可以理解为情景记忆，但实际上是存在差别的。\n对于一个agent的迭代轨迹{a0,o0,a1,o1,\u0026hellip;at,ot},可以直接把这个迭代轨迹放入上下文，也可以对这个迭代轨迹的每一步进行摘要提取，仅保留关键信息和引用，比如某步生成了一个很大的结构化，在进入下一轮时没有必要把整个json全部放入上下文，可以只放入一个引用，但是会把完整的json存入情景记忆，在下一轮迭代使用这个引用时再从情景记忆中取出这个对应的json，这样能避免大段内容直接进入到上下文中。\n同时还需要考虑到上下文长度限制和成本问题，一般的工作记忆还会考虑使用最近k轮的策略，上下文只保留最近k轮的迭代记录，但是全局信息以结构化的信息记录，把这个结构化信息也注入到上下文中，这样也不至于让agent丢失掉全局信息。而第一版的问题就在这里，状态不应该只是记忆的投影，状态是对记忆的删减和加工，实际上的改进就是在短期记忆和长期记忆之间加一个桥接适配层，来实现短期记忆和长期记忆的搭配使用。\n而为了agent项目的阶段性扩展和迭代，在前期工程化实现时就应该考虑长期记忆。在一个agent的迭代循环里，如果迭代轮数比较长，上下文窗口和LLM的上下文利用效率已经开始明显下降，就需要考虑结合长期记忆使用了。而为了缩减上下文，在删减掉比较早期的迭代信息后，需要识别出长期记忆中已保存的迭代记录中，哪些记忆内容会对当前轮决策有用，就选择加入到上下文。这个一般会使用retrival的方法，从长期记忆中进行检索。技术实现上会结合结构化和向量检索，而实际的实践需要根据场景需求去做设计和调整记忆存储和读写方式，可以使用slot，sql数据库，向量数据库，图数据库等等。\n实践过程汇总有一个原则可以参考：记忆模块在开始实现之初，就应该把短期记忆和长期记忆进行解耦设计，这不但为上下文管理留有比较大的优化空间，在符合可审计性原则之外还为经验复用和未来可能的RL积累数据基础。\n同时第二版的改进上，还有一个比较重要的改进点是还原了obs的单纯职责，obs只应该对当前轮的act和执行结果进行记录，不应该注入历史内容，obs保持职责单一只把当前轮的执行和执行结果(或摘要)放到工作记忆，工作记忆再去通过记忆模块补充历史上下文，这样修改之后，obs和工作记忆的职责也分的比较清晰了。\n另外在agent的工层化实现过程中，造成可审计比较困难的一个点就是对工程化实现过程的不同组件的职责理解和划分不清晰，一旦出了bug，bug溯因就会因为这种不清晰的边界设计增加debug的难度，所以需要在设计之初就厘清不同模块的边界再动手进行实现。\nagent记忆相关研究进展 上面提到RL微调，就再展开谈一下在agent在记忆管理方向的相关研究。agent记忆管理是一个很复杂的问题，从工程角度来看，agent的记忆管理可以分为两类技术方案，一种将复杂问题简化，另外一种是自动化。目前相关的记忆研究在这两个方向论文也比较多，找到了几篇比较有代表性的论文。前者是提供系统化/可插拔的记忆管理底座框架，如[5]，A-MEM[6]，后者是将手动/规则维护记忆的方式转为自动化，如Memory‑R1[7]，MEM1[8]，Memp[9]， MEMSearcher[10]等。\n系统化框架方向 1. Mem0 Mem0的核心目标是提供一个生产级的记忆管理框架,能够动态地从对话中提取、整合和检索关键信息。\nMem0支持多层次的记忆管理,包括用户级、会话级和Agent级三个层面。系统会通过LLM自动从对话中提取记忆,并智能处理记忆冲突。特别是它基于grapg存储的图增强版本Mem0ᵍ,将记忆组织为知识图谱,以实体-关系三元组的形式存储,这让系统能够捕捉更复杂的多跳关系。从工程角度看,Mem0已经构建的比较成熟,提供了API服务,并集成了LangChain、CrewAI等主流agent框架。\n在LOCOMO基准测试上,Mem0相比OpenAI Memory的准确率提升了26%,相比将全部上下文都送入模型的做法,P95延迟降低了91%,token使用量减少了90%。Mem0在保持高准确率的同时,显著提升了效率。Mem0目前在很多agent项目中也是使用比较多的。\n2. A-MEM A-MEM的设计灵感来自Zettelkasten[11]笔记法,是一种通过原子化笔记和灵活链接来构建知识网络的方法论。\nA-MEM将每条记忆组织成包含多个属性的\u0026quot;原子笔记\u0026quot;,包括上下文描述、关键词、标签等结构化信息。当新记忆加入时,系统会自动分析它与历史记忆之间的关联,建立有意义的连接。比较有意思的是A-MEM的记忆演化机制:新记忆的加入可能触发对旧记忆的更新,让整个记忆网络持续精炼自己的理解。这种设计让记忆系统不依赖预定义的固定操作,而是能灵活适应不同类型的任务。\n在性能上,A-MEM在多跳推理任务中表现突出,效果是基线方法的两倍以上。同时它的记忆使用效率很高,通常只需要1200到2500个tokens,低于作比较的MemGPT需要的16900 个tokens。\n自动学习方向 3. Memory-R1 Memory-R1算是第一个真正用强化学习训练agent主动管理外部记忆的框架,论文发表于2025年。它的核心思路是把记忆管理归类为一个决策问题,应该通过任务最终结果的奖励信号来学习,而不是依赖人工设计的规则。\n系统包含两个专门的agent。Memory Manager负责学习执行结构化的记忆操作,包括添加、更新、删除或保持不变。Answer Agent则实现了一个\u0026quot;记忆蒸馏\u0026quot;策略,从检索到的大量记忆中筛选出最相关的部分用于回答。这两个agent都通过PPO和GRPO算法进行outcome-driven的强化学习训练。\nMemory-R1的数据效率很高,仅用152个问答对就能达到最优性能,因为它直接优化任务结果,不需要为每个记忆操作标注正确答案。论文中举了个生动的例子:用户先说\u0026quot;我养了只狗叫Buddy\u0026quot;,后来又说\u0026quot;我又养了只狗叫Scout\u0026quot;。普通系统会误判这是矛盾,执行删除再添加,导致第一条记忆丢失。而训练过的Memory-R1会执行更新操作,将两条信息整合为\u0026quot;养了两只狗,Buddy和Scout\u0026quot;。在LOCOMO基准上,Memory-R1的F1分数达到24.91,并且在LLaMA-3.1和Qwen-2.5等不同模型上都展现出良好的泛化能力。\n4.MEM1 这项工作提出了一个比较独特的视角:将记忆整合与推理统一起来,让agent在推理过程中自然地完成记忆管理。\nMEM1的一个创新点是把推理本身视为\u0026quot;工作记忆\u0026quot;。在与环境交互的过程中,agent的推理链会提取关键信息,构建对问题的演进理解。使用XML风格的标签来显式标注不同组件:用表示内部推理状态,表示向环境的查询,表示agent的回答,表示外部观察结果。通过迭代的状态更新,MEM1只保留最新的完整状态集合,旧的工具输出则可以丢弃(anthropic也有类似的上下文维护策略),有效减轻上下文增长压力。\n在训练时,MEM1使用多目标任务,相比担任训练，多任务训练需要更多轮次的交互才能实现收敛,从而迫使模型学会高效的记忆管理。实验结果显示,MEM1的token消耗比较稳定,不会随着任务复杂度增长而快速增长,推理速度也更快。这让它特别适合长期web导航、多跳问答等需要持续环境交互的场景。\n5. Memp Memp探索的是程序性记忆(procedural memory)在agent中的作用。程序性记忆在人类认知中指的是\u0026quot;如何做\u0026quot;的知识,比如骑自行车、打字等通过练习变得自动化的技能。\nMemp设计了一个三阶段的循环机制。首先是构建阶段,系统从agent过去的行为轨迹中提炼记忆,既可以存储为细粒度的逐步操作指令,也可以抽象为高层次的脚本式表示。然后是检索阶段,当面对新任务时,agent会搜索记忆库找出最相关的过去经验作为起点,这比随机尝试要高效得多。最后再是更新阶段,agent可以反思失败案例,(www.tvmkv.com)修正和修订原始记忆。\nMemp的更新策略很灵活,可以简单地添加新经验,也可以只保留成功案例,还可以反思失败进行修正。通过持续的更新、纠错和淘汰过时内容,记忆库会随着经验的积累而演化。另外Memp还发现记忆可以跨模型迁移:用GPT-4o生成的程序性记忆可以直接给Qwen2.5使用,显著提升小模型的性能，这对降低部署成本有一些启发意义。在TravelPlanner和ALFWorld任务上,随着记忆库的精炼,agent的成功率稳步提升,效率也明显优化。\n6.MemSearcher 这是最近一周国科大联合小红书刚发表的新工作，专门针对搜索agent的记忆管理问题，实现了agent推理，工具调用和记忆管理的联合优化。\n现阶段的搜索agent面临一个两难困境:如果把完整的交互历史都拼接到上下文中,虽然保持了信息完整性,但会产生又长又嘈杂的上下文,导致计算和内存成本飙升;如果只使用当前轮次的信息,虽然避免了开销,但丢失了关键的历史信息。这种权衡限制了搜索agent的可扩展性。这个问题前文也提到过，说明工业实践和学术研究都在研究解决这个问题。\nMemSearcher提出了一个比较有意思的解决方案:在多轮交互过程中迭代维护一个紧凑的记忆,并在每轮将它与当前问题结合。具体工作流程是,每一轮MemSearcher首先将用户问题与记忆融合,生成推理轨迹并执行搜索动作,然后根据新的观察结果更新记忆,只保留对解决任务至关重要的信息。这种设计让上下文长度在多轮交互中保持稳定,在不牺牲准确性的前提下提升了效率。\n为了优化这个工作流,研究者引入了multi-context GRPO,这是一个端到端的强化学习框架,能够联合优化MemSearcher的推理能力、搜索策略和记忆管理。Multi-context GRPO会在不同上下文下采样多组轨迹,并在所有对话中传播轨迹级别的优势信号。\n在性能表现上,MemSearcher使用与Search-R1相同的训练数据,在7个公开基准测试上取得了显著提升:基于Qwen2.5-3B的版本平均相对增益11%,基于Qwen2.5-7B的版本增益12%。还有一点值得注意,3B参数的MemSearcher甚至超过了7B参数的基线模型,这说明在信息完整性和效率之间找到了一个合适的平衡点,能够同时带来更高的准确率和更低的计算开销。\n结语 通过一段时间的项目实践和agent学术研究的学习，可以明显的感受agent已经成为构建数字生产力的重要技术路径，它的主要突破在于，本身贴合强化学习理念的\u0026quot;行动-反馈\u0026quot;机制与大模型的推理能力的配合使用，实现了“1+1\u0026gt;\u0026gt;2”的组合效应。在LLM持续推高推理能力，工具连接逐步完善的同时，agent还比较缺失的两个环节，一个是现实世界的应用，这需要依赖世界模型和具身智能的突破，另外一个就是记忆，人类的记忆是非常精妙的设计，回忆遗忘都是如此的自然，但是要实现这样高效、健壮的记忆，还有很长一段路要走，这不但是追求更高智能的基础需求，也是让agent在更广泛，更复杂任务场景发挥价值所必须的。\n原文链接: Agent记忆技术及落地实践 作者: sosoba\n","permalink":"http://nb404.cn/posts/agent%E8%AE%B0%E5%BF%86%E6%8A%80%E6%9C%AF%E5%8F%8A%E8%90%BD%E5%9C%B0%E5%AE%9E%E8%B7%B5/","summary":"\u003cp\u003e做记忆模块搭建的相关研发工作，一开始认为agent的记忆就是维护上下文，应该和chatbot的对话管理差不多，但真的做一段时间之后，才发现和对话管理相比还是区别比较大的，而且记忆模块对agent的实现效果以及后期可扩展性有比较重要的影响。\u003c/p\u003e\n\u003ch5 id=\"agent记忆与chatbot上下文的区别\"\u003e\u003cstrong\u003eagent记忆与chatbot上下文的区别\u003c/strong\u003e\u003c/h5\u003e\n\u003cp\u003e我们拿agent记忆与上下文来作下比较，暂且不考虑长期记忆，就拿短期记忆来作对比，短期记忆(工作记忆)主要就是维护上下文，更官方一点的说法就是上下文工程，那chabot的对话管理不是也是在维护上下文吗？那两者有什么区别呢？\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/01bacdcac1138f90c7e861fd3b0907a8.png\"\u003e\u003c/p\u003e\n\u003ch6 id=\"目标\"\u003e\u003cstrong\u003e目标\u003c/strong\u003e\u003c/h6\u003e\n\u003cp\u003eagent记忆和chatbot上下文的目标看上去是一致的:给LLM/agent添加合适的状态来做下一步的决策。但是从服务对象，组织形式和维护重点的扩展来看有比较大的区别。\u003c/p\u003e\n\u003ch6 id=\"服务对象\"\u003e\u003cstrong\u003e服务对象\u003c/strong\u003e\u003c/h6\u003e\n\u003cp\u003e虽然两者都算是人机交互，拿服务的对象都可以算作是人，但从现阶段的主要技术实现来看，服务对象还是存在差异的。\u003c/p\u003e\n\u003cp\u003echatbot的服务对象是人这个毋庸置疑，做图灵测试也是为了验证对面和你说话的那个AI，有没有可能骗过你，而从让你以为它是个人，chatbot展开的多轮对话也是围绕人的实际需求展开。\u003c/p\u003e\n\u003cp\u003eagent虽然也存在与人的交互，agentic workflow中一般也会有人工输入的节点，但现阶段我们搭建agent的主要任务，更多时候是在自动完成一个复杂任务，因此服务对象可以认为是复杂任务。\u003c/p\u003e\n\u003ch6 id=\"组织形式\"\u003e\u003cstrong\u003e组织形式\u003c/strong\u003e\u003c/h6\u003e\n\u003cp\u003e从组织形式上来看，由于agent具备了行动能力，所以和chabot产生了组织形式的不同。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/953d252c69328a99749f85bca9eb64ed.png\"\u003e\u003c/p\u003e\n\u003cp\u003echatbot主要的构成是一问一答的形式，包括我们调用大模型api一般也遵循这个结构，可以表示为{[q0,a0],[q1,a1],\u0026hellip;[qt,at]}。\u003c/p\u003e\n\u003cp\u003eagent记忆的构成以最常见的react模式为例，主要是动作(tool)和动作结果(tool_result)的时序集合，可以表示为{a0,o0,a1,01,\u0026hellip;at,ot}。\u003c/p\u003e\n\u003ch6 id=\"维护重点\"\u003e\u003cstrong\u003e维护重点\u003c/strong\u003e\u003c/h6\u003e\n\u003cp\u003e对于记忆和上下文，很重要的一个功能是维护，但维护的侧重点也是有所不同的。\u003c/p\u003e\n\u003cp\u003echabot的上下文虽然也存在前后关联，不会每一轮都紧密联系，但会存在频繁的意图切换，如何理解意图并且实现有效的意图切换识别是上下文维护的重点。\u003c/p\u003e\n\u003cp\u003e而agent记忆的每一个步骤都是按迭代规划进行的，缺失某个步骤或跳过某个步骤都可能会导致任务失败，因此它的维护重点是如何在有限的窗口中记录对下一步决策产生影响的所需关键信息。\u003c/p\u003e\n\u003cp\u003e另外agent和chatbot还存在一个很大不同的点是的必要性。对于chatbot，长期记忆主要是记住个人信息和偏好用于个性化服务。而对于agent，长期记忆需要通过情景记忆来记住之前的迭代轨迹，这样不仅能通过检索的方式来获取与当前决策相关的上下文信息，还可以实现经验复用，在下一次遇到类似任务时，可以将之前的经验作为参考,马普所今年2月份发这篇论文时候就指出情景记忆是当前agent所缺少的[1]。\u003c/p\u003e\n\u003ch4 id=\"agent短期记忆-业界技术分享\"\u003e\u003cstrong\u003eagent短期记忆-业界技术分享\u003c/strong\u003e\u003c/h4\u003e\n\u003ch5 id=\"anthropic\"\u003e\u003cstrong\u003eanthropic\u003c/strong\u003e\u003c/h5\u003e\n\u003cp\u003eanthropic提到agent在长程任务上的三种管理上下文方式[2]包括:压缩,结构化笔记和采用子agent架构。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/387d2755dd654931c7687697dd44f614.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e压缩\u003c/strong\u003e通过对上下文关键内容的提取，改写和无关内容删除实现上下文瘦身；\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e结构化笔记\u003c/strong\u003e是把关键信息以结构化形式存入笔记，让agent可以阅读到关键信息；\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e子agent架构\u003c/strong\u003e则是通过子agent维护自己的独立上下文再将关键结果返回主agent实现上下文解耦。\u003c/p\u003e\n\u003ch5 id=\"oepnai\"\u003e\u003cstrong\u003eoepnai\u003c/strong\u003e\u003c/h5\u003e\n\u003cp\u003eopenai的短期记忆管理[3]则是围绕agent sdk来谈到管理短期记忆的两个主要方式:裁剪（trimming）和压缩（summarizing）。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e压缩\u003c/strong\u003e和anthropic的compact是一样的，裁剪就是把旧的历史信息直接剪掉。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003etrimming\u003c/strong\u003e的好处是实现比较简单，延时友好而且不会引入偏移信息（相比压缩），但缺点也显而易见，裁剪的内容可能包含当前决策需要的信息，所以一般适用于任务独立，上下文关联不大，低延迟要求场景。\u003c/p\u003e\n\u003ch5 id=\"langchain--manus\"\u003e\u003cstrong\u003elangchain \u0026amp; manus\u003c/strong\u003e\u003c/h5\u003e\n\u003cp\u003elangchain与最近的一次交流[4]提到manus的三种上下文管理方式:reduce ，offload context和isolate context。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/0a91b18e5dcebee1f435e386854e5c9a.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003ereduce context\u003c/strong\u003e包括将工具执行结果进行压缩放在窗口内，而降完整结果保存在文件系统中，在上下文触发窗口限制时对整个轨迹进行整体压缩；\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003econtext isolate\u003c/strong\u003e类似于anthropic的sub agent方法，但细分为两种方式：对于简单任务main agent通过function call的方式将指令传递给子agent，子agent在自己的窗口执行任务；而对于复杂任务，子agent会和主agent共享上下文。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003econtext offloading\u003c/strong\u003e和anthropic的结构化笔记虽然都是将内容存入文件，但处理思路不一样。manus的方式是将大多数操作卸载到沙盒层，在沙盒中通过bash工具就可以实现多样化的文件读写操作，这样就可以把工具执行结果保存到文件，在需要时通过bash的grep等查询命令进行访问。另外manus的这个设计相当于把大部分先验知识文件化，让agent按需通过读取文件内容获取先验来指导行动，anthropic的skill实现应该也是类似的思路。\u003c/p\u003e\n\u003ch5 id=\"agent记忆-项目实践\"\u003e\u003cstrong\u003eagent记忆-项目实践\u003c/strong\u003e\u003c/h5\u003e\n\u003ch6 id=\"初版记忆实现\"\u003e\u003cstrong\u003e初版记忆实现\u003c/strong\u003e\u003c/h6\u003e\n\u003cp\u003e在实际搭建agent时，工具模块，记忆模块，提示词模块是三个重要的基础模块。工具模块和提示词模块相对简单或者说比较成熟的方案，而记忆模块的搭建则有不同的设计思路和实现方式，但核心思路一致 - \u0026ldquo;给agent提供恰当的上下文\u0026rdquo;，但难就难在\u0026quot;恰当\u0026quot;，首先受限于LLM的上下文窗口，所以累计上下文就不能过长。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/bb300e7d10121e49b8504ca07022230d.png\"\u003e\u003c/p\u003e\n\u003cp\u003e另外上下文中堆积无关或者重复的内容不但会影响推理规划，也是不经济的。还有一个重要原因是上下文中的内容对于agent来说不是等权重的，对于当前决策而言，有的内容相对其它内容就会更重要，类似于需要一个attention机制来选择关键信息，那以什么形式来管理上下文获取更相信的信息加入就尤为关键了。\u003c/p\u003e\n\u003cp\u003e在近期的一个agent项目实践中，实现记忆模块的初始版本，设定的原则是\u0026quot;状态是记忆的投影\u0026quot;，以记忆作为事实的唯一来源，同时要求不在agent中维护状态，把记忆事实作为状态来源，放入agent的上下文中让agent自己进行决策。思路看上去是没有问题，但实际测试后就发现想简单了。\u003c/p\u003e\n\u003cp\u003e对于agent而言本身依赖的LLM是无状态的，所以agent也可以认为是无状态的，但是记忆的目的就是为了让agent具有状态。在初版的实现里，每一轮迭代都把obs写入工作记忆，同时读取当前轮之前的工作记忆中的结构化历史信息，把obs作为上下文唯一来源，直接注入到下一轮迭代的上下文，这样做是比较省事，但是一旦agent内部迭代出现问题，因为obs和工作记忆之间的这种耦合设计，很难追溯问题来源。\u003c/p\u003e\n\u003ch6 id=\"第二版记忆重构优化\"\u003e\u003cstrong\u003e第二版记忆重构优化\u003c/strong\u003e\u003c/h6\u003e\n\u003cp\u003e在发现第一版的问题后，开始进行第二版改进。第二版的改进主要是基于看到的相关的技术博客和论文，重新设计了记忆方案。首先记忆模块的目录设计应该把短期记忆和长期记忆做清晰分划分，维护当前agent迭代执行任务所需上下文的就是短期记忆(工作记忆)，而记录完整迭代过程的是长期记忆（情景记忆），产生对应产出的也是长期记忆(语义记忆)。其中比较容易混淆的是工作记忆和情景记忆，从持久化的角度来说，把工作记忆持久化就可以理解为情景记忆，但实际上是存在差别的。\u003c/p\u003e\n\u003cp\u003e对于一个agent的迭代轨迹{a0,o0,a1,o1,\u0026hellip;at,ot},可以直接把这个迭代轨迹放入上下文，也可以对这个迭代轨迹的每一步进行摘要提取，仅保留关键信息和引用，比如某步生成了一个很大的结构化，在进入下一轮时没有必要把整个json全部放入上下文，可以只放入一个引用，但是会把完整的json存入情景记忆，在下一轮迭代使用这个引用时再从情景记忆中取出这个对应的json，这样能避免大段内容直接进入到上下文中。\u003c/p\u003e\n\u003cp\u003e同时还需要考虑到上下文长度限制和成本问题，一般的工作记忆还会考虑使用最近k轮的策略，上下文只保留最近k轮的迭代记录，但是全局信息以结构化的信息记录，把这个结构化信息也注入到上下文中，这样也不至于让agent丢失掉全局信息。而第一版的问题就在这里，状态不应该只是记忆的投影，状态是对记忆的删减和加工，实际上的改进就是在短期记忆和长期记忆之间加一个桥接适配层，来实现短期记忆和长期记忆的搭配使用。\u003c/p\u003e\n\u003cp\u003e而为了agent项目的阶段性扩展和迭代，在前期工程化实现时就应该考虑长期记忆。在一个agent的迭代循环里，如果迭代轮数比较长，上下文窗口和LLM的上下文利用效率已经开始明显下降，就需要考虑结合长期记忆使用了。而为了缩减上下文，在删减掉比较早期的迭代信息后，需要识别出长期记忆中已保存的迭代记录中，哪些记忆内容会对当前轮决策有用，就选择加入到上下文。这个一般会使用retrival的方法，从长期记忆中进行检索。技术实现上会结合结构化和向量检索，而实际的实践需要根据场景需求去做设计和调整记忆存储和读写方式，可以使用slot，sql数据库，向量数据库，图数据库等等。\u003c/p\u003e\n\u003cp\u003e实践过程汇总有一个原则可以参考：记忆模块在开始实现之初，就应该把短期记忆和长期记忆进行解耦设计，这不但为上下文管理留有比较大的优化空间，在符合可审计性原则之外还为经验复用和未来可能的RL积累数据基础。\u003c/p\u003e\n\u003cp\u003e同时第二版的改进上，还有一个比较重要的改进点是还原了obs的单纯职责，obs只应该对当前轮的act和执行结果进行记录，不应该注入历史内容，obs保持职责单一只把当前轮的执行和执行结果(或摘要)放到工作记忆，工作记忆再去通过记忆模块补充历史上下文，这样修改之后，obs和工作记忆的职责也分的比较清晰了。\u003c/p\u003e\n\u003cp\u003e另外在agent的工层化实现过程中，造成可审计比较困难的一个点就是对工程化实现过程的不同组件的职责理解和划分不清晰，一旦出了bug，bug溯因就会因为这种不清晰的边界设计增加debug的难度，所以需要在设计之初就厘清不同模块的边界再动手进行实现。\u003c/p\u003e\n\u003ch5 id=\"agent记忆相关研究进展\"\u003e\u003cstrong\u003eagent记忆相关研究进展\u003c/strong\u003e\u003c/h5\u003e\n\u003cp\u003e上面提到RL微调，就再展开谈一下在agent在记忆管理方向的相关研究。agent记忆管理是一个很复杂的问题，从工程角度来看，agent的记忆管理可以分为两类技术方案，一种将复杂问题简化，另外一种是自动化。目前相关的记忆研究在这两个方向论文也比较多，找到了几篇比较有代表性的论文。前者是提供系统化/可插拔的记忆管理底座框架，如[5]，A-MEM[6]，后者是将手动/规则维护记忆的方式转为自动化，如Memory‑R1[7]，MEM1[8]，Memp[9]， MEMSearcher[10]等。\u003c/p\u003e","title":"Agent记忆技术及落地实践"},{"content":"(一) 测试工具（服务器） /etc/systemd/system/natapp.service\n编号 名称 版本 用途 工具状态 1 Unixbench 5.1.3 测试操作系统综合处理能力。 开源工具 2 Spec2006 2006 测试 CPU 性能。 商用软件 3 iozone 4.3.0 测试磁盘读写性能（Mb/s），包括随机、顺序读写、最大最小和平均读写速度等。 开源工具 4 Netperf 2.7.0 测试网络传输速率、网络吞吐率、网络响应时间等，包括 TCP、UDP 流吞吐速率、TCP 请求/响应、丢包率、误包率等。 开源工具 5 SPECjvm2008 2008 测试 JAVA 虚拟机的性能。 开源工具 6 LMbench 3.0 测试操作系统性能 开源工具 7 LTP LTP 20160510 测试系统稳定性 开源工具 8 Stream 5.09 测试内存带宽性能 开源工具 9 FIO 2.1.10 测试磁盘读写性能 开源工具 (2) uos deb http://mirrors.163.com/debian stable main 内核更新： apt install linux-image* linux-header* 卸载多余内核： apt remove linux-image-5.6.0-2-arm64 deb https://uos.deepin.cn/uos eagle main contrib non-free deb https://enterprise-packages.chinauos.com/server-enterprise fou/sp2 main contrib non-free apt-key adv \u0026ndash;keyserver keyserver.ubuntu.com \u0026ndash;recv-keys deb https://professional-store-packages.chinauos.com/appstore eagle appstore 麒麟v10源： deb http://archive.kylinos.cn/kylin/KYLIN-ALL 10.0 main restricted universe multiverse deb http://archive.kylinos.cn/kylin/partner juniper main 定制版uos： mkdir /tmp/livecd mount -o loop uos*.iso /tmp/livecd mkdir -p livecd/cd rsync --exclude=/live/filesystem.squashfs -a /tmp/livecd/ livecd/cd mkdir livecd/squashfs\u0026amp;\u0026amp;mkdir livecd/custom modprobe squashfs mount -t squashfs -o loop /tmp/livecd/live/filesystem.squashfs livecd/squashfs cp -a livecd/squashfs/* livecd/custom cp /etc/resolv.conf livecd/custom/etc/ cp /etc/apt/sources.list livecd/custom/etc/apt/sources.list chroot livecd/custom apt install xrdp htop gnome-disk* rm -rf livecd/custom/recovery* mksquashfs livecd/custom ./filesystem.squashfs \u0026amp;\u0026amp; chmod -R 777 ./*.squashfs uos无需激活即可root： nano /etc/pam.d/su #auth requisite deepin_security_verify.so 命令行激活试用：uos uos-activator-cmd -t 1 (3) unixbench wget http://github.itzmx.com/1265578519/unixbench/master/5.1.3/unixbench.sh chmod 777 *.sh \u0026amp;\u0026amp; ./unixbench.sh 多核的话改一下run文件，第 109,110,111,112 行修改数字为当前系统 CPU 核数，然后./Run -c 核数 nano Makefile ，47行 1GL_LIBS = -lGL -lXext -lX11 lm nano Run，111行 # \u0026#39;3d\u0026#39; =\u0026gt; { \u0026#39;name\u0026#39; =\u0026gt; \u0026#34;3D Graphics Benchmarks\u0026#34;,\u0026#39;maxCopies\u0026#39; =\u0026gt; 8 }, make all \u0026amp;\u0026amp; ./Run graphics 1 (4) iozone wget http://www.iozone.org/src/current/iozone3_487.tar tar -xvf iozone3_487.tar cd iozone3_487/src/current/ make linux ./iozone -a -i 0 -i 1 -i 2 -f /mnt/testfile -r 16m -s 8G | tee -a iozone.log ./iozone -a -i 0 -i 1 -i 2 -f /mnt/testfile -r 16m -s 16G | tee -a iozone.log ./iozone -a -i 0 -i 1 -i 2 -f /mnt/testfile -r 16m -s 32G | tee -a iozone.log wgethttps://gitee.com/haolixu/test/raw/master/iozone.sh\u0026amp;\u0026amp; bash iozone.sh (5) 远程桌面 apt install xrdp apt install gnome* echo “gnome-session \u0026ndash;session=gnome-classic” \u0026gt; ~/.xsession /etc/init.d/xrdp start 19.12.23更新！\napt install xdm*\n不用选xdm即可远程\n20.1.15更新！\napt install dde*\n可恢复deepin桌面！！\n(6) fio apt install fio* dd if=/dev/zero of=/root/test bs=4k count=524288 fio \u0026ndash;filename=/root/test -iodepth=64 -ioengine=libaio \u0026ndash;direct=1 \u0026ndash;rw=read \u0026ndash;bs=1m \u0026ndash;size=2g \u0026ndash;numjobs=4 \u0026ndash;runtime=10 \u0026ndash;group_reporting \u0026ndash;name=test-read fio -filename=/root/test -iodepth=64 -ioengine=libaio -direct=1 -rw=write -bs=1m -size=2g -numjobs=4 -runtime=20 -group_reporting -name=test-write fio -filename=/root/test -iodepth=64 -ioengine=libaio -direct=1 -rw=randread -bs=4k -size=2G -numjobs=64 -runtime=20 -group_reporting -name=test-rand-read fio -filename=/root/test -iodepth=64 -ioengine=libaio -direct=1 -rw=randwrite -bs=4k -size=2G -numjobs=64 -runtime=20 -group_reporting -name=test-rand-write wgethttps://gitee.com/haolixu/test/raw/master/fio.sh\u0026amp;\u0026amp; bash fio.sh (7) SPECjvm2008 wget http://spec.cs.miami.edu/downloads/osg/java/SPECjvm2008_1_01_setup.jar https://gitlab.com/haolixu/hello/-/raw/main/SPECjvm2008_1_01_setup.jar apt install openjdk-8-jre-headless update-alternatives \u0026ndash;config java nano /etc/profile JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-arm64/\nCLASSPATH=$JAVA_HOME/lib/tools.jar:/lib.dt.jar\nPATH=\nJ\rA\rV\rA\rH\rO\rM\rE\r/\rb\ri\rn\r:\rJAVA_HOME/bin:\rJAVAH​OME/bin:PATH\rexport JAVA_HOME CLASSPATH PATH\nsource /etc/profile java -jar SPECjvm2008_1_01_setup.jar -i console nano /etc/java-8-openjdk/accessibility.properties #assistive_technologies=org.GNOME.Accessibility.AtkWrapper\njava -jar SPECjvm2008.jar \u0026ndash;base java -jar SPECjvm2008.jar \u0026ndash;peak (8) LTP 麒麟v10 1231版本修改： nano ltp/testscripts/ltpstress.sh #250行 TOTALRAM=$(LC_ALL=C free -m | grep Mem: | awk {\u0026#39;print $2\u0026#39;}) TOTALSWAP=$(LC_ALL=C free -m | grep Swap: | awk {\u0026#39;print $2\u0026#39;}) TESTSWAP=$(($TOTALSWAP / 2)) if [ $TESTSWAP -eq 0 ]; then #if there is no swap in the system, use only the free RAM TESTMEM=$(LC_ALL=C free -m | grep Mem: | awk {\u0026#39;print $4\u0026#39;}) wget https://github.com/linux-test-project/ltp/releases/download/20190930/ltp-full-20190930.tar.bz2 cd ltp-full-20190930 apt install gcc g++ gfortran ./configure \u0026amp;\u0026amp; make \u0026amp;\u0026amp; make install ./ltpstress.sh –n –t 12 –l /root/ltpstress.log The NFS related tests should fail because network stress was disabled,去掉这个 bug： ./ltpstress.sh –n –t 12 (9) web性能 http://html5test.com http://CSS3test.com https://www.browserbench.org/JetStream/ https://webkit.org/perf/sunspider-1.0.2/sunspider-1.0.2/driver.html (10) stream mkdir stream \u0026amp;\u0026amp; cd stream wget https://www.nersc.gov/assets/Trinity–NERSC-8-RFP/Benchmarks/Jan9/stream.tar tar -xvf stream.tar gcc -O2 -DSTREAM_ARRAY_SIZE=1000000000 stream.c -o stream ./stream (11) Lmbench wget http://106.54.231.176/tar/lmbench.tar tar -xvf lmbench.tar \u0026amp;\u0026amp; cd lmbench cd lmbench3/src \u0026amp;\u0026amp; make cd …/scripts \u0026amp;\u0026amp; ./config-run ./results make see | tee -a lmbench.log (12) Netperf，iperf wget http://106.54.231.176/tar/netperf-2.7.0.tar tar -xvf netperf-2.7.0.tar \u0026amp;\u0026amp; cd netperf-netperf-2.7.0 ./configure \u0026amp;\u0026amp; make \u0026amp;\u0026amp; make install netserver netperf -H 192.168.4.11 -l 60 -t TCP_STREAM | tee -a netperf.log 测延迟： ./cepreiperf-ARM 192.168.124.13 tcp_lat ./cepreiperf-ARM 192.168.124.13 udp_lat (13) 图形稳定性测试 apt install mesa-utils (14) 宝德OS！！！ 安装文件管理器，图片查看器： apt-get install nautilus gpicview 网络连接图标异常： nano /etc/NetworkManager/NetworkManager.conf managed=true 更改grub壁纸和开机logo： apt install plymouth plymouth-themes cd /usr/share/desktop-base/futureprototype-theme/ cd /usr/share/plymouth/themes/futureprototype plymouth-set-default-theme -R futureprototype 更改桌面壁纸，对应用户执行： gsettings set org.gnome.desktop.background picture-uri \u0026#39;file:///baode/Flowerbed.png\u0026#39; 安装桌面： apt-get install gnome-shell gnome-panel gnome-menus gnome-session gdm3 apt-get install kde-plasma-desktop apt install x-window-system-core gnome-core apt install lightdm apt install sddm apt install cinnamon apt install lxde 更改登陆界面logo： nano /etc/gdm3/greeter.dconf-defaults [org/gnome/login-screen] logo=\u0026#39;/baode/logo.png\u0026#39; dpkg-reconfigure gdm3 添加自动登陆（只有gdm）： nano /etc/gdm3/daemon.conf AutomaticLogin = guest 安装其他终端： apt install xfce4-terminal 安装程序： apt install calamares-settings-debian 添加桌面图标： apt install nemo nano ~/.config/autostart/nemo.desktop [Desktop Entry] Type=Application Name=Desktop Icons Exec=nemo-desktop OnlyShowIn=GNOME; NoDisplay=true X-GNOME-Autostart-Phase=Desktop X-GNOME-Autostart-Notify=true X-GNOME-AutoRestart=true X-GNOME-Provides=filemanager gsettings set org.nemo.desktop show-desktop-icons true 如果执行不了，root下执行su -重新运行。 live cd： apt-get install -y \\ debootstrap \\ squashfs-tools \\ xorriso \\ grub-efi-arm64-bin \\ mtools debootstrap \\ --arch=arm64 \\ --variant=minbase \\ stable \\ /home/guest/LIVE_BOOT/chroot \\ http://mirrors.163.com/debian chroot /home/guest/LIVE_BOOT/chroot echo \u0026#34;baodeOS\u0026#34; \u0026gt;/etc/hostname apt-get install live-boot systemd-sysv sudo vim iputils-ping nano x-window-system-core gnome-core plymouth plymouth-themes linux-image-arm64 linux-headers-arm64 adduser user nano /etc/sudoers user ALL=(ALL) NOPASSWD:ALL nano /etc/lightdm/lightdm.conf autologin-user=user exit chroot mksquashfs LIVE_BOOT/chroot/ ./filesystem.squashfs \u0026amp;\u0026amp; chmod -R 777 ./*.squashfs mkdir -vp /home/guest/LIVE_BOOT/{scratch,image/live} mksquashfs \\ /home/guest/LIVE_BOOT/chroot \\ /home/guest/LIVE_BOOT/image/live/os.squashfs \\ -e boot cp -v /home/guest/LIVE_BOOT/chroot/boot/vmlinuz-* /home/guest/LIVE_BOOT/image/vmlinuz cp -v /home/guest/LIVE_BOOT/chroot/boot/initrd.img-* /home/guest/LIVE_BOOT/image/initrd nano /home/guest/LIVE_BOOT/image/DEBIAN_CUSTOM nano /home/guest/LIVE_BOOT/scratch/grub.cfg insmod all_video set default=\u0026#34;0\u0026#34; set timeout=\u0026#34;30\u0026#34; menuentry \u0026#34;baodeOS-installer\u0026#34;\u0026#34; { search --set=root --no-floppy --file /DEBIAN_CUSTOM linzux /vmlinuz boot=live quiet nomodeset initrd /initrd } grub-mkstandalone \\ --format=arm64-efi \\ --output=/home/guest/LIVE_BOOT/scratch/grubaa64.efi \\ --locales=\u0026#34;\u0026#34; \\ --fonts=\u0026#34;\u0026#34; \\ \u0026#34;boot/grub/grub.cfg=/home/guest/LIVE_BOOT/scratch/grub.cfg\u0026#34; cd /home/guest/LIVE_BOOT/scratch dd if=/dev/zero of=efiboot.img bs=1M count=10 mkfs.vfat efiboot.img mmd -i efiboot.img efi efi/boot mcopy -i efiboot.img ./grubaa64.efi ::efi/boot/ xorriso \\ -as mkisofs \\ -iso-level 3 \\ -full-iso9660-filenames \\ -volid \u0026#34;baodeOS_CUSTOM\u0026#34; \\ -eltorito-alt-boot \\ -e EFI/efiboot.img \\ -no-emul-boot \\ -append_partition 2 0xef /home/guest/LIVE_BOOT/scratch/efiboot.img \\ -output \u0026#34;/home/guest/baodeOS-installer.iso\u0026#34; \\ -graft-points \\ \u0026#34;/home/guest/LIVE_BOOT/image\u0026#34; \\ /EFI/efiboot.img=/home/guest/LIVE_BOOT/scratch/efiboot.img dd if=./baodeOS-installer.iso of=/dev/sdb bs=4M 一些有用的： https://bitbucket.org/chandrakantsingh/ https://www.linux.com/topic/distributions/aryalinux-distribution-and-platform/ https://www.linuxprobe.com/aryalinux-base-lfs.html https://blog.csdn.net/weixin_41217917/article/details/80757652?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-14\u0026amp;spm=1001.2101.3001.4242 http://wiki.linuxfromscratch.org/lfs https://github.com/marco-buratto/lamponepi.qemubox live-build： 自动配置脚本目录：auto/config 创建镜像时安装的软件所在目录：config/package-lists/ 自定义镜像内容目录：config/includes.chroot/ 创建系统后执行的脚本所在目录：config/hooks/ 自定义引导程序目录：config/bootloaders/ 重新打包ISO： xorriso -as mkisofs -r -checksum_algorithm_iso md5,sha1 -V \u0026#39;Ubuntu-Server 16.04.3 LTS arm64\u0026#39; \\ -o ./new-ubuntu-16.04.3-server-arm64.iso -J -joliet-long -cache-inodes -e boot/grub/efi.img \\ -no-emul-boot -append_partition 2 0xef ubuntu/boot/grub/efi.img -partition_cyl_align all ubuntu/ 1 1 (15) 常用 hostnamectl set-hostname 取消32位支持 dpkg \u0026ndash;remove-architecture i386\nfind / -name 还原系统后解决开机慢的问题 sed -ri ‘s/.swap./#\u0026amp;/’ /etc/fstab\nrm /etc/mdadm/mdadm.conf\nupdate-initramfs -u\nwin10下面打开powershell输入tar -czvf .\\jdk7.tar.gz ./jdk7-server-release-1708 查看温度，AMD显卡： apt-get install lm-sensors sensors-applet \u0026amp;\u0026amp; watch sensors apt install radeontop \u0026amp;\u0026amp; radeontop apt install hddtemp \u0026amp;\u0026amp; hddtemp SATA:/dev/sda 让nano显示行号： nano ~/.nanorc\nset linenumbers\n让root有颜色 PS1=\u0026quot;[\\u@\\h \\w]$ \u0026quot;\n让root可以命令行打开图形化： cp /home/guest/.Xauthority /root/ 命令行连WiFi： nmcli device wifi connect wifiname password wifipasswd 新系统安装： wget ://gitee.com/haolixu//raw/master/.vimrc \u0026amp;\u0026amp; mv -b .vimrc /root\nwget https://gitee.com/haolixu/test/raw/master/motd \u0026amp;\u0026amp; mv -b motd /etc\nwget https://gitee.com/haolixu/test/raw/master/.bashrc \u0026amp;\u0026amp; mv -b .bashrc /root\n谷歌搜索： https://go.readmorejoy.com/search/ 查看系统信息，硬盘速率： apt install inxi dmesg | grep SATA |head -n 1 修改密码安全等级（降低） apt-get install libpam-cracklib nano /etc/pam.d/common-password apt之后直接就可以设置了，nano可以提供安全等级 GitHub中国专用： github.com.cnpmjs.org hub.fastgit.org 程序后台执行：nohup sh test.sh \u0026amp; 建立文件夹软连接，强制覆盖： ln -sfn /var/lib/docker/ lixu666/ 设置默认启动界面： systemctl set-default multi-user.target #字符 systemctl set-default graphical.target #图形 查看开机启动的程序 systemctl list-unit-files | grep enable 1 (16) wine https://www.novaspirit.com/2019/04/15/run-x86-arm/\n2.6更新\napt-get install qemu qemu-user qemu-user-static binfmt-support debootstrap binutils\ndebootstrap \u0026ndash;foreign \u0026ndash;arch i386 stable ./chroot-stretch-i386 http://.163.com/debian\nmount -t sysfs sys ./chroot-stretch-i386/sys/\nmount -t proc proc ./chroot-stretch-i386/proc/\nmount \u0026ndash;bind /dev ./chroot-stretch-i386/dev/\nmount \u0026ndash;bind /dev/pts ./chroot-stretch-i386/dev/pts/\nmount \u0026ndash;bind /dev/shm ./chroot-stretch-i386/dev/shm/\ncp /usr/bin/qemu-i386-static ./chroot-stretch-i386/usr/bin/\nchroot ./chroot-stretch-i386/ /debootstrap/debootstrap \u0026ndash;second-stage\nchroot ./chroot-stretch-i386/ /bin/su -l root\nadduser -uid 1000 test\napt install leafpad ca-certificates dirmngr sudo bzip2 zenity curl\nchroot ./chroot-stretch-i386/ /bin/su -l root\ntar -jxf PlayOnLinux-wine-3.9-linux-x86.pol \u0026ndash;strip-components=1\nmv ./3.9/bin/wine-preloader ./3.9/bin/wine-preloader.renamed\nmv ./3.9 /opt/wine-3.9/\necho PATH=/opt/wine-3.9/bin/:$PATH \u0026gt;\u0026gt; ~/.bashrc\nsource ./.bashrc\nchroot /home/test/Desktop/chroot-stretch-i386/ /bin/su -l test\necho PATH=/opt/wine-3.9/bin/:$PATH \u0026gt;\u0026gt; ~/.bashrc\nsource ./.bashrc\nwinecfg\nwget http://security..com/ubuntu/pool/main/libp/libpng/libpng12-0_1.2.46-3ubuntu4.2_i386.deb\ndpkg -i libpng12-0_1.2.46-3ubuntu4.2_i386.deb\ngit clone https://gitee.com/AN_drew/-ubuntu.git\ncd deepin-wine-ubuntu \u0026amp;\u0026amp; ./install.sh\nwine必装：\nwget https://mirrors.ustc.edu.cn/deepin/pool/non-free/d/deepin-wine-plugin/deepin-wine-plugin_1.0deepin2_i386.deb\nwget https://mirrors.ustc.edu.cn/deepin/pool/non-free/d/deepin-wine-plugin-virtual/deepin-wine-plugin-virtual_1.0deepin3_all.deb\napt install -f\nwget https://mirrors.aliyun.com/deepin/pool/non-free/d/deepin-wine-helper/deepin-wine-helper_1.2deepin8_i386.deb\napt install -f\n微信：\nwget https://mirrors.ustc.edu.cn/deepin/pool/non-free/d/deepin.com.wechat/deepin.com.wechat_2.6.8.65deepin0_i386.deb\n2.12更新！\ndebootstrap \u0026ndash;foreign \u0026ndash;arch arm64 bionic ./arm64-ubuntu http://mirrors.aliyun.com/ubuntu-ports\ndeb [by-hash=force] http://packages.deepin.com/deepin lion main contrib non-free\n3.13.更新！\nwget https://qd.myapp.com/myapp/qqteam/pcqq/PCQQ2020.exe\n3.30更新！\nexport DISPLAY=:0\nexport DISPLAY=:1\n(17)虚拟化（ ，kvm） uos原生可安装docker，但是无法安装镜像，需更新内核到5.4。 docker安装图形化管理： apt install curl gnupg2 ca-certificates apt-transport-https software-properties-common\ncurl -sSL https://get.docker.com | sh\ndocker \u0026ndash;version\n#国内源参考big教程\ndocker pull /portainer\ndocker volume create portainer_data\ndocker run -d -p 9000:9000 \u0026ndash;name portainer \u0026ndash;restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer\n127.0.0.1:9000\ndocker安装ubuntu docker pull ubuntu\ndocker run -it -p 80:80 ubuntu /bin/bash\ndocker ps -a\ndocker start (CONTAINER ID）\ndocker attach (CONTAINER ID）\n安装kvm wget https://gitee.com/haolixu/test/raw/master/kvm.sh \u0026amp;\u0026amp; bash kvm.sh apt install virtinst python-libvirt virt-viewer virt-manager bridge-utils uml-utilities ovmf qemu-efi libvirt-daemon-system qemu qemu-system qemu-system-arm qemu-system-common qemu-user qemu-utils qemu-kvm #yum install kvm virt-manager libvirt libvirt-python python-virtinst libvirt-client qemu-kvm qemu-img modprobe kvm #加载kvm内核模块，vmare虚拟机需要开启虚拟化支持 systemctl status libvirtd virsh list --all #上两步验证是否安装成功 1 (18) 内网穿透（web服务器) http://download.natapp.cn/assets/downloads/clients/2_3_9/natapp_linux_arm64_2_3_9.zip unzip natapp_linux_arm64_2_3_9.zip chmod 777 natapp \u0026amp;\u0026amp;./natapp -authtoken=8582fece4a62980c wget https://gitee.com/haolixu/test/raw/master/natapp.sh \u0026amp;\u0026amp;./natapp -authtoken=8582fece4a62980c 检查有无公网IP： TRACERT.EXE baidu.com\nweb服务器设置： apt install apache2\niptables -I INPUT -p tcp \u0026ndash;dport 3389 -j ACCEPT\nnano /etc/apache2/ports.conf\nservice apache2 restart\nservice apache2 status\napt install php7.3 php-mbstring php-pdo php-curl php-mysql mariadb-server-10.3 php-gd php-zip php-xml*\nmysqladmin -u root -p password #这个有效\nnano /etc/mysql/mariadb.conf.d/50-server.cnf\n#bind-address = 127.0.0.1\nport = 3389\nmysql -u root -p\nGRANT ALL PRIVILEGES ON . TO ‘root’@‘%’ IDENTIFIED BY ‘密码’ WITH GRANT OPTION;\nFLUSH PRIVILEGES;\n#赋予root权限并立即生效\nservice mysql restart\nmysql -u root -p这里设置密码 -h 192.168.20.12 -P 3389\n远程连接：\nuse mysql\nupdate user set host=‘%’ where user =‘root’;\nFLUSH PRIVILEGES;\nALTER USER ‘root’@‘%’ IDENTIFIED WITH mysql_native_password BY ‘1’;\nFLUSH PRIVILEGES;\n1 (18) BMC 通过BMC命令行 ipmcset -t precisealarm -d -v 0x0D000009 1 assert\nipmcset -t precisealarm -d mock -v 0x0D000009 1 deassert\nipmcset -t precisealarm -d mock -v 0x0D000003 1 assert\nipmcset -t precisealarm -d mock -v 0x0D000003 1 deassert\n查看面板led指示灯及登录BMC web首页，查看“告警与事件-当前告警”。\n通过ipmitool命令行chassis power status查询单板业务平面的上下电状态，执行单板上电，下电，复位命令： ipmitool -H ... -I lanplus -U \u0026lt;用户名\u0026gt; -P \u0026lt;密码\u0026gt; chassis power on\nipmitool -H ... -I lanplus -U \u0026lt;用户名\u0026gt; -P \u0026lt;密码\u0026gt; chassis power off\nipmitool -H ... -I lanplus -U \u0026lt;用户名\u0026gt; -P \u0026lt;密码\u0026gt; chassis power reset\n查询系统当前功率及所有传感器的信息 ipmitool -I lanplus -H -U \u0026lt;BMC账号\u0026gt; -P \u0026lt;密码\u0026gt; raw 0x30 0x93 0xdb 0x07 0x00 0x11 0x00\nipmitool -I lanplus -L administrator -H -U \u0026lt;BMC账号\u0026gt; -P \u0026lt;密码\u0026gt; sensor\n打开KVM，勾选“本地文件夹”，点击浏览并确定，点击连接。 (19) 天翼网关，云盘 超级管理员账户 telecomadmin 密码 nE7jA%5m 查看WiFi： wpa_cli -iwlan0 status wpa_cli -iwlan0 scan wpa_cli -iwlan0 scan_results ifconfig wlan0 up dhclient wlan0 Linux使用云盘： wget https://raw.fastgit.org/haolixu/Temporary-image-backup/master/cloudpan189-go-v0.0.9-linux-arm64.zip unzip cloudpan189-go-v0.0.9-linux-arm64.zip cd cloudpan189-go-v0.0.9-linux-arm64/ \u0026amp;\u0026amp; ./cloudpan189-go login #登录 sign #签到 ls \u0026amp;\u0026amp; cd 来自家庭共享/ download gcc9.3.tar.gz #下载 upload /root/postgresq-lixu666.py ./ 1 (20) C++ string必须加头文件\u0026lt;string.h\u0026gt; 值传递形参不改变实参，地址传递会改变。如果不想修改主函数中的数据，用值传递。 用指针可以节约内存空间。 (21) Git 远程拉项目及上传更新项目： mkdir git-lixu666 \u0026amp;\u0026amp; cd git-lixu666 \u0026amp;\u0026amp; git init git config --global user.name \u0026#34;haolixu\u0026#34; git config --global user.email \u0026#34;1300311464@qq.com\u0026#34; git remote add origin https://gitee.com/haolixu/test.git git pull origin master git commit -m \u0026#34;lixu666\u0026#34; git push -u origin master 设置代理: git config http.proxy http://127.0.0.1:7890 只下载最新版本，不下载历史版本： git clone git仓库地址 --depth=1 1 原文链接: 服务器测试整理 作者: lixusocool\n","permalink":"http://nb404.cn/posts/%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%B5%8B%E8%AF%95%E6%95%B4%E7%90%86/","summary":"\u003ch3 id=\"一-测试工具服务器\"\u003e(一)   测试工具（服务器）\u003c/h3\u003e\n\u003cp\u003e/etc/systemd/system/natapp.service\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e编号\u003c/th\u003e\n          \u003cth\u003e名称\u003c/th\u003e\n          \u003cth\u003e版本\u003c/th\u003e\n          \u003cth\u003e用途\u003c/th\u003e\n          \u003cth\u003e工具状态\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e1\u003c/td\u003e\n          \u003ctd\u003eUnixbench\u003c/td\u003e\n          \u003ctd\u003e5.1.3\u003c/td\u003e\n          \u003ctd\u003e测试操作系统综合处理能力。\u003c/td\u003e\n          \u003ctd\u003e开源工具\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e2\u003c/td\u003e\n          \u003ctd\u003eSpec2006\u003c/td\u003e\n          \u003ctd\u003e2006\u003c/td\u003e\n          \u003ctd\u003e测试 CPU 性能。\u003c/td\u003e\n          \u003ctd\u003e商用软件\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e3\u003c/td\u003e\n          \u003ctd\u003eiozone\u003c/td\u003e\n          \u003ctd\u003e4.3.0\u003c/td\u003e\n          \u003ctd\u003e测试磁盘读写性能（Mb/s），包括随机、顺序读写、最大最小和平均读写速度等。\u003c/td\u003e\n          \u003ctd\u003e开源工具\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e4\u003c/td\u003e\n          \u003ctd\u003eNetperf\u003c/td\u003e\n          \u003ctd\u003e2.7.0\u003c/td\u003e\n          \u003ctd\u003e测试网络传输速率、网络吞吐率、网络响应时间等，包括 TCP、UDP 流吞吐速率、TCP 请求/响应、丢包率、误包率等。\u003c/td\u003e\n          \u003ctd\u003e开源工具\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e5\u003c/td\u003e\n          \u003ctd\u003eSPECjvm2008\u003c/td\u003e\n          \u003ctd\u003e2008\u003c/td\u003e\n          \u003ctd\u003e测试 JAVA 虚拟机的性能。\u003c/td\u003e\n          \u003ctd\u003e开源工具\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e6\u003c/td\u003e\n          \u003ctd\u003eLMbench\u003c/td\u003e\n          \u003ctd\u003e3.0\u003c/td\u003e\n          \u003ctd\u003e测试操作系统性能\u003c/td\u003e\n          \u003ctd\u003e开源工具\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e7\u003c/td\u003e\n          \u003ctd\u003eLTP\u003c/td\u003e\n          \u003ctd\u003eLTP 20160510\u003c/td\u003e\n          \u003ctd\u003e测试系统稳定性\u003c/td\u003e\n          \u003ctd\u003e开源工具\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e8\u003c/td\u003e\n          \u003ctd\u003eStream\u003c/td\u003e\n          \u003ctd\u003e5.09\u003c/td\u003e\n          \u003ctd\u003e测试内存带宽性能\u003c/td\u003e\n          \u003ctd\u003e开源工具\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e9\u003c/td\u003e\n          \u003ctd\u003eFIO\u003c/td\u003e\n          \u003ctd\u003e2.1.10\u003c/td\u003e\n          \u003ctd\u003e测试磁盘读写性能\u003c/td\u003e\n          \u003ctd\u003e开源工具\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch3 id=\"2-uos\"\u003e(2)   uos\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003edeb \u003ca href=\"http://mirrors.163.com/debian\"\u003ehttp://mirrors.163.com/debian\u003c/a\u003e stable main\u003c/li\u003e\n\u003cli\u003e内核更新：\u003c/li\u003e\n\u003cli\u003eapt install linux-image* linux-header*\u003c/li\u003e\n\u003cli\u003e卸载多余内核：\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-plain\" data-lang=\"plain\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt remove linux-image-5.6.0-2-arm64\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col\u003e\n\u003cli\u003edeb \u003ca href=\"https://uos.deepin.cn/uos\"\u003ehttps://uos.deepin.cn/uos\u003c/a\u003e eagle main contrib non-free\u003c/li\u003e\n\u003cli\u003edeb \u003ca href=\"https://enterprise-packages.chinauos.com/server-enterprise\"\u003ehttps://enterprise-packages.chinauos.com/server-enterprise\u003c/a\u003e fou/sp2 main contrib non-free\u003c/li\u003e\n\u003cli\u003eapt-key adv \u0026ndash;keyserver keyserver.ubuntu.com \u0026ndash;recv-keys\u003c/li\u003e\n\u003cli\u003edeb \u003ca href=\"https://professional-store-packages.chinauos.com/appstore\"\u003ehttps://professional-store-packages.chinauos.com/appstore\u003c/a\u003e eagle appstore\u003c/li\u003e\n\u003cli\u003e麒麟v10源：\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-plain\" data-lang=\"plain\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edeb http://archive.kylinos.cn/kylin/KYLIN-ALL 10.0 main restricted universe multiverse\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edeb http://archive.kylinos.cn/kylin/partner juniper main\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col\u003e\n\u003cli\u003e定制版uos：\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-dockerfile\" data-lang=\"dockerfile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir /tmp/livecd\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emount -o loop uos*.iso /tmp/livecd\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir -p livecd/cd\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ersync --exclude\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/live/filesystem.squashfs -a /tmp/livecd/ livecd/cd\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir livecd/squashfs\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003emkdir livecd/custom\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emodprobe squashfs\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emount -t squashfs -o loop /tmp/livecd/live/filesystem.squashfs livecd/squashfs\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecp -a livecd/squashfs/* livecd/custom\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecp /etc/resolv.conf livecd/custom/etc/\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecp /etc/apt/sources.list livecd/custom/etc/apt/sources.list\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003echroot livecd/custom apt install xrdp htop gnome-disk*\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erm -rf livecd/custom/recovery*\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emksquashfs livecd/custom ./filesystem.squashfs \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e chmod -R \u003cspan style=\"color:#ae81ff\"\u003e777\u003c/span\u003e ./*.squashfs\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col\u003e\n\u003cli\u003euos无需激活即可root：\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-plain\" data-lang=\"plain\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enano /etc/pam.d/su\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#auth    requisite           deepin_security_verify.so\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col\u003e\n\u003cli\u003e命令行激活试用：uos\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-plain\" data-lang=\"plain\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euos-activator-cmd -t\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col\u003e\n\u003cli\u003e1\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"3-unixbench\"\u003e(3) unixbench\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003ewget \u003ca href=\"http://github.itzmx.com/1265578519/unixbench/master/5.1.3/unixbench.sh\"\u003ehttp://github.itzmx.com/1265578519/unixbench/master/5.1.3/unixbench.sh\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003echmod 777 *.sh \u0026amp;\u0026amp; ./unixbench.sh\u003c/li\u003e\n\u003cli\u003e多核的话改一下run文件，第 109,110,111,112 行修改数字为当前系统 CPU 核数，然后./Run -c 核数\u003c/li\u003e\n\u003cli\u003enano Makefile ，47行\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-plain\" data-lang=\"plain\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e1GL_LIBS = -lGL -lXext -lX11 lm\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col\u003e\n\u003cli\u003enano Run，111行\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-plain\" data-lang=\"plain\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# \u0026#39;3d\u0026#39;  =\u0026gt; { \u0026#39;name\u0026#39; =\u0026gt; \u0026#34;3D Graphics Benchmarks\u0026#34;,\u0026#39;maxCopies\u0026#39; =\u0026gt; 8 },\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col\u003e\n\u003cli\u003emake all \u0026amp;\u0026amp; ./Run graphics\u003c/li\u003e\n\u003cli\u003e1\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"4iozone\"\u003e(4) iozone\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003ewget \u003ca href=\"http://www.iozone.org/src/current/iozone3_487.tar\"\u003ehttp://www.iozone.org/src/current/iozone3_487.tar\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003etar -xvf iozone3_487.tar\u003c/li\u003e\n\u003cli\u003ecd iozone3_487/src/current/\u003c/li\u003e\n\u003cli\u003emake linux\u003c/li\u003e\n\u003cli\u003e./iozone -a -i 0 -i 1 -i 2 -f /mnt/testfile -r 16m -s 8G | tee -a iozone.log\u003c/li\u003e\n\u003cli\u003e./iozone -a -i 0 -i 1 -i 2 -f /mnt/testfile -r 16m -s 16G | tee -a iozone.log\u003c/li\u003e\n\u003cli\u003e./iozone -a -i 0 -i 1 -i 2 -f /mnt/testfile -r 16m -s 32G | tee -a iozone.log\u003c/li\u003e\n\u003cli\u003ewget\u003ca href=\"https://gitee.com/haolixu/test/raw/master/fio.sh\"\u003ehttps://gitee.com/haolixu/test/raw/master/iozone.sh\u003c/a\u003e\u0026amp;\u0026amp; bash iozone.sh\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"5远程桌面\"\u003e(5) 远程桌面\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003eapt install xrdp\u003c/li\u003e\n\u003cli\u003eapt install gnome*\u003c/li\u003e\n\u003cli\u003eecho “gnome-session \u0026ndash;session=gnome-classic” \u0026gt; ~/.xsession\u003c/li\u003e\n\u003cli\u003e/etc/init.d/xrdp start\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e19.12.23更新！\u003c/p\u003e","title":"服务器测试整理"},{"content":"在接口测试中实现“自动解析文档→生成用例”的核心是通过**“文档结构化解析→元数据提取→场景规则映射→用例自动化编排”**的全流程自动化，结合的语义理解与测试领域知识，将非结构化的接口文档转化为覆盖全面、可直接执行的测试用例。\n一、整体流程框架 整个过程分为4个核心阶段，由“接口解析Agent”和“用例生成Agent”协同完成，依赖“文档同步模块”“元数据存储模块”“规则引擎”三大支撑组件：\ngraph TD\rsubgraph 准备阶段\rA[接口文档同步] --\u0026gt; A1[对接Swagger/OpenAPI]\rA --\u0026gt; A2[监听文档变更（Webhook）]\rA --\u0026gt; A3[历史文档版本管理]\rend\rsubgraph 解析阶段（接口解析Agent）\rB[元数据提取] --\u0026gt; B1[基础信息：路径/方法/描述]\rB --\u0026gt; B2[参数信息：类型/约束/位置]\rB --\u0026gt; B3[响应信息：状态码/schema/字段]\rB --\u0026gt; B4[依赖关系：前置接口/动态参数]\rend\rsubgraph 生成阶段（用例生成Agent）\rC[场景规则映射] --\u0026gt; C1[正向场景：合法参数组合]\rC --\u0026gt; C2[异常场景：参数校验失败]\rC --\u0026gt; C3[边界场景：临界值/极限值]\rC --\u0026gt; C4[依赖场景：接口调用链]\rend\rsubgraph 输出阶段\rD[用例格式化] --\u0026gt; D1[Postman/JMeter格式]\rD --\u0026gt; D2[pytest脚本格式]\rD --\u0026gt; D3[测试管理工具格式（TestRail）]\rend 二、具体步骤与技术实现 阶段1：同步——确保解析源实时准确 目标：获取最新接口文档（如/OpenAPI），并监控变更以触发后续解析流程。\n具体操作：\n文档接入方式： 主动拉取：通过定时任务（如每小时）调用接口文档地址（如https://api.example.com/v3/api-docs），获取JSON格式的Swagger文档； 被动接收：配置Git Webhook，当接口文档代码（如后端项目的Swagger配置）提交时，自动推送最新文档至Agent系统。 文档版本管理： 将每次获取的文档存储在版本库（如Git），标记版本号（如v2.3.1），便于后续对比变更（如参数新增/删除）。 阶段2：元（接口解析Agent核心工作） 目标：从接口文档中提取结构化元数据（基础信息、参数、响应、依赖），为用例生成提供“原材料”。\n技术实现：\n接口解析Agent通过解析Swagger/OpenAPI的JSON结构，提取以下核心信息（以Swagger 3.0为例）：\n2.1 基础信息提取 提取接口的路径、请求方法、功能描述等基础信息：\n# 解析基础信息代码片段 def extract_basic_info(swagger_path, swagger_method): \u0026#34;\u0026#34;\u0026#34; swagger_path: 接口路径（如\u0026#34;/api/order\u0026#34;） swagger_method: 接口方法（如\u0026#34;post\u0026#34;） \u0026#34;\u0026#34;\u0026#34; method_details = swagger_path[swagger_method] return { \u0026#34;path\u0026#34;: swagger_path, # 接口路径 \u0026#34;method\u0026#34;: swagger_method.upper(), # 请求方法（GET/POST等） \u0026#34;description\u0026#34;: method_details.get(\u0026#34;description\u0026#34;, \u0026#34;\u0026#34;), # 功能描述 \u0026#34;tags\u0026#34;: method_details.get(\u0026#34;tags\u0026#34;, []), # 所属模块（如\u0026#34;订单管理\u0026#34;） \u0026#34;operation_id\u0026#34;: method_details.get(\u0026#34;operationId\u0026#34;, \u0026#34;\u0026#34;) # 唯一标识 } 2.2 参数信息提取 参数是的核心，需提取参数位置、类型、约束规则（非空、长度、枚举等），支持路径参数、查询参数、请求体（body）等多种类型：\n# 解析参数信息代码片段 def extract_parameters(method_details): parameters = [] # 1. 提取路径参数、查询参数（在\u0026#34;parameters\u0026#34;字段中） for param in method_details.get(\u0026#34;parameters\u0026#34;, []): param_info = { \u0026#34;name\u0026#34;: param[\u0026#34;name\u0026#34;], # 参数名 \u0026#34;in\u0026#34;: param[\u0026#34;in\u0026#34;], # 位置：path/query/header \u0026#34;type\u0026#34;: param[\u0026#34;schema\u0026#34;][\u0026#34;type\u0026#34;], # 类型：string/number/integer等 \u0026#34;required\u0026#34;: param.get(\u0026#34;required\u0026#34;, False), # 是否必填 \u0026#34;constraints\u0026#34;: {} # 约束规则 } # 提取约束规则（如长度、范围、枚举） if \u0026#34;minLength\u0026#34; in param[\u0026#34;schema\u0026#34;]: param_info[\u0026#34;constraints\u0026#34;][\u0026#34;minLength\u0026#34;] = param[\u0026#34;schema\u0026#34;][\u0026#34;minLength\u0026#34;] if \u0026#34;maxLength\u0026#34; in param[\u0026#34;schema\u0026#34;]: param_info[\u0026#34;constraints\u0026#34;][\u0026#34;maxLength\u0026#34;] = param[\u0026#34;schema\u0026#34;][\u0026#34;maxLength\u0026#34;] if \u0026#34;enum\u0026#34; in param[\u0026#34;schema\u0026#34;]: param_info[\u0026#34;constraints\u0026#34;][\u0026#34;enum\u0026#34;] = param[\u0026#34;schema\u0026#34;][\u0026#34;enum\u0026#34;] if \u0026#34;minimum\u0026#34; in param[\u0026#34;schema\u0026#34;]: param_info[\u0026#34;constraints\u0026#34;][\u0026#34;minimum\u0026#34;] = param[\u0026#34;schema\u0026#34;][\u0026#34;minimum\u0026#34;] parameters.append(param_info) # 2. 提取请求体参数（在\u0026#34;requestBody\u0026#34;字段中，通常为JSON） request_body = method_details.get(\u0026#34;requestBody\u0026#34;, {}) if \u0026#34;content\u0026#34; in request_body and \u0026#34;application/json\u0026#34; in request_body[\u0026#34;content\u0026#34;]: json_schema = request_body[\u0026#34;content\u0026#34;][\u0026#34;application/json\u0026#34;][\u0026#34;schema\u0026#34;] # 递归解析嵌套JSON参数（如{\u0026#34;user\u0026#34;: {\u0026#34;name\u0026#34;: \u0026#34;string\u0026#34;, \u0026#34;age\u0026#34;: \u0026#34;integer\u0026#34;}}） body_params = parse_nested_schema(json_schema, parent_key=\u0026#34;body\u0026#34;) parameters.extend(body_params) return parameters # 辅助函数：解析嵌套JSON参数 def parse_nested_schema(schema, parent_key): nested_params = [] if schema[\u0026#34;type\u0026#34;] == \u0026#34;object\u0026#34; and \u0026#34;properties\u0026#34; in schema: for prop_name, prop_schema in schema[\u0026#34;properties\u0026#34;].items(): full_key = f\u0026#34;{parent_key}.{prop_name}\u0026#34; if parent_key else prop_name # 若为嵌套对象，递归解析（如address.city） if prop_schema.get(\u0026#34;type\u0026#34;) == \u0026#34;object\u0026#34;: nested_params.extend(parse_nested_schema(prop_schema, full_key)) else: # 提取基础类型参数的约束 param = { \u0026#34;name\u0026#34;: full_key, \u0026#34;in\u0026#34;: \u0026#34;body\u0026#34;, \u0026#34;type\u0026#34;: prop_schema[\u0026#34;type\u0026#34;], \u0026#34;required\u0026#34;: prop_name in schema.get(\u0026#34;required\u0026#34;, []), \u0026#34;constraints\u0026#34;: extract_constraints(prop_schema) } nested_params.append(param) return nested_params 示例输出（参数信息）：\n[ { \u0026#34;name\u0026#34;: \u0026#34;orderId\u0026#34;, \u0026#34;in\u0026#34;: \u0026#34;path\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;, \u0026#34;required\u0026#34;: true, \u0026#34;constraints\u0026#34;: {\u0026#34;minLength\u0026#34;: 10, \u0026#34;maxLength\u0026#34;: 20} // 订单ID长度10-20位 }, { \u0026#34;name\u0026#34;: \u0026#34;body.amount\u0026#34;, \u0026#34;in\u0026#34;: \u0026#34;body\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;number\u0026#34;, \u0026#34;required\u0026#34;: true, \u0026#34;constraints\u0026#34;: {\u0026#34;minimum\u0026#34;: 0.01, \u0026#34;maximum\u0026#34;: 10000} // 金额0.01-10000元 }, { \u0026#34;name\u0026#34;: \u0026#34;status\u0026#34;, \u0026#34;in\u0026#34;: \u0026#34;query\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;, \u0026#34;required\u0026#34;: false, \u0026#34;constraints\u0026#34;: {\u0026#34;enum\u0026#34;: [\u0026#34;pending\u0026#34;, \u0026#34;paid\u0026#34;, \u0026#34;cancelled\u0026#34;]} // 状态枚举 } ] 2.3 响应信息提取 提取接口的响应状态码、响应体schema（字段及类型），用于后续用例的预期结果校验：\ndef extract_responses(method_details): responses = {} for status_code, status_details in method_details.get(\u0026#34;responses\u0026#34;, {}).items(): # 提取响应体schema（如200成功响应） if \u0026#34;content\u0026#34; in status_details and \u0026#34;application/json\u0026#34; in status_details[\u0026#34;content\u0026#34;]: response_schema = status_details[\u0026#34;content\u0026#34;][\u0026#34;application/json\u0026#34;][\u0026#34;schema\u0026#34;] responses[status_code] = { \u0026#34;description\u0026#34;: status_details.get(\u0026#34;description\u0026#34;, \u0026#34;\u0026#34;), \u0026#34;schema\u0026#34;: response_schema # 响应体字段及类型定义 } return responses # 示例输出（响应信息） { \u0026#34;200\u0026#34;: { \u0026#34;description\u0026#34;: \u0026#34;success\u0026#34;, \u0026#34;schema\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;object\u0026#34;, \u0026#34;properties\u0026#34;: { \u0026#34;code\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;integer\u0026#34;, \u0026#34;enum\u0026#34;: [200]}, \u0026#34;data\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;object\u0026#34;, \u0026#34;properties\u0026#34;: {\u0026#34;orderId\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;}}}, \u0026#34;msg\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;} } } }, \u0026#34;400\u0026#34;: { \u0026#34;description\u0026#34;: \u0026#34;bad request\u0026#34;, \u0026#34;schema\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;object\u0026#34;, \u0026#34;properties\u0026#34;: {\u0026#34;code\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;integer\u0026#34;}, \u0026#34;msg\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;}}} } } 2.4 提取 识别接口的前置依赖（如“创建订单”需先“登录获取token”），为生成“接口调用链”用例提供依据：\ndef extract_dependencies(method_details): dependencies = [] # 1. 从请求头提取token依赖（如Authorization字段） for param in method_details.get(\u0026#34;parameters\u0026#34;, []): if param.get(\u0026#34;name\u0026#34;) == \u0026#34;Authorization\u0026#34; and param.get(\u0026#34;in\u0026#34;) == \u0026#34;header\u0026#34;: # 假设登录接口返回token，路径为\u0026#34;/api/login\u0026#34; dependencies.append({ \u0026#34;type\u0026#34;: \u0026#34;token\u0026#34;, \u0026#34;source_interface\u0026#34;: \u0026#34;/api/login\u0026#34;, # 前置接口 \u0026#34;extract_rule\u0026#34;: \u0026#34;response.body.token\u0026#34; # 从登录响应提取token的规则 }) # 2. 从业务逻辑提取依赖（如“确认收货”需先“创建订单”） if \u0026#34;operationId\u0026#34; in method_details and \u0026#34;confirmReceipt\u0026#34; in method_details[\u0026#34;operationId\u0026#34;]: dependencies.append({ \u0026#34;type\u0026#34;: \u0026#34;business\u0026#34;, \u0026#34;source_interface\u0026#34;: \u0026#34;/api/order/create\u0026#34;, # 前置接口 \u0026#34;extract_rule\u0026#34;: \u0026#34;response.body.orderId\u0026#34; # 从创建订单响应提取orderId }) return dependencies 阶段3：生成（用例生成Agent核心工作） 目标：基于提取的元数据，按“正向→异常→边界→依赖”四类场景生成用例，覆盖所有参数规则和业务逻辑。\n3.1 正向用例生成（合法参数组合） 生成符合所有参数约束的用例，验证接口正常功能：\n逻辑：为每个参数选择“合法值”（如字符串取中间长度、数字取范围内值、枚举取合法选项），组合成完整请求。 示例（针对上文参数）： def generate_positive_cases(parameters): positive_params = {} for param in parameters: if param[\u0026#34;type\u0026#34;] == \u0026#34;string\u0026#34; and \u0026#34;enum\u0026#34; in param[\u0026#34;constraints\u0026#34;]: # 枚举参数：选第一个合法值 positive_params[param[\u0026#34;name\u0026#34;]] = param[\u0026#34;constraints\u0026#34;][\u0026#34;enum\u0026#34;][0] elif param[\u0026#34;type\u0026#34;] == \u0026#34;string\u0026#34; and \u0026#34;minLength\u0026#34; in param[\u0026#34;constraints\u0026#34;]: # 字符串参数：取中间长度（如min=10, max=20→取15位） length = (param[\u0026#34;constraints\u0026#34;][\u0026#34;minLength\u0026#34;] + param[\u0026#34;constraints\u0026#34;][\u0026#34;maxLength\u0026#34;]) // 2 positive_params[param[\u0026#34;name\u0026#34;]] = \u0026#34;a\u0026#34; * length elif param[\u0026#34;type\u0026#34;] == \u0026#34;number\u0026#34;: # 数字参数：取中间值（如0.01-10000→取5000.00） mid = (param[\u0026#34;constraints\u0026#34;][\u0026#34;minimum\u0026#34;] + param[\u0026#34;constraints\u0026#34;][\u0026#34;maximum\u0026#34;]) / 2 positive_params[param[\u0026#34;name\u0026#34;]] = round(mid, 2) return { \u0026#34;case_type\u0026#34;: \u0026#34;positive\u0026#34;, \u0026#34;priority\u0026#34;: \u0026#34;P0\u0026#34;, \u0026#34;params\u0026#34;: positive_params, \u0026#34;expected_response\u0026#34;: {\u0026#34;status_code\u0026#34;: 200, \u0026#34;schema_match\u0026#34;: True} } 正向用例示例：\n{ \u0026#34;case_id\u0026#34;: \u0026#34;API-ORDER-001\u0026#34;, \u0026#34;case_type\u0026#34;: \u0026#34;positive\u0026#34;, \u0026#34;priority\u0026#34;: \u0026#34;P0\u0026#34;, \u0026#34;path\u0026#34;: \u0026#34;/api/order\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;POST\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;orderId\u0026#34;: \u0026#34;aaaaaaaaaaaaaaa\u0026#34;（15位，符合10-20位约束）, \u0026#34;body.amount\u0026#34;: 5000.00（0.01-10000中间值）, \u0026#34;status\u0026#34;: \u0026#34;pending\u0026#34;（合法枚举值） }, \u0026#34;expected_response\u0026#34;: { \u0026#34;status_code\u0026#34;: 200, \u0026#34;schema_match\u0026#34;: true, \u0026#34;fields\u0026#34;: {\u0026#34;code\u0026#34;: 200, \u0026#34;msg\u0026#34;: \u0026#34;success\u0026#34;} } } 3.2 异常用例生成（参数校验失败） 生成违反参数约束的用例，验证接口的错误处理能力（如提示“参数格式错误”）：\n逻辑：针对每个参数的“约束规则”，生成“违反单条规则”的用例（避免多错误叠加导致定位困难）。 示例（针对上文参数）： def generate_abnormal_cases(parameters): abnormal_cases = [] for param in parameters: # 非空校验：必填参数不传 if param[\u0026#34;required\u0026#34;]: case = { \u0026#34;case_type\u0026#34;: \u0026#34;abnormal\u0026#34;, \u0026#34;priority\u0026#34;: \u0026#34;P1\u0026#34;, \u0026#34;error_type\u0026#34;: \u0026#34;missing_required_param\u0026#34;, \u0026#34;params\u0026#34;: {k: v for k, v in base_params.items() if k != param[\u0026#34;name\u0026#34;]}, # 剔除当前参数 \u0026#34;expected_response\u0026#34;: {\u0026#34;status_code\u0026#34;: 400, \u0026#34;msg_contains\u0026#34;: f\u0026#34;缺少参数{param[\u0026#39;name\u0026#39;]}\u0026#34;} } abnormal_cases.append(case) # 类型校验：参数类型错误（如数字传字符串） if param[\u0026#34;type\u0026#34;] == \u0026#34;number\u0026#34;: case = { \u0026#34;case_type\u0026#34;: \u0026#34;abnormal\u0026#34;, \u0026#34;priority\u0026#34;: \u0026#34;P1\u0026#34;, \u0026#34;error_type\u0026#34;: \u0026#34;type_error\u0026#34;, \u0026#34;params\u0026#34;: {**base_params, param[\u0026#34;name\u0026#34;]: \u0026#34;not_a_number\u0026#34;}, # 传字符串 \u0026#34;expected_response\u0026#34;: {\u0026#34;status_code\u0026#34;: 400, \u0026#34;msg_contains\u0026#34;: f\u0026#34;{param[\u0026#39;name\u0026#39;]}必须为数字\u0026#34;} } abnormal_cases.append(case) return abnormal_cases 异常用例示例：\n{ \u0026#34;case_id\u0026#34;: \u0026#34;API-ORDER-002\u0026#34;, \u0026#34;case_type\u0026#34;: \u0026#34;abnormal\u0026#34;, \u0026#34;priority\u0026#34;: \u0026#34;P1\u0026#34;, \u0026#34;error_type\u0026#34;: \u0026#34;missing_required_param\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;body.amount\u0026#34;: 5000.00, // 缺少必填参数orderId \u0026#34;status\u0026#34;: \u0026#34;pending\u0026#34; }, \u0026#34;expected_response\u0026#34;: { \u0026#34;status_code\u0026#34;: 400, \u0026#34;msg_contains\u0026#34;: \u0026#34;缺少参数orderId\u0026#34; } } 3.3 边界用例生成（临界值测试） 生成参数边界值的用例，验证接口对极限情况的处理（如“金额=10000.00”“订单ID=10位/20位”）：\n逻辑：针对“长度、范围”类约束，取“最小值、最大值、最小值-1、最大值+1”作为参数值。 示例： { \u0026#34;case_id\u0026#34;: \u0026#34;API-ORDER-003\u0026#34;, \u0026#34;case_type\u0026#34;: \u0026#34;boundary\u0026#34;, \u0026#34;priority\u0026#34;: \u0026#34;P1\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;orderId\u0026#34;: \u0026#34;aaaaaaaaaa\u0026#34;（10位，等于minLength）, \u0026#34;body.amount\u0026#34;: 10000.00（等于maximum）, \u0026#34;status\u0026#34;: \u0026#34;paid\u0026#34; }, \u0026#34;expected_response\u0026#34;: {\u0026#34;status_code\u0026#34;: 200, \u0026#34;msg\u0026#34;: \u0026#34;success\u0026#34;} }, { \u0026#34;case_id\u0026#34;: \u0026#34;API-ORDER-004\u0026#34;, \u0026#34;case_type\u0026#34;: \u0026#34;boundary\u0026#34;, \u0026#34;priority\u0026#34;: \u0026#34;P1\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;orderId\u0026#34;: \u0026#34;aaaaaaaaa\u0026#34;（9位，小于minLength）, \u0026#34;body.amount\u0026#34;: 10000.01（大于maximum）, \u0026#34;status\u0026#34;: \u0026#34;cancelled\u0026#34; }, \u0026#34;expected_response\u0026#34;: {\u0026#34;status_code\u0026#34;: 400, \u0026#34;msg_contains\u0026#34;: \u0026#34;orderId长度不足/金额超限\u0026#34;} } 3.4 依赖用例链生成（接口调用序列） 针对有前置依赖的接口，生成“前置接口→目标接口”的调用链用例，确保上下文连贯：\n逻辑：先执行前置接口（如登录），提取动态参数（如token），再传入目标接口（如创建订单）。 示例（登录→创建订单的用例链）： { \u0026#34;case_chain_id\u0026#34;: \u0026#34;CHAIN-001\u0026#34;, \u0026#34;cases\u0026#34;: [ { \u0026#34;case_id\u0026#34;: \u0026#34;PRE-LOGIN-001\u0026#34;, \u0026#34;path\u0026#34;: \u0026#34;/api/login\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;POST\u0026#34;, \u0026#34;params\u0026#34;: {\u0026#34;username\u0026#34;: \u0026#34;test\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;123456\u0026#34;}, \u0026#34;extract\u0026#34;: {\u0026#34;token\u0026#34;: \u0026#34;response.body.token\u0026#34;} // 提取token }, { \u0026#34;case_id\u0026#34;: \u0026#34;API-ORDER-005\u0026#34;, \u0026#34;path\u0026#34;: \u0026#34;/api/order\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;POST\u0026#34;, \u0026#34;params\u0026#34;: { \u0026#34;orderId\u0026#34;: \u0026#34;aaaaaaaaaaaaaaa\u0026#34;, \u0026#34;body.amount\u0026#34;: 5000.00, \u0026#34;headers\u0026#34;: {\u0026#34;Authorization\u0026#34;: \u0026#34;Bearer {{token}}\u0026#34;} // 引用前置接口的token }, \u0026#34;expected_response\u0026#34;: {\u0026#34;status_code\u0026#34;: 200} } ] } 阶段4：用例与输出 将生成的用例转化为可执行格式，适配主流测试工具：\nPostman格式：生成Collection JSON，包含请求URL、参数、headers、测试脚本（断言）； pytest格式：生成Python脚本，调用requests库发送请求，用assert断言响应； TestRail格式：按“标题、步骤、预期结果”格式化，通过API同步至测试管理工具。 pytest脚本示例：\nimport requests def test_order_create_positive(): url = \u0026#34;https://test-api.example.com/api/order\u0026#34; headers = {\u0026#34;Content-Type\u0026#34;: \u0026#34;application/json\u0026#34;} params = { \u0026#34;orderId\u0026#34;: \u0026#34;aaaaaaaaaaaaaaa\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;pending\u0026#34; } json_data = {\u0026#34;amount\u0026#34;: 5000.00} response = requests.post(url, headers=headers, params=params, json=json_data) # 断言 assert response.status_code == 200 assert response.json()[\u0026#34;code\u0026#34;] == 200 assert \u0026#34;orderId\u0026#34; in response.json()[\u0026#34;data\u0026#34;] 三、实例演示：完整流程跑通一个接口 以“用户转账接口（POST /api/transfer）”为例，展示从解析到生成用例的完整过程：\n1. 接口文档（Swagger片段） { \u0026#34;paths\u0026#34;: { \u0026#34;/api/transfer\u0026#34;: { \u0026#34;post\u0026#34;: { \u0026#34;description\u0026#34;: \u0026#34;用户转账\u0026#34;, \u0026#34;parameters\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;Authorization\u0026#34;, \u0026#34;in\u0026#34;: \u0026#34;header\u0026#34;, \u0026#34;required\u0026#34;: true, \u0026#34;schema\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;} } ], \u0026#34;requestBody\u0026#34;: { \u0026#34;content\u0026#34;: { \u0026#34;application/json\u0026#34;: { \u0026#34;schema\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;object\u0026#34;, \u0026#34;properties\u0026#34;: { \u0026#34;targetAccount\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;, \u0026#34;minLength\u0026#34;: 10, \u0026#34;maxLength\u0026#34;: 20}, \u0026#34;amount\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;number\u0026#34;, \u0026#34;minimum\u0026#34;: 0.01, \u0026#34;maximum\u0026#34;: 50000}, \u0026#34;remark\u0026#34;: {\u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;, \u0026#34;maxLength\u0026#34;: 100} }, \u0026#34;required\u0026#34;: [\u0026#34;targetAccount\u0026#34;, \u0026#34;amount\u0026#34;] } } } }, \u0026#34;responses\u0026#34;: { \u0026#34;200\u0026#34;: {\u0026#34;description\u0026#34;: \u0026#34;success\u0026#34;}, \u0026#34;400\u0026#34;: {\u0026#34;description\u0026#34;: \u0026#34;参数错误\u0026#34;} } } } } } 2. 元数据提取结果 { \u0026#34;path\u0026#34;: \u0026#34;/api/transfer\u0026#34;, \u0026#34;method\u0026#34;: \u0026#34;POST\u0026#34;, \u0026#34;parameters\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;Authorization\u0026#34;, \u0026#34;in\u0026#34;: \u0026#34;header\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;, \u0026#34;required\u0026#34;: true, \u0026#34;constraints\u0026#34;: {} }, { \u0026#34;name\u0026#34;: \u0026#34;body.targetAccount\u0026#34;, \u0026#34;in\u0026#34;: \u0026#34;body\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;, \u0026#34;required\u0026#34;: true, \u0026#34;constraints\u0026#34;: {\u0026#34;minLength\u0026#34;: 10, \u0026#34;maxLength\u0026#34;: 20} }, { \u0026#34;name\u0026#34;: \u0026#34;body.amount\u0026#34;, \u0026#34;in\u0026#34;: \u0026#34;body\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;number\u0026#34;, \u0026#34;required\u0026#34;: true, \u0026#34;constraints\u0026#34;: {\u0026#34;minimum\u0026#34;: 0.01, \u0026#34;maximum\u0026#34;: 50000} }, { \u0026#34;name\u0026#34;: \u0026#34;body.remark\u0026#34;, \u0026#34;in\u0026#34;: \u0026#34;body\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;string\u0026#34;, \u0026#34;required\u0026#34;: false, \u0026#34;constraints\u0026#34;: {\u0026#34;maxLength\u0026#34;: 100} } ], \u0026#34;dependencies\u0026#34;: [ {\u0026#34;type\u0026#34;: \u0026#34;token\u0026#34;, \u0026#34;source_interface\u0026#34;: \u0026#34;/api/login\u0026#34;, \u0026#34;extract_rule\u0026#34;: \u0026#34;response.body.token\u0026#34;} ] } 3. 生成的用例（节选） 正向用例：合法参数组合； 异常用例：缺失targetAccount、amount为负数； 边界用例：targetAccount=10位/20位、amount=50000.00； 依赖用例链：登录→转账（携带token）。 四、关键技术保障 嵌套参数解析能力：通过递归函数处理多层JSON参数（如body.user.address.city），避免漏解析； 约束规则完整性：覆盖Swagger支持的所有约束类型（minLength/maxLength/enum/minimum/maximum/pattern等）； 动态依赖处理：通过“参数提取规则”（如response.body.token）实现跨接口参数传递，确保用例链可执行； 去重与精简：合并重复场景（如“参数A为空”和“参数B为空”是两个独立场景，但格式一致时复用模板），避免用例冗余。 总结 Agent通过“文档同步→元数据提取→多场景用例生成→格式化输出”的全流程自动化，将接口测试用例的生成效率提升80%以上，参数覆盖率从人工的70%提升至100%。核心优势在于：\n无遗漏：严格按参数约束生成场景，避免人工经验不足导致的漏测； 可扩展：支持任意Swagger/OpenAPI接口，适配嵌套参数、复杂依赖等场景； 可执行：直接生成Postman/pytest格式用例，无需二次修改即可执行。 落地时需重点维护“参数约束规则库”和“依赖关系图谱”，确保Agent对业务逻辑的理解准确性。\n原文链接: Agent接口测试中实践 作者: 质量保障小乔\n","permalink":"http://nb404.cn/posts/agent%E6%8E%A5%E5%8F%A3%E6%B5%8B%E8%AF%95%E4%B8%AD%E5%AE%9E%E8%B7%B5/","summary":"\u003cp\u003e在接口测试中实现“自动解析文档→生成用例”的核心是通过**“文档结构化解析→元数据提取→场景规则映射→用例自动化编排”**的全流程自动化，结合的语义理解与测试领域知识，将非结构化的接口文档转化为覆盖全面、可直接执行的测试用例。\u003c/p\u003e\n\u003ch4 id=\"一整体流程框架\"\u003e一、整体流程框架\u003c/h4\u003e\n\u003cp\u003e整个过程分为\u003cstrong\u003e4个核心阶段\u003c/strong\u003e，由“接口解析Agent”和“用例生成Agent”协同完成，依赖“文档同步模块”“元数据存储模块”“规则引擎”三大支撑组件：\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-mermaid\" data-lang=\"mermaid\"\u003egraph TD\r\n    subgraph 准备阶段\r\n        A[接口文档同步] --\u0026gt; A1[对接Swagger/OpenAPI]\r\n        A --\u0026gt; A2[监听文档变更（Webhook）]\r\n        A --\u0026gt; A3[历史文档版本管理]\r\n    end\r\n    \r\n    subgraph 解析阶段（接口解析Agent）\r\n        B[元数据提取] --\u0026gt; B1[基础信息：路径/方法/描述]\r\n        B --\u0026gt; B2[参数信息：类型/约束/位置]\r\n        B --\u0026gt; B3[响应信息：状态码/schema/字段]\r\n        B --\u0026gt; B4[依赖关系：前置接口/动态参数]\r\n    end\r\n    \r\n    subgraph 生成阶段（用例生成Agent）\r\n        C[场景规则映射] --\u0026gt; C1[正向场景：合法参数组合]\r\n        C --\u0026gt; C2[异常场景：参数校验失败]\r\n        C --\u0026gt; C3[边界场景：临界值/极限值]\r\n        C --\u0026gt; C4[依赖场景：接口调用链]\r\n    end\r\n    \r\n    subgraph 输出阶段\r\n        D[用例格式化] --\u0026gt; D1[Postman/JMeter格式]\r\n        D --\u0026gt; D2[pytest脚本格式]\r\n        D --\u0026gt; D3[测试管理工具格式（TestRail）]\r\n    end\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"二具体步骤与技术实现\"\u003e二、具体步骤与技术实现\u003c/h4\u003e\n\u003ch5 id=\"阶段1同步确保解析源实时准确\"\u003e阶段1：同步——确保解析源实时准确\u003c/h5\u003e\n\u003cp\u003e\u003cstrong\u003e目标\u003c/strong\u003e：获取最新接口文档（如/OpenAPI），并监控变更以触发后续解析流程。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e具体操作\u003c/strong\u003e：\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003e文档接入方式\u003c/strong\u003e：\u003c/li\u003e\n\u003c/ol\u003e\n\u003cul\u003e\n\u003cli\u003e主动拉取：通过定时任务（如每小时）调用接口文档地址（如\u003ccode\u003ehttps://api.example.com/v3/api-docs\u003c/code\u003e），获取JSON格式的Swagger文档；\u003c/li\u003e\n\u003cli\u003e被动接收：配置Git Webhook，当接口文档代码（如后端项目的Swagger配置）提交时，自动推送最新文档至Agent系统。\u003c/li\u003e\n\u003c/ul\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003e\u003cstrong\u003e文档版本管理\u003c/strong\u003e：\n将每次获取的文档存储在版本库（如Git），标记版本号（如\u003ccode\u003ev2.3.1\u003c/code\u003e），便于后续对比变更（如参数新增/删除）。\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch5 id=\"阶段2元接口解析agent核心工作\"\u003e阶段2：元（接口解析Agent核心工作）\u003c/h5\u003e\n\u003cp\u003e\u003cstrong\u003e目标\u003c/strong\u003e：从接口文档中提取结构化元数据（基础信息、参数、响应、依赖），为用例生成提供“原材料”。\u003c/p\u003e","title":"Agent接口测试中实践"},{"content":"脚本依赖环境安装指南 以下是为运行 CSDN 博客导出脚本（如 export_csdn_cf.py）而准备 Linux 系统环境所执行的一系列有效命令。这些命令主要用于安装 运行时、及其依赖库。\n# 1. 安装 Python 包管理工具 pip3 apt install python3-pip -y # 2. 安装文件传输和解压工具 apt -y install lrzsz # 提供 rz/sz 命令，用于终端文件上传下载 apt -y install zip unzip # 用于处理 zip 和 unzip 格式的压缩包 # 3. 安装重命名工具 apt install rename # 强大的 Perl 脚本，用于批量重命名文件 # 4. 配置 Google Chrome 浏览器安装源 (使用清华镜像加速) # 下载并添加 Google 的 GPG 公钥以验证软件包完整性 wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - #或者上传执行如下的命令 # cat linux_signing_key.pub |sudo apt-key add - Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)). OK # 将清华镜像的 Chrome 源写入 APT 源列表 echo \u0026#34;deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/google-chrome/deb/ stable main\u0026#34; \u0026gt; /etc/apt/sources.list.d/google-chrome.list # 5. 更新软件包索引并安装 Chrome 及其系统依赖 apt update # 同步最新的软件包列表 # 安装稳定版 Google Chrome # 下载 \u0026amp;\u0026amp; dpkg -i去安装 https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb # 修复相关的依赖 apt --fix-broken install -y # 6. 安装 Chrome 运行所需的底层库 (确保 headless 模式正常工作) apt install -y \\ wget \\ unzip \\ libxss1 \\ libappindicator1 \\ libindicator7 \\ fonts-liberation \\ libasound2 \\ libatk-bridge2.0-0 \\ libgtk-3-0 \\ libdrm-common # 7. （可选）修复可能存在的依赖问题 apt --fix-broken install -y # 如果之前的安装出现中断或依赖错误，此命令可尝试自动修复 说明： 虽然核心抓取脚本export_csdn_cf.py使用的是cloudscraper，它不直接依赖浏览器，但如果您后续计划使用selenium或playwright等基于真实浏览器的自动化工具来应对更复杂的反爬机制（如 Turnstile 验证码），那么安装 Chrome 是必需的。 此处列出的lib*库是 Chrome 在无头（headless）模式下运行时常见的依赖项，能避免因缺少图形或音频库而导致的启动失败。 使用清华（TUNA）镜像可以显著加快在境内网络环境下下载 Chrome 的速度。 步骤一：安装 pip3 依赖 在开始编写和执行脚本之前，我们需要先配置好运行环境并安装必要的第三方库。\n# 1. 配置pip的源 (csdn-env) root@wanyan:/opt/csdn# cat ~/.pip/pip.conf [global] index-url = https://mirrors.aliyun.com/pypi/simple/ trusted-host = pypi.aliyun.com timeout = 120 # 2. 创建并激活 Python 虚拟环境 (推荐做法，避免依赖冲突) apt install python3.10-venv -y python3 -m venv csdn-env source csdn-env/bin/activate # Linux/Mac # 或者在 Windows 上: csdn-env\\Scripts\\activate # 3. 安装核心依赖包 pip3 install cloudscraper requests beautifulsoup4 markdownify lxml 实现原理与注释： cloudscraper: 这是本方案的核心。CSDN 网站使用了 Cloudflare 的反爬虫保护机制（如著名的“5秒盾”）。普通的requests库会直接被拦截。cloudscraper是一个专门设计用来绕过 Cloudflare 防护的库，它能模拟真实的浏览器行为，自动处理 JavaScript 挑战，从而成功获取页面内容。 requests: 提供基础的 HTTP 请求功能，cloudscraper内部也依赖于它。 beautifulsoup4 (bs4): 强大的 HTML/XML 解析库。用于解析从网页抓取下来的 HTML 文档，方便我们通过 CSS 选择器或标签名来定位和提取所需的数据（如文章标题、链接、正文）。 markdownify: 将 HTML 内容转换为 Markdown 格式的工具。这对于知识归档非常有用，因为 Markdown 文件轻量、可读性强，且易于在各种平台（如 Obsidian, Notion, VS Code）中查看和编辑。 lxml: 作为BeautifulSoup的解析后端，相比默认的html.parser，lxml速度更快、容错性更好，能更高效地处理复杂的 HTML 结构。 提示：如果国内网络访问 PyPI 较慢，可以使用 -i 参数指定镜像源，例如：pip3 install -i https://mirrors.aliyun.com/pypi/simple/ cloudscraper \u0026hellip;\n步骤二：展示源代码 (export_csdn_cf.py) 并添加注释（字已经处理了） #!/usr/bin/env python3 # -*- coding: utf-8 -*- \u0026#34;\u0026#34;\u0026#34; CSDN 文章导出 – cloudscraper 硬刚 521 版 仅对抗 CF 免费 5 秒盾；遇到 Pro/Turnstile 请升级商业方案 \u0026#34;\u0026#34;\u0026#34; import os, time, re import cloudscraper from bs4 import BeautifulSoup import markdownify BLOG_USERNAME = \u0026#34;3x7hnic1ty83t4\u0026#34; # ← 你的用户名 OUTPUT_DIR = f\u0026#34;csdn_posts_{BLOG_USERNAME}\u0026#34; MAX_PAGE = 10000 # 先抓 10 页试试水 os.makedirs(OUTPUT_DIR, exist_ok=True) # 1. 创建 scraper 实例（默认破解 CF 免费盾） scraper = cloudscraper.create_scraper( browser={\u0026#34;browser\u0026#34;: \u0026#34;chrome\u0026#34;, \u0026#34;platform\u0026#34;: \u0026#34;linux\u0026#34;, \u0026#34;mobile\u0026#34;: False} ) # 2. 抓列表页（静态 HTML 里就有 40 篇） def list_articles(): articles = [] for page in range(1, MAX_PAGE + 1): url = f\u0026#34;https://blog.csdn.net/{BLOG_USERNAME}/article/list/{page}\u0026#34; print(f\u0026#34;[+] 拉取列表页 {page} {url}\u0026#34;) resp = scraper.get(url, timeout=15) if resp.status_code != 200: print(\u0026#34;[-] CF 可能升级了，返回:\u0026#34;, resp.status_code) break soup = BeautifulSoup(resp.text, \u0026#34;lxml\u0026#34;) links = soup.select(\u0026#34;h4 a[href*=\u0026#39;article/details\u0026#39;]\u0026#34;) if not links: print(\u0026#34;[=] 本页无文章，已到尽头\u0026#34;) break for a in links: articles.append((a.text.strip(), a[\u0026#34;href\u0026#34;])) time.sleep(2) print(f\u0026#34;[#] 共拿到 {len(articles)} 篇\u0026#34;) return articles # 新增：统一的文件名清洗函数（等效于你给的 shell 命令链） def sanitize_filename(fname): # Step 1: 替换空格、括号、逗号等为下划线，合并多个下划线 fname = re.sub(r\u0026#39;[ \\(\\),]+\u0026#39;, \u0026#39;_\u0026#39;, fname) fname = re.sub(r\u0026#39;_+\u0026#39;, \u0026#39;_\u0026#39;, fname) # Step 2: 去除首尾下划线 fname = fname.strip(\u0026#39;_\u0026#39;) # Step 3: 移除开头的 \u0026#34;原创\u0026#34; 字样（含换行符） fname = re.sub(r\u0026#39;^原创\\s*\u0026#39;, \u0026#39;\u0026#39;, fname, flags=re.MULTILINE) # Step 4: 删除所有换行符 fname = fname.replace(\u0026#39;\\n\u0026#39;, \u0026#39;\u0026#39;) # Step 5: 首尾空白和多余空格/下划线清理，中间多个空格/下划线变一个空格 fname = re.sub(r\u0026#39;^[ _]+|[ _]+$\u0026#39;, \u0026#39;\u0026#39;, fname) # 去首尾 fname = re.sub(r\u0026#39;[ _]{2,}\u0026#39;, \u0026#39; \u0026#39;, fname) # 多个空格/下划线→单空格 # Step 6: 移除 \u0026amp; 和 + fname = fname.replace(\u0026#39;\u0026amp;\u0026#39;, \u0026#39;\u0026#39;).replace(\u0026#39;+\u0026#39;, \u0026#39;\u0026#39;) # Step 7: 保留字母、数字、中文、点、横线、空格（Unicode 安全） fname = re.sub(r\u0026#39;[^\\w .-]\u0026#39;, \u0026#39;\u0026#39;, fname, flags=re.UNICODE) # Step 8: 再次清理因删除特殊字符后产生的多余符号 fname = re.sub(r\u0026#39;^[ _]+|[ _]+$\u0026#39;, \u0026#39;\u0026#39;, fname) fname = re.sub(r\u0026#39;_+\u0026#39;, \u0026#39;_\u0026#39;, fname).strip(\u0026#39;_\u0026#39;) # 最终防止为空 return fname or \u0026#34;untitled\u0026#34; # 3. 抓正文 def scrape_article(title, url): print(f\u0026#34;[*] {title}\u0026#34;) try: resp = scraper.get(url, timeout=15) soup = BeautifulSoup(resp.text, \u0026#34;lxml\u0026#34;) content = soup.select_one(\u0026#34;#content_views, #article_content, .htmledit_views\u0026#34;) if not content: print(\u0026#34; 找不到正文，跳过\u0026#34;) return md = markdownify.markdownify(str(content), heading_style=\u0026#34;ATX\u0026#34;) # 【关键修改】使用增强版文件名清洗 fname_base = re.sub(r\u0026#39;[\u0026lt;\u0026gt;:/\\\\|?*\u0026#34;\\\u0026#39;\\n]+\u0026#39;, \u0026#39;_\u0026#39;, title)[:100] # 初步过滤非法字符 cleaned_fname = sanitize_filename(fname_base) fname = f\u0026#34;{cleaned_fname}.md\u0026#34; # 防止重名冲突 counter = 1 final_path = os.path.join(OUTPUT_DIR, fname) original_fname = fname while os.path.exists(final_path): name_only = os.path.splitext(original_fname)[0] ext = \u0026#34;.md\u0026#34; fname = f\u0026#34;{name_only}_{counter}{ext}\u0026#34; final_path = os.path.join(OUTPUT_DIR, fname) counter += 1 with open(final_path, \u0026#34;w\u0026#34;, encoding=\u0026#34;utf-8\u0026#34;) as f: f.write(f\u0026#34;# {title}\\n\\n{md}\u0026#34;) print(f\u0026#34; 保存为: {fname}\u0026#34;) except Exception as e: print(f\u0026#34; 失败: {e}\u0026#34;) # 4. 主流程 def main(): articles = list_articles() for title, url in articles: scrape_article(title, url) print(f\u0026#34;[OK] 全部完成 → ./{OUTPUT_DIR}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() 步骤三：执行 python3 命令 在确保虚拟环境已激活且依赖安装完成后，执行以下命令运行脚本：\npython3 export_csdn_cf.py 步骤四：执行输出展示 脚本运行时，会在终端实时输出日志信息。一次成功的执行过程大致如下：\n(csdn-env) root@wanyan:/opt/csdn# python3 export_csdn_cf.py [INFO] 开始抓取用户 \u0026#39;3x7hnic1ty83t4\u0026#39; 的博客文章... [+] 正在拉取列表页 1: https://blog.csdn.net/3x7hnic1ty83t4/article/list/1 [+] 正在拉取列表页 2: https://blog.csdn.net/3x7hnic1ty83t4/article/list/2 [+] 正在拉取列表页 3: https://blog.csdn.net/3x7hnic1ty83t4/article/list/3 [+] 正在拉取列表页 4: https://blog.csdn.net/3x7hnic1ty83t4/article/list/4 [+] 正在拉取列表页 5: https://blog.csdn.net/3x7hnic1ty83t4/article/list/5 [+] 正在拉取列表页 6: https://blog.csdn.net/3x7hnic1ty83t4/article/list/6 [+] 正在拉取列表页 7: https://blog.csdn.net/3x7hnic1ty83t4/article/list/7 [+] 正在拉取列表页 8: https://blog.csdn.net/3x7hnic1ty83t4/article/list/8 [=] 本页未找到文章链接，可能是最后一页，停止抓取。 [#] 列表抓取完成，共发现 320 篇文章。 [INFO] 开始抓取文章正文... [*] 正在处理: 原创 PHP项目Kubernetes部署与Jenkins CI/CD流水线全栈实践指南 [✓] 已保存: ./csdn_posts_weixin_52315708/原创_PHP项目Kubernetes部署与Jenkins_CI_CD流水线全栈实践指南.md [*] 正在处理: 原创 docker-compose部署yapi [✓] 已保存: ./csdn_posts_weixin_52315708/原创_docker_compose部署yapi.md [*] 正在处理: 原创 PHP 项目容器化与自动化部署实践：从 Docker 改造到 Jenkins Pipeline 滚动更新 [✓] 已保存: ./csdn_posts_weixin_52315708/原创_PHP_项目容器化与自动化部署实践：从_Docker_改造到_Jenkins_Pipeline_滚动更新.md ... (后续文章处理中) [OK] 全部任务完成！文章已保存至 \u0026#39;./csdn_posts_weixin_52315708\u0026#39; 目录。 关键点说明： 脚本成功识别到用户共有 8 个有效的文章列表页，总计 320 篇。 每篇文章都经过了抓取和转换，并在终端显示了成功 ([✓]) 或失败 ([✗]) 的状态。 所有.md文件均已生成在./csdn_posts_weixin_52315708目录下。 步骤五：输出文件处理与命名规范化（python程序已经处理了，理论上这个已经不需要了，但是还是保留吧） 虽然脚本已经对文件名做了基础清理，但生成的文件名仍包含“原创”字样、多余的下划线 _ 和特殊符号，不够美观。我们可以使用一系列 rename 和 sed 命令进行深度清洗。\n# 进入输出目录 cd csdn_posts_3x7hnic1ty83t4 # 1. 将空格、括号、逗号等替换为下划线，并合并连续的多个下划线 rename -v \u0026#39;s/[ \\(\\),]+/_/g; s/__+/_/g; s/^_+//; s/_$//\u0026#39; *.md # 2. 移除文件名开头的 \u0026#34;原创\u0026#34; 字样及其后的空白符（包括换行） rename -v \u0026#39;s/^原创\\s*\\n?\\s*//\u0026#39; *.md # 3. 删除文件名中可能残留的换行符 (\\n) rename -v \u0026#39;s/\\n//g\u0026#39; *.md # 4. 终极规范化：使用 sed 进行精细调整 # - 去除首尾空格和下划线 # - 将多个连续的空格或下划线合并为一个空格 # - 移除 \u0026amp; 和 + 符号 # - 只保留字母、数字、空格、点(.)、连字符(-)和中文等Unicode字符 ls *.md | while read f; do new=$(echo \u0026#34;$f\u0026#34; | \\ sed -E \u0026#39;s/^[ _]+|[ _]+$//g; \u0026#39; \\ # 去首尾空格/下划线 \u0026#39;s/[ _]{2,}/ /g; \u0026#39; \\ # 多个空格/下划线变一个空格 \u0026#39;s/[\u0026amp;+]//g; \u0026#39; \\ # 移除 \u0026amp; 和 + \u0026#39;s/[^[:alnum:] _.\\-\\p{L}\\p{N}]//g\u0026#39;) # 仅保留字母数字、空格、点、横线、Unicode字符 # 如果新旧文件名不同，则执行重命名 [ \u0026#34;$f\u0026#34; != \u0026#34;$new\u0026#34; ] \u0026amp;\u0026amp; mv \u0026#34;$f\u0026#34; \u0026#34;$new\u0026#34; done 最终效果： 经过上述清洗，原始文件名： 原创_PHP_项目容器化与自动化部署实践：从_Docker_改造到_Jenkins_Pipeline_滚动更新.md 将被完美地重命名为： PHP 项目容器化与自动化部署实践 从 Docker 改造到 Jenkins Pipeline 滚动更新.md 这样处理后的文件名简洁、规范，便于管理和阅读。\n总结 本文通过一个完整的案例，展示了如何利用 Python + cloudscraper + Shell 的组合，实现对受反爬保护网站的内容采集与后期数据清洗。整个流程自动化程度高，具有很强的实用性和可复用性，是构建个人知识库的利器。\n原文链接: CSDN博客文章批量导出 作者: 完颜振江\n","permalink":"http://nb404.cn/posts/csdn%E5%8D%9A%E5%AE%A2%E6%96%87%E7%AB%A0%E6%89%B9%E9%87%8F%E5%AF%BC%E5%87%BA/","summary":"\u003ch3 id=\"脚本依赖环境安装指南\"\u003e脚本依赖环境安装指南\u003c/h3\u003e\n\u003cp\u003e以下是为运行 CSDN 博客导出脚本（如 \u003ccode\u003eexport_csdn_cf.py\u003c/code\u003e）而准备 Linux 系统环境所执行的一系列有效命令。这些命令主要用于安装  运行时、及其依赖库。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 1. 安装 Python 包管理工具 pip3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt install python3-pip -y\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 2. 安装文件传输和解压工具\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt -y install lrzsz                    \u003cspan style=\"color:#75715e\"\u003e# 提供 rz/sz 命令，用于终端文件上传下载\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt -y install zip unzip                \u003cspan style=\"color:#75715e\"\u003e# 用于处理 zip 和 unzip 格式的压缩包\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 3. 安装重命名工具\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt install rename                      \u003cspan style=\"color:#75715e\"\u003e# 强大的 Perl 脚本，用于批量重命名文件\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 4. 配置 Google Chrome 浏览器安装源 (使用清华镜像加速)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#    下载并添加 Google 的 GPG 公钥以验证软件包完整性\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#或者上传执行如下的命令\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# cat linux_signing_key.pub |sudo apt-key add -\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWarning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003esee apt-key\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e8\u003cspan style=\"color:#f92672\"\u003e))\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOK\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#    将清华镜像的 Chrome 源写入 APT 源列表\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/google-chrome/deb/ stable main\u0026#34;\u003c/span\u003e \u0026gt; /etc/apt/sources.list.d/google-chrome.list\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 5. 更新软件包索引并安装 Chrome 及其系统依赖\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt update                            \u003cspan style=\"color:#75715e\"\u003e# 同步最新的软件包列表\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 安装稳定版 Google Chrome\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 下载 \u0026amp;\u0026amp; dpkg -i去安装\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehttps://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 修复相关的依赖\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt --fix-broken install -y\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 6. 安装 Chrome 运行所需的底层库 (确保 headless 模式正常工作)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt install -y \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    wget \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    unzip \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    libxss1 \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    libappindicator1 \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    libindicator7 \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    fonts-liberation \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    libasound2 \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    libatk-bridge2.0-0 \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    libgtk-3-0 \u003cspan style=\"color:#ae81ff\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    libdrm-common\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 7. （可选）修复可能存在的依赖问题\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt --fix-broken install -y           \u003cspan style=\"color:#75715e\"\u003e# 如果之前的安装出现中断或依赖错误，此命令可尝试自动修复\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch4 id=\"说明\"\u003e说明：\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e虽然核心抓取脚本\u003ccode\u003eexport_csdn_cf.py\u003c/code\u003e使用的是\u003ccode\u003ecloudscraper\u003c/code\u003e，它不直接依赖浏览器，但如果您后续计划使用\u003ccode\u003eselenium\u003c/code\u003e或\u003ccode\u003eplaywright\u003c/code\u003e等基于真实浏览器的自动化工具来应对更复杂的反爬机制（如 Turnstile 验证码），那么安装 Chrome 是必需的。\u003c/li\u003e\n\u003cli\u003e此处列出的\u003ccode\u003elib*\u003c/code\u003e库是 Chrome 在无头（headless）模式下运行时常见的依赖项，能避免因缺少图形或音频库而导致的启动失败。\u003c/li\u003e\n\u003cli\u003e使用清华（TUNA）镜像可以显著加快在境内网络环境下下载 Chrome 的速度。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"步骤一安装-pip3-依赖\"\u003e步骤一：安装 pip3 依赖\u003c/h3\u003e\n\u003cp\u003e在开始编写和执行脚本之前，我们需要先配置好运行环境并安装必要的第三方库。\u003c/p\u003e","title":"CSDN博客文章批量导出"},{"content":" 开发板有哪些存储，存储如何测试 如何决定测试标准，和老板开发开会决定还是用行业标准 你觉得你有什么长处在测试方面 蓝牙如何测试，命令是什么 自动测试有哪些方面的应用 串口是什么协议，WiFi有哪些协议 WiFi如何测试 USB接口如何测试 固件如何测试 python深拷贝和浅拷贝区别 python进程通信有哪些 原文链接: ARM硬件测试面试题 作者: lixusocool\n","permalink":"http://nb404.cn/posts/arm%E7%A1%AC%E4%BB%B6%E6%B5%8B%E8%AF%95%E9%9D%A2%E8%AF%95%E9%A2%98/","summary":"\u003col\u003e\n\u003cli\u003e开发板有哪些存储，存储如何测试\u003c/li\u003e\n\u003cli\u003e如何决定测试标准，和老板开发开会决定还是用行业标准\u003c/li\u003e\n\u003cli\u003e你觉得你有什么长处在测试方面\u003c/li\u003e\n\u003cli\u003e蓝牙如何测试，命令是什么\u003c/li\u003e\n\u003cli\u003e自动测试有哪些方面的应用\u003c/li\u003e\n\u003cli\u003e串口是什么协议，WiFi有哪些协议\u003c/li\u003e\n\u003cli\u003eWiFi如何测试\u003c/li\u003e\n\u003cli\u003eUSB接口如何测试\u003c/li\u003e\n\u003cli\u003e固件如何测试\u003c/li\u003e\n\u003cli\u003epython深拷贝和浅拷贝区别\u003c/li\u003e\n\u003cli\u003epython进程通信有哪些\u003c/li\u003e\n\u003c/ol\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/149785300?spm=1001.2014.3001.5502\"\u003eARM硬件测试面试题\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"ARM硬件测试面试题"},{"content":"大家好，我是玄姐。\n▼最近直播超级多，预约保你有收获\n关于 Agent 的定义目前还没有形成共识，目前有3个代表性的定义：\n流行最广的是前 OpenAI 研究与安全副总裁 Lilian Weng 对 Agent 的定义：Agent = LLM + Planning + Tools + Memory。\n除此之外，LangChain 对 Agent 的定义为：使用 LLM 决定应用程序控制流的系统。\nOpenAI 对 Agent 的定义是：Agent 是能够代表用户自主完成任务的系统。\n尽管目前对 Agent 的定义还没形成共识，但是大家对 Agentic System（智能系统）基本的共识是：Agentic System 是一种有目标、基于环境的决策系统。与 LLM 最大的区别在于，Agentic System 可以与现实世界交互，从感知环境开始，做出决策并执行，影响环境，然后基于反馈调整，不断持续迭代循环。\n—1—\nAgentic System 架构设计剖析\n一个完整的 Agentic System 架构包含四个核心组成部分：\n感知：为大模型构建上下文信息。常见的方法包括检索增强生成（RAG），查询结构化数据（比如：数据库、网页内容）或者检索历史记录（比如：长短期记忆）。\n决策：本质上是 Planning 规划过程。可以通过规则引擎（Workflow）实现，也可以由大语言模型（LLM）驱动（自主 Agent），或者借助外部规划器。在设计时需要权衡泛化能力和准确性\u0026ndash;LLM 驱动的决策泛化能力强，但不确定性较高；而基于规则的工作流泛化能力较弱，但更可控。\n执行：通过调用工具来改变环境。包括 API 调用（比如：REST、RPC、SQL、函数调用）或与图形软件的集成（比如：Anthropic 的 Computer use）。\n反馈：用于评估和迭代的机制。反馈可以通过人工标注、规则或模型生成，更新可以是离线的或在线的。\n这个闭环构成了 Agent 的基础单元（building block）。复杂的 Agent 可以由多个小 Agent 组成，复杂业务逻辑大决策通常由一系列小型决策构成。\n—2—\n多 Agentic System 架构设计原则\n当多个 Agent 协同工作时，就构成了 Multi-Agent 系统。在设计 Multi-Agent 系统时，要避免过度拆分。每个 Agent 应该代表一个明确的业务决策点，并可以通过持续反馈进行优化。只有在单个 Agent 无法满足需求时，才考虑引入更多的 Agent。\n第一、借鉴分布式系统的思路，可以把 Agent 比作一台计算机：\nLLM（大语言模型）是计算机的CPU，负责处理和运算。 Context window（上下文窗口）是计算机的内存，用于临时存储信息。 向量数据库是计算机的硬盘，用于长期存储数据。 工具（Tools）是计算机上的程序，用于执行特定任务。 分布式系统主要解决以下三个问题：\n性能不足：单台计算机的计算或存储能力有限。 容错性：单个系统容易出现故障，需要多个系统协同工作以提高可靠性。 协作：不同团队负责不同的微服务，需要协同工作。 Multi-Agent 系统的设计原则与此类似：\n解决单次 LLM 调用智力不足的问题：当单个 Agent 无法处理复杂的任务时，可以引入多个 Agent 协同工作。 提高容错性：多个 Agent 协同工作可以提高系统的可靠性和稳定性。 促进协作：不同 Agent 可以负责不同的任务或决策点，实现更复杂的业务逻辑。 第二、Agentic System 架构演进 Multi-Agent 系统的设计应从单个 Agent 开始，只有在单个 Agent 无法满足需求时，才逐步过渡到多 Agent 架构。这种逐步扩展的方式有助于保持系统的简洁性和可维护性。\n—3—\n从单 Agent 到多 Agent 智能助手案例架构演进\n智能助手的演进遵循了从单 Agent 到 Multi-Agent 的路径：\n初始阶段：仅有产品问答模块，使用简单的 RAG（检索增强生成）技术。 技能扩展：添加多种技能，但用户需要手动切换。 意图识别：开发意图识别 Agent，但仍为单 Agent 架构。 多 Agent 体系：随着场景复杂化和多团队协作需求的增加，逐步过渡到多 Agent 体系。 除架构演进外，我们还进行了多项技术优化：\nRAG 优化：增加查询改写功能，提高系统的鲁棒性。用户不一定会提出完美的问题，通过查询扩展和改写，系统能够更好地处理各种输入变化。 知识图谱：引入 GraphRAG 技术，将产品知识问答的准确度从 76% 提升到 93%。对于算法实力一般但工程能力强的团队，知识图谱是模型后训练的实用替代方案。 强化学习：在经营分析场景中，将评价体系（如 AARRR 模型）转化为强化学习的奖励函数，实现模型的持续优化。 当然，我们也在经营分析场景中基于 SFT（监督微调）和强化学习进行微调。我们之前基于经营分析 Agent 构建的数据集和评价体系，天然地过渡到了 RL（强化学习）领域的环境和奖励函数的构建。我们之前评价一个经营建议好坏的一个重要指标是思考过程是否符合 AARRR 模型，现在在 RL 中，这个指标也成为了奖励函数之一。\n原文链接: 从单 Agent 到多 Agent 的案例落地实践 作者: CC 4.0 BY-SA\n","permalink":"http://nb404.cn/posts/%E4%BB%8E%E5%8D%95_agent_%E5%88%B0%E5%A4%9A_agent_%E7%9A%84%E6%A1%88%E4%BE%8B%E8%90%BD%E5%9C%B0%E5%AE%9E%E8%B7%B5/","summary":"\u003cp\u003e大家好，我是玄姐。\u003c/p\u003e\n\u003cp\u003e▼最近直播超级多，预约保你有收获\u003c/p\u003e\n\u003cp\u003e关于 Agent 的定义目前还没有形成共识，目前有3个代表性的定义：\u003c/p\u003e\n\u003cp\u003e流行最广的是前 OpenAI 研究与安全副总裁 Lilian Weng 对 Agent 的定义：Agent = LLM + Planning + Tools + Memory。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/e757333072c125bd0c54b950372b2945.png\"\u003e\u003c/p\u003e\n\u003cp\u003e除此之外，LangChain 对 Agent 的定义为：使用 LLM 决定应用程序控制流的系统。\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Agent Types\" loading=\"lazy\" src=\"/posts/images/0010fdccaae1d6b1280a256bd8539b5b.png\"\u003e\u003c/p\u003e\n\u003cp\u003eOpenAI 对 Agent 的定义是：Agent 是能够代表用户自主完成任务的系统。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/f3d9d42503f64bc7abdf1f12933895c8.png\"\u003e\u003c/p\u003e\n\u003cp\u003e尽管目前对 Agent 的定义还没形成共识，但是大家对 Agentic System（智能系统）基本的共识是：Agentic System 是一种有目标、基于环境的决策系统。与 LLM 最大的区别在于，Agentic System 可以与现实世界交互，从感知环境开始，做出决策并执行，影响环境，然后基于反馈调整，不断持续迭代循环。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/aff439c3a8dfb100cafb830831c99fe3.jpeg\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e\u003cem\u003e\u003cstrong\u003e—\u003cem\u003e1\u003c/em\u003e\u003c/strong\u003e\u003c/em\u003e—\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eAgentic System 架构设计剖析\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e一个完整的 Agentic System 架构包含四个核心组成部分：\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/daa60a90b24dccd313bbebb50b993dac.png\"\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e感知：为大模型构建上下文信息。常见的方法包括检索增强生成（RAG），查询结构化数据（比如：数据库、网页内容）或者检索历史记录（比如：长短期记忆）。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e决策：本质上是 Planning 规划过程。可以通过规则引擎（Workflow）实现，也可以由大语言模型（LLM）驱动（自主 Agent），或者借助外部规划器。在设计时需要权衡泛化能力和准确性\u0026ndash;LLM 驱动的决策泛化能力强，但不确定性较高；而基于规则的工作流泛化能力较弱，但更可控。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e执行：通过调用工具来改变环境。包括 API 调用（比如：REST、RPC、SQL、函数调用）或与图形软件的集成（比如：Anthropic 的 Computer use）。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e反馈：用于评估和迭代的机制。反馈可以通过人工标注、规则或模型生成，更新可以是离线的或在线的。\u003c/p\u003e","title":"从单 Agent 到多 Agent 的案例落地实践"},{"content":" 我系统是ubuntu18.04.6 LTS 执行以下命令： curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb sudo dpkg -i cloudflared.deb cloudflared tunnel login #这里会打开浏览器窗口登录cloudfare，我这里是之前绑定了域名，建议大家也绑定域名 cloudflared tunnel create vm1 #这里会生成下面所需的json文件 mkdir ./cloudflared \u0026amp;\u0026amp; cd cloudflared/ nano config.yaml #添加以下内容 tunnels: vm1 credentials-file: /home/lixu/.cloudflared/95b49dcc-XXXX.json protocol: http2 ingress: - hostname: vm.nb404.cn service: http://127.0.0.1:80 originRequest: disableChunkedEncoding: true noTLSVerify: true - service: http_status:404 cloudflared tunnel --config config.yaml route dns vm1 vm.nb404.cn #这句命令会给域名增加vm的dns记录 cloudflared tunnel --config ./config.yaml run vm1 #这里就可以访问了，大家记得改成自己的域名 enjoy\n原文链接: 使用cloudfare实现免费内网穿透 作者: CC 4.0 BY-SA\n","permalink":"http://nb404.cn/posts/%E4%BD%BF%E7%94%A8cloudfare%E5%AE%9E%E7%8E%B0%E5%85%8D%E8%B4%B9%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F/","summary":"\u003col\u003e\n\u003cli\u003e我系统是ubuntu18.04.6 LTS\u003c/li\u003e\n\u003cli\u003e执行以下命令：\u003c/li\u003e\n\u003cli\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecurl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo dpkg -i cloudflared.deb\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecloudflared tunnel login\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#这里会打开浏览器窗口登录cloudfare，我这里是之前绑定了域名，建议大家也绑定域名\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecloudflared tunnel create vm1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#这里会生成下面所需的json文件\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir ./cloudflared \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e cd cloudflared/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enano config.yaml\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#添加以下内容\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etunnels: vm1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecredentials-file: /home/lixu/.cloudflared/95b49dcc-XXXX.json\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eprotocol: http2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eingress:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - hostname: vm.nb404.cn\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    service: http://127.0.0.1:80\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    originRequest:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      disableChunkedEncoding: true\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      noTLSVerify: true\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  - service: http_status:404\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecloudflared tunnel --config config.yaml route dns vm1 vm.nb404.cn\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#这句命令会给域名增加vm的dns记录\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecloudflared tunnel --config ./config.yaml run vm1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#这里就可以访问了，大家记得改成自己的域名\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eenjoy\u003c/p\u003e","title":"使用cloudfare实现免费内网穿透"},{"content":" 先安装ubuntu18的版本，使用典型安装，因为它会自动安装open vm工具实现复制粘贴桌面自动大小功能，同时不要尝试手动安装open vm工具，我试过在ubuntu20+上面试过 没用。 输入相关信息 直接自动化一键安装。 重启后，执行以下命令升级系统，这个阶段可能需要等30min+ sudo apt upgrade sudo do-release-upgrade -c 重启 即可 24.5.19更新：\n缺点：snap install node 会导致nodejs无法使用，缺少依赖 原文链接: 解决ubuntu20+不能在vmare17复制粘贴的麻烦解决方案 作者: lixusocool\n","permalink":"http://nb404.cn/posts/%E8%A7%A3%E5%86%B3ubuntu20+%E4%B8%8D%E8%83%BD%E5%9C%A8vmare17%E5%A4%8D%E5%88%B6%E7%B2%98%E8%B4%B4%E7%9A%84%E9%BA%BB%E7%83%A6%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/","summary":"\u003col\u003e\n\u003cli\u003e先安装ubuntu18的版本，使用典型安装，因为它会自动安装open vm工具实现复制粘贴桌面自动大小功能，同时不要尝试手动安装open vm工具，我试过在ubuntu20+上面试过 没用。\u003cimg loading=\"lazy\" src=\"/posts/images/33f7da4551d70987c3d389e7068c9ead.png\"\u003e\u003c/li\u003e\n\u003cli\u003e输入相关信息 直接自动化一键安装。\u003c/li\u003e\n\u003cli\u003e重启后，执行以下命令升级系统，这个阶段可能需要等30min+\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003esudo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eapt\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eupgrade\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003esudo\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erelease\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eupgrade\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ec\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003col start=\"4\"\u003e\n\u003cli\u003e重启  即可\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/f4c2472908275cecb3c27b82727baa8c.png\"\u003e\u003c/p\u003e\n\u003cp\u003e24.5.19更新：\u003c/p\u003e\n\u003cp\u003e缺点：snap install node  会导致nodejs无法使用，缺少依赖  \u003c/p\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/139016176?spm=1001.2014.3001.5502\"\u003e解决ubuntu20+不能在vmare17复制粘贴的麻烦解决方案\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"解决ubuntu20+不能在vmare17复制粘贴的麻烦解决方案"},{"content":"\nnano ~/.bashrc export LC_ALL=en_US.UTF-8 export LANG=en_US.UTF-8 保存退出 ，重新登录终端让修改生效！\n原文链接: nano在centos7下中文乱码 作者: lixusocool\n","permalink":"http://nb404.cn/posts/nano%E5%9C%A8centos7%E4%B8%8B%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81/","summary":"\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/e451ca6f3e1c6d249a0905d23c2aedf0.png\"\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003enano\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e~\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/.bashrc\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eLC_ALL\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003een_US\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eUTF\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eLANG\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003een_US\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eUTF\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e保存退出 ，重新登录终端让修改生效！\u003cimg loading=\"lazy\" src=\"/posts/images/0a8761893e8b6c1320229ffabedfd1d5.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/f4c2472908275cecb3c27b82727baa8c.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/138995486?spm=1001.2014.3001.5502\"\u003enano在centos7下中文乱码\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"nano在centos7下中文乱码"},{"content":" 安全组设置： 一定要关闭本地代理才能访问，比如clash！ 原文链接: aws的linux其他端口无法访问问题 作者: lixusocool\n","permalink":"http://nb404.cn/posts/aws%E7%9A%84linux%E5%85%B6%E4%BB%96%E7%AB%AF%E5%8F%A3%E6%97%A0%E6%B3%95%E8%AE%BF%E9%97%AE%E9%97%AE%E9%A2%98/","summary":"\u003col\u003e\n\u003cli\u003e安全组设置：\u003cimg loading=\"lazy\" src=\"/posts/images/c6834a6d4afe437d4af29bbeb40b3a6e.png\"\u003e\u003c/li\u003e\n\u003cli\u003e一定要关闭本地代理才能访问，比如clash！\u003c/li\u003e\n\u003c/ol\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003chr\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/f4c2472908275cecb3c27b82727baa8c.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/138953071?spm=1001.2014.3001.5502\"\u003eaws的linux其他端口无法访问问题\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"aws的linux其他端口无法访问问题"},{"content":" sudo systemctl stop ollama sudo systemctl disable ollama sudo rm /etc/systemd/system/ollama.service sudo rm $(which ollama) sudo rm -r /usr/share/ollama sudo userdel ollama sudo groupdel ollama 我是用官方安装的，卸载比较麻烦\n建议 用 install ollama\n卸载也方便snap remove\n原文链接: linux的ollama卸载 作者: lixusocool\n","permalink":"http://nb404.cn/posts/linux%E7%9A%84ollama%E5%8D%B8%E8%BD%BD/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esudo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esystemctl\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estop\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eollama\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esudo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esystemctl\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edisable\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eollama\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esudo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erm\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eetc\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003esystemd\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003esystem\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eollama\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eservice\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esudo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erm\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e$\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ewhich\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eollama\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esudo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erm\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003er\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eusr\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eshare\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eollama\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esudo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euserdel\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eollama\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esudo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egroupdel\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eollama\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e我是用官方安装的，卸载比较麻烦\u003c/p\u003e\n\u003cp\u003e建议 用  install ollama\u003c/p\u003e\n\u003cp\u003e卸载也方便snap remove\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/138470183?spm=1001.2014.3001.5502\"\u003elinux的ollama卸载\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"linux的ollama卸载"},{"content":"查看网络：\ndocker network list 选择一个bridge网络，重新部署容器的时候加进去\u0026ndash; 1panel-network：\ndocker run -d -p 3001:8080 --network 1panel-network 这样容器就可以引入本机网络的或者其他端口，建议关闭\n原文链接: 解决docker容器不能问本机网络 作者: lixusocool\n","permalink":"http://nb404.cn/posts/%E8%A7%A3%E5%86%B3docker%E5%AE%B9%E5%99%A8%E4%B8%8D%E8%83%BD%E9%97%AE%E6%9C%AC%E6%9C%BA%E7%BD%91%E7%BB%9C/","summary":"\u003cp\u003e查看网络：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003edocker\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003enetwork\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elist\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/posts/images/e311d216d3223b5fe81b6ea1fcd6761b.png\"\u003e\u003c/p\u003e\n\u003cp\u003e选择一个bridge网络，重新部署容器的时候加进去\u0026ndash; 1panel-network：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#a6e22e\"\u003edocker\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erun\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3001\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e8080\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003enetwork\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003epanel\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003enetwork\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e这样容器就可以引入本机网络的或者其他端口，建议关闭\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e原文链接: \u003ca href=\"https://blog.csdn.net/lixusocool/article/details/138425922?spm=1001.2014.3001.5502\"\u003e解决docker容器不能问本机网络\u003c/a\u003e\n作者: lixusocool\u003c/p\u003e\n\u003c/blockquote\u003e","title":"解决docker容器不能问本机网络"},{"content":"IoTAutomationFramework_2.0 使用的自动化工具 概述 这是一个基于 Python 的 IoT 设备自动化测试框架，主要用于测试高通（Qualcomm）芯片平台的设备。\n核心自动化工具 1. ADB (Android Debug Bridge) ⭐⭐⭐⭐⭐ 主要工具，使用最广泛\n位置: Libs/Utilities/adb.py\n用途:\n设备连接和通信 执行 shell 命令 文件传输（push/pull） 设备重启 日志收集 使用示例:\nfrom Libs.Utilities.adb import adb # 执行命令 adb.run_cmd(\u0026#34;adb shell ls /data\u0026#34;, serial_number) # 推送文件 adb.push(local_path, remote_path, serial_number) # 拉取文件 adb.pull(remote_path, local_path, serial_number) # 重启设备 adb.run_cmd(\u0026#34;adb reboot\u0026#34;, serial_number) 特点:\n支持多设备（通过 serial_number 区分） 支持 ADB over WiFi 自动日志记录（发送和接收的命令） 2. UIAutomator2 ⭐⭐⭐⭐ UI 自动化工具\n库: uiautomator2 (简称 u2)\n用途:\nAndroid UI 元素定位和操作 点击、滑动、输入等交互 截图和屏幕录制 应用启动和管理 使用示例:\nimport uiautomator2 as u2 # 连接设备 d = u2.connect(serial_number) # 点击按钮 d(resourceId=\u0026#34;com.example:id/button\u0026#34;).click() # 输入文本 d(resourceId=\u0026#34;com.example:id/edit\u0026#34;).set_text(\u0026#34;Hello\u0026#34;) # 检查元素是否存在 if d(text=\u0026#34;Settings\u0026#34;).exists: d(text=\u0026#34;Settings\u0026#34;).click() # 滑动 d.swipe(100, 500, 100, 100) 应用场景:\nLAW (Linux Android Wear) 平台测试 UI 交互测试 设置配置 弹窗处理 3. SSH ⭐⭐⭐ 远程连接工具\n位置: Libs/Utilities/SSH/SSH.py\n用途:\nLinux 设备远程连接 执行 shell 命令 文件传输 使用场景:\nLE (Linux Embedded) 平台 LU (Linux Ubuntu) 平台 需要 SSH 访问的设备 4. Alpaca TAC ⭐⭐ 硬件控制工具\n库: alpaca.tac\n用途:\n硬件电源控制 设备重启（硬件级别） USB 切换 使用示例:\nimport alpaca.tac # 探测设备 ports = alpaca.tac.ProbeForDevices() # 电源控制 # 用于硬件级别的设备控制 5. GStreamer ⭐⭐⭐⭐ 多媒体处理工具\n用途:\n相机预览和录制 视频编码/解码 音频处理 多媒体管道测试 使用示例（通过 ADB 执行）:\n# 相机预览 gst-launch-1.0 qtiqmmfsrc camera=0 ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! waylandsink # 视频录制 gst-launch-1.0 qtiqmmfsrc camera=0 ! video/x-raw(memory:GBM),format=NV12 ! qtic2venc ! h264parse ! mp4mux ! filesink location=/data/video.mp4 配置文件: Plan/*/Config/Camera/TestCommands/*.json\n辅助工具和库 6. 其他 Python 库 日志和监控 logging - Python 标准日志库 threading - 多线程支持 subprocess - 进程管理 数据处理 json - JSON 配置文件解析 xml.etree.ElementTree - XML 配置解析 re - 正则表达式 网络和通信 requests - HTTP 请求（结果上传） socket - 网络通信 serial - 串口通信（调试 UART） 可视化 matplotlib - 数据可视化 Chart.js - HTML 报告图表（前端） 硬件接口 TACDev - TAC 设备驱动 win32api/win32con - Windows API（文件属性等） 测试框架架构 IoTAutomationFramework_2.0/\r├── TestEntrance.py # 测试入口\r├── Libs/\r│ ├── Utilities/\r│ │ ├── adb.py # ADB 封装\r│ │ ├── SSH/ # SSH 工具\r│ │ └── Utility.py # 通用工具\r│ ├── Tests/\r│ │ ├── BaseTestCase.py # 测试基类\r│ │ └── TestProcedure.py # 测试流程\r│ └── LogCatcher/ # 日志收集\r├── Case/\r│ └── Products/ # 产品测试用例\r│ ├── QCS8550_LE_1_0/\r│ ├── QRB5165_UBUN_2_0/\r│ └── ...\r└── Plan/ # 测试计划和配置\r├── LE/ # Linux Embedded\r├── LU/ # Linux Ubuntu\r└── LAW/ # Linux Android Wear 支持的平台 1. LE (Linux Embedded) 工具: ADB + SSH + GStreamer 芯片: QCS8550, QCS615, QCM6490 等 特点: 嵌入式 Linux 系统 2. LU (Linux Ubuntu) 工具: ADB + SSH + GStreamer 芯片: QRB5165 等 特点: Ubuntu 系统 3. LAW (Linux Android Wear) 工具: ADB + UIAutomator2 芯片: SW5100, SW6100, SDM429W 等 特点: Android Wear 系统，需要 UI 自动化 4. LA (Linux Android) 工具: ADB + UIAutomator2 芯片: QCS8245, QCS610 等 特点: Android 系统 测试类型 1. Stability 测试 Reboot 测试 Suspend/Resume 测试 长时间运行测试 2. 功能测试 Camera 测试（预览、录制、快照） Audio 测试（播放、录制） Video 测试（编解码） Connectivity 测试（WiFi、BT） Sensor 测试（IMU、GPS） 3. 性能测试 CPU/Memory 压力测试 并发测试 AI/ML 模型测试 4. 并发测试 多摄像头并发 WiFi + Audio + Camera + ML 并发 关键特性 1. 多设备支持 通过 serial_number 区分设备 支持 ADB over WiFi 支持 USB 和网络连接 2. 灵活的测试策略 Random - 随机执行测试用例 Sequence - 顺序执行 Iteration - 迭代执行指定次数 3. 完善的日志系统 自动收集 logcat 自动收集 kernel log (kmsg) 自动收集 tombstone/coredump 生成 HTML 测试报告 4. 后台测试支持 CPU/DDR 压力测试 并发测试 长时间稳定性测试 依赖安装 # 核心依赖 pip install uiautomator2 pip install requests # 可选依赖 pip install matplotlib pip install alpaca-tac # 如果使用 Alpaca 硬件 # ADB 需要单独安装 # 下载 Android Platform Tools # 添加到系统 PATH 总结 这个框架是一个混合型自动化测试框架，主要特点：\n以 ADB 为核心 - 所有平台都使用 ADB 作为主要通信工具 UI 自动化 - 使用 UIAutomator2 处理 Android UI 交互 多媒体测试 - 使用 GStreamer 进行相机和视频测试 硬件控制 - 使用 Alpaca TAC 进行硬件级别控制 跨平台支持 - 支持 Linux Embedded、Ubuntu、Android Wear 等多个平台 适用场景: IoT 设备、嵌入式系统、Android 设备的自动化测试，特别是高通芯片平台。\n","permalink":"http://nb404.cn/posts/lot-test/","summary":"\u003ch1 id=\"iotautomationframework_20-使用的自动化工具\"\u003eIoTAutomationFramework_2.0 使用的自动化工具\u003c/h1\u003e\n\u003ch2 id=\"概述\"\u003e概述\u003c/h2\u003e\n\u003cp\u003e这是一个基于 Python 的 IoT 设备自动化测试框架，主要用于测试高通（Qualcomm）芯片平台的设备。\u003c/p\u003e\n\u003ch2 id=\"核心自动化工具\"\u003e核心自动化工具\u003c/h2\u003e\n\u003ch3 id=\"1-adb-android-debug-bridge-\"\u003e1. \u003cstrong\u003eADB (Android Debug Bridge)\u003c/strong\u003e ⭐⭐⭐⭐⭐\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003e主要工具，使用最广泛\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e位置\u003c/strong\u003e: \u003ccode\u003eLibs/Utilities/adb.py\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e用途\u003c/strong\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e设备连接和通信\u003c/li\u003e\n\u003cli\u003e执行 shell 命令\u003c/li\u003e\n\u003cli\u003e文件传输（push/pull）\u003c/li\u003e\n\u003cli\u003e设备重启\u003c/li\u003e\n\u003cli\u003e日志收集\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e使用示例\u003c/strong\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e Libs.Utilities.adb \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e adb\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 执行命令\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadb\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erun_cmd(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;adb shell ls /data\u0026#34;\u003c/span\u003e, serial_number)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 推送文件\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadb\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epush(local_path, remote_path, serial_number)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 拉取文件\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadb\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epull(remote_path, local_path, serial_number)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 重启设备\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadb\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erun_cmd(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;adb reboot\u0026#34;\u003c/span\u003e, serial_number)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e特点\u003c/strong\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e支持多设备（通过 serial_number 区分）\u003c/li\u003e\n\u003cli\u003e支持 ADB over WiFi\u003c/li\u003e\n\u003cli\u003e自动日志记录（发送和接收的命令）\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"2-uiautomator2-\"\u003e2. \u003cstrong\u003eUIAutomator2\u003c/strong\u003e ⭐⭐⭐⭐\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eUI 自动化工具\u003c/strong\u003e\u003c/p\u003e","title":""}]