ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SLM与边缘计算驱动的虚拟Agent:Think与Memory过程设计与实践

SLM与边缘计算驱动的虚拟Agent:Think与Memory过程设计与实践 1. 背景为什么虚拟 Agent 需要“小模型 边缘计算”近几年大语言模型驱动的智能体Agent已经走出实验室开始出现在客服、办公助手、智能家居、工业巡检等场景中。常用做法是把所有对话、规划、工具调用都交给云端的大模型处理Agent 相当于一个“远程大脑的遥控器”。但真实项目落地时这种“一切放云端”的做法并不总是最优解。先看几个非常典型的实际问题成本不可控上下文一旦变长每次请求的 Token 消耗会成倍增加线上 Agent 跑一天下来费用不低。延迟不稳定用户一次提问Agent 内部往往要先“思考”再调用工具再“回答”多轮交互叠加后网络往返次数很多高并发下体验容易劣化。隐私数据出域企业内部场景中会议纪要、生产日志、个人健康信息等往往不允许直接发送到外部云服务。离线场景失效工厂车间、远洋船只、野外作业等环境下网络极不稳定云端方案直接不可用。于是行业里出现了一个自然的方向把一部分推理能力放到端侧或边缘侧设备上用规模较小的大语言模型Small Language ModelsSLM来承担思考、规划、记忆相关任务。围绕这个方向业界正在形成一套新的研究课题能否用 SLM 在边缘设备上支撑起虚拟 Agent 的 Think 过程和 Memory 过程本文的核心任务是拆解这个课题。内容分为三部分结合 SLM、Edge Computing、Think、Memory 四个关键词梳理这套技术方案的概念和体系。从工程角度给出一个边缘端虚拟 Agent 的最小可运行示例重点演示 Think 流程和 Memory 流程在本地怎么串联。整理一份可行的探索性评测框架帮助我们判断“某个 SLM 在边缘端做 Agent 是否够用”。文章适合三类读者正在做 Agent 应用开发的工程师、需要做端侧模型选型的技术负责人、对 SLM 与边缘计算感兴趣的研究者。读完你可以获得一个能直接运行的原型以及一套可扩展的评测思路。2. 四个关键词的技术拆解在进入代码之前先把标题中四个关键词一次讲清楚。这些概念在社区讨论中经常被混用不先厘清边界后续设计和改造都会很痛苦。2.1 SLMSmall Language ModelsSLM 是相对 LLM 而言的概念泛指参数量较小、可在受限硬件上运行的语言模型。不同资料的划分标准不一样但通常日常讨论中说的 SLM 指 0.5B 到 7B 左右的开源模型例如 Qwen 系列的小尺寸版本、Llama 3.2 小参数版本、Phi 系列等。SLM 的核心优势是部署门槛低量化后体积可以降到 1GB 以内甚至几百 MB。能被消费级 CPU、低端 GPU、树莓派级别的开发板运行。推理过程在本地完成数据不出设备。尤其要注意一点SLM 并不是“缩水版聊天机器人”它被设计成端侧 Agent 的推理核心后重点是完成工具调用、指令跟随、简单规划等任务模型本身的能力权重不应被夸大关键要看外围框架如何弥补短板。2.2 什么是边缘计算边缘计算指的是把计算任务放到靠近数据源头的设备或边缘节点执行而不是必须进入中心机房。Agent 场景中“边缘”可以有三个层次层级代表形态特点设备端手机、工控机、IoT 设备延迟最低算力最弱边缘网关园区服务器、路由节点、边缘盒子比设备稍强可统一管理边缘云靠近用户的区域数据中心资源充裕但离终端有一段距离在工程上SLM 究竟部署到哪一层取决于模型大小、业务对延迟的容忍度、设备的内存限制。研究标题中的“Edge-Computing”实际上涵盖上述多个层次不能简单等同于“塞进手机”。2.3 Think 过程与 Memory 过程的含义虚拟 Agent 的内部设计没有一个统一标准但基本可以抽象成几个模块感知输入、规划思考、调用工具、生成回答、保存状态。这里面的 Think 和 Memory 是两类关键过程。Think 过程大致包含理解用户目标输入的真实意图是什么。规划执行路径要不要调用工具调用什么工具。反思与校验前一步结果是否合理需不需要修正。约束条件判断哪些内容不能执行哪些信息不足。Memory 过程则负责让 Agent 具备持续工作的能力写入把对话中值得保留的事实存入短期或长期存储。召回下一轮对话时把相关信息放回提示词。更新原有记忆与新事实冲突时如何合并。遗忘超过容量的内容如何淘汰避免上下文爆炸。两者是协作关系Think 需要记忆提供上下文材料Memory 的内容又会依赖 Think 来判断哪些信息值得沉淀。如果只有 Think 没有 MemoryAgent 每一轮都是全新的“失忆者”如果只有 Memory 没有 Think记忆不过是堆积字符串无法驱动后续行动。2.4 为什么叫 Exploratory Evaluation论文标题中使用了 Exploratory Evaluation 这样的措辞这一定位在工程上也很重要。它意味着研究不是声称“SLM 方案一定超过云端大模型”而是在探索一个尚未成熟、存在大量未知因素的领域。对于普通开发者这也是一种启发尝试 SLM 边缘计算的 Agent 时我们很难照搬一套标准答案更没有统一 benchmark 来下结论。比较务实的做法是围绕任务集、评测指标、消融实验建立自己的评估方法。后面第 5 节会专门说明这一套评测框架怎么搭。3. SLM 边缘计算到底解决了什么这组组合的核心价值不是“用更差的模型替代大模型”而是让某些场景从不可用变成可用。把话说明白才能判断适合与不适合。三大价值如下。3.1 把 Agent 放到了延迟可控的位置智能体交互有一个特殊问题多次推理调用带来的累计延迟。假设一次完整工具调用涉及 3 次模型推理云端方案单次往返要 1.5 秒累计就是 4.5 秒以上用户体感会非常差。而本地 SLM 推理单次在几百毫秒到 1 秒之间节点之间也没有跨数据中心来回延迟低且稳定不会随着网络拥塞剧烈抖动。3.2 隐私边界内完成信息处理设备上的录音、摄像头画面、本地文档等可以在提取特征或生成摘要后只保留必要结果。命令和敏感数据不穿越网络这在企业内部和工业场景中有很强吸引力。尤其是那些对数据出境有合规要求的场景边缘部署几乎是唯一解。3.3 让 Agent 具备低成本试错能力云端的计费模型是按 Token 计算的因此很多有意思的探索想法会被成本挡住。比如让 Agent 在后台反复自我反思、模拟多种方案Token 数量一多成本立刻飙升。本地 SLM 的边际推理成本趋近于零开发者可以做更多高频率探索实验。这对研究和教育都非常有价值。但也要坦诚看待不足。SLM 在复杂推理、长上下文保持、指令遵循方面和当前主流云端大模型仍有明显差距。一个负责任的工程判断是它不是取代方案而是补齐方案。在一些核心问题上可能还是会采用云端大模型兜底再通过路由机制把简单任务导入边缘端 SLM。4. Think 与 Memory 在边缘端的设计原则4.1 Think 过程的三种常见形态边缘端 Agent 的 Think 过程不必机械模仿“思维链”。受限于上下文窗口和推理速度我们应该设计轻量级的思考协议。一种常见形态是“带格式的思考输出”。也就是说模型在生成最终回答之前先按固定前缀输出判断和行动框架代码负责解析。下面是一个示意THINK: 用户的问题需要调用计算工具 ACTION: calculator((23 7) * 3)这种输出并不仅仅是为了方便解析更重要的是输出结构本身的约束会让模型先做一步规划。第二种形态是“工具路由决策”。Agent 不需要从零开始规划所有步骤只需要判断当前请求适合调用编号 1-5 的哪个工具甚至可以直接输出“不调用工具”。这种二分决策比开放式规划鲁棒得多。第三种形态是“结果反思”。工具返回结果后框架让模型再回答一次结果是否符合预期如果不符合是否需要修正参数重试。注意这个反思步骤在边缘端不宜无限循环一般控制在 1-2 次内否则延迟会不可接受。4.2 Memory 过程的分层设计边缘设备的存储空间和上下文窗口都有限所以记忆系统必须区分层级短期记忆当前会话中最近的几轮内容通常放在内存队列里长度受上下文窗口限制。工作记忆生成当前回答时临时放入提示词的关键信息。长期记忆从对话中抽取出来的事实、偏好、任务结果需持久化到本地文件或轻量数据库。设计时最重要的原则是不是所有对话都要永久保存。以本地 Agent 为例值得进入长期记忆的信息通常包含用户明确表达过的偏好、与当前任务关键相关的结果、需要后续使用的临时标识。而寒暄、重复确认等噪声内容应当直接丢弃。4.3 边缘端的状态管理要“轻”云端 Agent 可以把整个对话历史重新塞进大上下文窗口边缘端不行。所以在边缘环境中的推荐做法是给每次推理设置最大输入长度超出则做截断。只把最近 N 条对话和记忆检索结果放入提示词。记忆召回使用简单的关键词匹配或向量检索不要让排队本身成为新的性能瓶颈。这三点会贯穿在后面的代码中。5. 如何做探索性评测做工程和技术选型时只凭一两个示例判断模型好坏非常不可靠。建议围绕四个维度搭建自己的评测框架。维度需要回答的问题常见指标任务成功率Think 规划是否正确、工具调用是否有效任务完成比例、工具调用准确率延迟单轮交互耗时是否可接受Think 耗时、完整会话总耗时记忆效果跨轮次的信息是否能被正确保存和召回记忆命中率、跨会话任务成功率资源占用设备内存和存储是否满足要求峰值内存、模型加载大小比较理想的做法是设计一个任务集同时准备带记忆与不带记忆两个版本运行多轮之后对比结果差异。这也就是基础的消融实验思想。第 6 和第 7 节中我会让一个最小 Agent 分别运行两轮任务先验证 Think 正确性再验证 Memory 对第二轮任务的影响。如果你手头有多台边缘设备、多个 SLM 模型可以按同样的代码逻辑跑一个对比矩阵。6. 实验环境与前置准备为了更好地演示如何“在边缘端用 SLM 驱动一个虚拟 Agent并评估 Think 与 Memory 过程”我们用一个轻量示例来实现。演示环境如下操作系统Ubuntu 22.04Windows 11 或 macOS 也可运行Python 版本3.10模型执行引擎Ollama本地运行 SLM 的最常见方式示例模型qwen2.5:1.5b 或 llama3.2:1b 均可外部依赖requests用于调用 Ollama 的 HTTP API下面先完成环境准备。# 安装 Ollama具体安装命令请以官网为准 curl -fsSL https://ollama.com/install.sh | sh # 下载一个适合边缘端的轻量模型 ollama pull qwen2.5:1.5b # 确认模型已经就绪 ollama list如果你的设备是 Apple Silicon 或者 WindowsOllama 官网也提供桌面安装包安装完成后在终端执行同一套命令即可。然后创建 Python 虚拟环境并安装 requestsmkdir slm-agent-edge cd slm-agent-edge python3 -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate pip install requests准备一个模型调用的核心工具文件。这里直接调用 Ollama 的本机 REST API避免引入过重 SDK# 文件路径slm_agent_edge/ollama_client.py import requests def generate(prompt: str, model: str qwen2.5:1.5b, max_tokens: int 256) - str: url http://localhost:11434/api/generate payload { model: model, prompt: prompt, stream: False, options: { num_predict: max_tokens, temperature: 0.2 } } response requests.post(url, jsonpayload, timeout120) response.raise_for_status() return response.json()[response]这段代码做了几件基础但重要的事将模型请求发送到本地 11434 端口。关闭流式输出便于同步处理结果。temperature 设置较低值 0.2让规划输出更稳定减少随机波动。不同 Ollama 版本的 API 细节可能存在差异如果后续调用报错第一反应是检查 /api/generate 的字段是否符合当前版本。7. 核心实验围绕 Think 与 Memory 构建小 Agent下面开始搭建一个最小虚拟 Agent。它的业务能力很简单但恰好可以覆盖 Think 与 Memory 两个过程使用计算器工具完成算术任务并把需要长期保存的结果写入记忆文件。整体流程如下用户提问 → 构建带记忆的 Prompt → SLM 生成思考与动作 → 提取 ACTION 并执行工具 → 生成最终回答 → 写入记忆 → 供下一轮使用。7.1 设计工具函数我们让 Agent 只拥有一个计算工具输入一个支持加减乘除和括号的表达式。为了安全在本地只允许数学运算字符不允许使用 import、eval 相关危险能力。# 文件路径slm_agent_edge/tools.py import re def calculator(expression: str): # 只允许数字、运算符、括号和空格 if not re.fullmatch(r[\d\s\-*/().], expression): raise ValueError(illegal expression) # 在受控表达式中执行计算 return eval(expression, {__builtins__: {}}, {})这里使用 eval 只是为了教学演示实际生产环境建议使用专门的计算表达式库并严格控制可输入字符集。7.2 Think 模块让模型输出结构化思考系统提示词是 Think 模块的核心。它要求模型按固定前缀输出推理过程和动作方便程序解析和执行。关键点有两个一是让模型做一步简短判断二是强制它输出可解释的 ACTION。# 文件路径slm_agent_edge/think.py import re SYSTEM_PROMPT 你是一个运行在边缘设备上的轻量智能体。 你只有一个名叫 calculator(expression) 的计算工具。 当用户提出问题时先按下面的固定格式输出你的思考 THINK: 你对问题的简短判断 ACTION: calculator(数学表达式) ANSWER: 给用户看的最终回答 注意 - 表达式只允许数字、空格、 - * / 和括号。 - 如果用户的问题不需要计算直接输出 THINK 和 ANSWER不输出 ACTION。 - 你的每一步思考和动作必须遵循输出格式不要额外解释格式本身。 def think(user_input: str, memory_context: str ) - dict: history if memory_context: history f本轮开始前你从长期记忆中读到了以下信息\n{memory_context}\n full_prompt SYSTEM_PROMPT \n history 用户问题 user_input from ollama_client import generate output generate(full_prompt) result { raw: output, think: None, action: None, answer: None } for line in output.splitlines(): if line.startswith(THINK:): result[think] line.replace(THINK:, ).strip() elif line.startswith(ACTION:): result[action] line.replace(ACTION:, ).strip() elif line.startswith(ANSWER:): result[answer] line.replace(ANSWER:, ).strip() return result这段代码中think 函数返回的 dict 已经足够清晰。实际使用中若模型输出格式不规范可能需要增加重试或恢复策略这一点会在第 8 节故障排查中详细展开。7.3 Memory 模块把需要保留的信息写入本地接下来做最基础的 Memory 实现使用 JSON 文件存储记忆条目。每一轮写入“上一轮计算结果”等事实下一轮开始时再读取所有记忆并按时间排序放回 Prompt 中。# 文件路径slm_agent_edge/memory.py import json import os MEMORY_FILE memory.json def save_memory(key: str, value: str): if os.path.exists(MEMORY_FILE): with open(MEMORY_FILE, r, encodingutf-8) as f: data json.load(f) else: data [] data.append({key: key, value: value}) # 简单限制长期记忆的条数防止无限增大 data data[-20:] with open(MEMORY_FILE, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) def load_memory_context() - str: if not os.path.exists(MEMORY_FILE): return with open(MEMORY_FILE, r, encodingutf-8) as f: data json.load(f) chunks [] for item in data: chunks.append(f{item[key]}: {item[value]}) return \n.join(chunks)从这个实现可以看到 Memory 过程的核心思想不是堆叠原始对话而是把每一轮值得长期保留的事实提炼出来以 key-value 形式永久保存。在本示例中key 可以设计为 “上一轮计算结果”。7.4 主循环把 Think、工具调用、Memory 串联起来主程序在一次用户输入中依次执行思考、动作解析、工具调用、回答生成、记忆保存。# 文件路径slm_agent_edge/agent.py from tools import calculator from think import think from memory import load_memory_context, save_memory import re def run_once(user_input: str, save_result: bool False) - dict: mem load_memory_context() result think(user_input, memory_contextmem) print( 模型原始输出 ) print(result[raw]) final_answer result[answer] action result[action] if action: match re.search(rcalculator\(([^)])\), action) if match: expr match.group(1).strip() value calculator(expr) if result[answer] is None: final_answer f计算结果为 {value}。 print(f 工具执行结果{value} ) if save_result and value is not None: save_memory(上一轮计算结果, str(value)) print(f 最终回答{final_answer} ) return { raw: result, tool_result: value if action else None, answer: final_answer } if __name__ __main__: print(第一轮请计算 (23 7) * 3) run_once(请计算 (23 7) * 3 的结果并告诉我。, save_resultTrue) print(\n第二轮基于记忆继续计算) run_once(刚才计算结果加上 10 等于多少, save_resultTrue)运行该脚本后预期流程如下第一轮用户请求触发 Think模型输出 ACTION: calculator((23 7) * 3)。工具执行得到 90主程序把“上一轮计算结果: 90”写入 memory.json。第二轮用户请求前load_memory_context 会自动把记忆拼进 Prompt。模型看到长期记忆中有上一轮结果 90于是输出 ACTION: calculator(90 10)最终得到 100。在 SLM 能力不稳定的情况下第二轮可能出现两种情况模型正确理解了记忆并调用 calculator(90 10)。模型忽略记忆或者从原始文本里误解析表达式导致结果不同。后者正是我们需要通过评测去发现的核心问题。7.5 运行与验证在项目目录下依次执行source venv/bin/activate python agent.py注意第一次运行需要确保 Ollama 服务已在后台启动模型已下载完成。如果发现输出格式漂移可以多运行几次也可以调整 temperature 或更换模型。8. 评测扩展如何量化 Think 与 Memory 的效果前面那个最小 Agent 可以用来自我验证但它还不足以得出可靠的结论。为了更贴近“探索性评估”的目标建议把运行方式调整为批量评测。首先准备一组任务比如编号输入期望动作依赖记忆T1计算 (1 2) * 4calculator((1 2) * 4)否T2计算 10 20calculator(10 20)否T3在上一步基础上再加 5calculator(35 5)是然后用评分脚本逐条执行统计下列指标Think 格式合规率输出中 THINK、ACTION、ANSWER 是否齐全。工具调用准确率实际 ACTION 是否与期望动作一致这个指标不必要求表达式字符串一字不差可以对比计算结果。任务完成率最终答案与期望结果是否一致。Memory 生效次数把带记忆版本和不带记忆版本分别运行比较第二轮成功率差。这里的关键是记录每一轮状态并按指标汇总。下面给一个非常轻量的离线评测脚本示例。# 文件路径slm_agent_edge/evaluate.py from agent import run_once from memory import save_memory cases [ {input: 请计算 (1 2) * 4, expected: 12, save: True}, {input: 请计算 10 20, expected: 30, save: True}, {input: 在上一步结果基础上加 5, expected: 35, save: True} ] def evaluate(): total 0 success 0 for case in cases: total 1 result run_once(case[input], save_resultcase[save]) tool_value result.get(tool_result) if tool_value is not None: try: # 兼容整数与浮点结果比较 success_flag abs(float(tool_value) - float(case[expected])) 1e-6 except (TypeError, ValueError): success_flag False else: success_flag False if success_flag: success 1 print(f用例通过{case[input]}) else: print(f用例失败{case[input]}期望 {case[expected]}工具结果 {tool_value}) print(f任务完成率{success}/{total} {success / total:.2%}) if __name__ __main__: evaluate()运行这个脚本前建议先清空 memory.json以保证每轮之间的记忆状态可预期。测试完成后如果想要做带记忆与不带记忆的对比可以把 agent.py 中 load_memory_context 的注入开关关掉重新执行一遍脚本观察任务完成率下降幅度。这种实验方式依然朴素但已经具备一个探索性评测的最小闭环任务集 → 执行 → 指标统计 → 消融对比。市面上一篇正经的“SLM Memory 效果评估”论文本质上也是这个流程的放大版只是任务集更复杂、参与模型更多、评测工具更严谨而已。9. 常见问题与排查思路在本地运行上述实验时最容易遇到下面几类问题这里做一份排错清单。问题现象常见原因解决思路Ollama 接口报 404 或字段错误Ollama 版本 API 变化查看本地版本的 API 文档确认接口路径和字段名模型输出没有 ACTION 行SLM 指令遵循能力弱降低 temperature 到 0.1 或 0.2简化系统提示词适当增加示例工具执行报 illegal expression模型生成的表达式含非法字符在 Think 模块中尽量让模型只生成数字与括号或修改工具函数容忍部分换行第二轮回答错误memory.json 没有被正确写入或没有加载检查文件是否生成检查 load_memory_context 返回内容是否为空模型陷入多轮反思响应极慢试错循环过多在主循环中限制 Think 次数不超过 1-2 次不要把反思和工具调用混在同一轮内存占用过高本地模型参数量或上下文窗口设置过大改用更小的量化版本调整 num_ctx 参数关闭 stream 时注意内存释放遇到模型输出格式漂移时最有效的方法不是换一个 Prompt而是先在系统提示词中给一个“输入输出示例”让模型照格式生成。这个做法看似简单但对 SLM 特别有效。10. 工程落地的最佳实践从原型走向生产环境时下面几个经验值得标记。10.1 Think 输出要能被程序校验不应该信任模型百分之百遵循 JSON 输出格式。推荐的做法是让模型先输出带前缀的文本再用正则或状态机解析。解析失败时不直接报错而是将“thinking”重试一次。更进阶的做法是构建一个自我反思循环第一次工具执行后让模型回答“结果是否可信是否需要重跑”。这一步能明显提升成功率但要严格控制最高循环次数。10.2 Memory 存储需要版本化和可清理生产环境的 memory.json 很容易因为长期运行变得混乱。建议至少增加这些设计每条记忆带时间戳。相同 key 的新值要能覆盖旧值而不是无限追加。提供独立的清理脚本定期删除无效和过期记忆。必要时对记忆做分层路由短期记忆放内存长期记忆放数据库。10.3 建立“可回退”机制边缘设备上的部署通常要面对不稳定的模型行为。一个稳妥的策略是保留云端的兜底通道普通请求走本地 SLM遇到高复杂度任务或本地模型低置信度场景时再把请求转发到能力更强的云端模型。这种混合路由机制在实际产品里比“纯 SLM”更容易交付。10.4 评估与监控要提前埋点既然目标是评测 Think 和 Memory 的效果建议在代码中为每一轮记录原始输入与输出。解析后的 Think / Action / Answer。工具调用耗时。记忆命中条目。最终是否成功。把这些字段输出为结构化日志后续可以方便地汇总指标、定位失败样本。生产系统还可以将这些日志接入监控大盘随时观察 Agent 的效果随时间的变化。10.5 性能与成本的均衡选型时并不是模型参数越小越好。对于边缘 Agent 来说模型需要满足两个下限一是能稳定跟随机器的指令格式二是能处理目标工具的参数组合格式。在这个前提下再选择尽可能小的参数版本才能把延迟和内存压到合理范围。如果你需要快速跑通整个流程并观察效果建议先尝试 qwen2.5:1.5b 这类中文能力均衡的小模型确认业务方向可行后再针对自己的目标设备做量化和性能测试。结语回到这篇文章的起点虚拟 Agent 的落地不一定只有“大模型 云端”这一条路。SLM 与边缘计算的组合能让 Agent 实现低成本、低延迟、保护隐私地运行在用户设备附近而 Think 与 Memory 过程的合理设计决定了这种 Agent 是否能真正连贯、可靠地工作。这篇文章中我们通过对任务流程的反复测量发现哪怕就是一个“记住上一轮计算结果并继续计算”这样的小任务带 Memory 与不带 Memory 的 Agent 差异也会非常明显。真实项目中记忆系统的差异会在几十轮工作后几何级放大。建议你现在就打开终端把第 6、7 节的代码跑一遍体验一次 SLM 边缘 Agent 的“思考”与“记忆”全流程然后回到你手头的业务里去寻找一个最合适的落点。
返回列表