首页 文章 精选 留言 我的

精选列表

搜索[虚拟互动空间],共10007篇文章
优秀的个人博客,低调大师

AgentScope第17式·洞府空间

# AgentScope第17式·工作区 人设写在 Java 里的那一天,就注定了改一句话要发一次版。 ```text [读者] 已经跑通数字人 Demo 的 Java 后端工程师 [痛点] 数字人身份、边界、知识、MCP 配置全硬编码在 Java 里 [现在读] 第16式之后 Agent 能跑了,但配置还没归位 [读完] 能把 Persona 与配置迁进 Workspace,并说清它和 AgentState 的区别 ``` ```text [旧方案] persona / 业务边界 / MCP 配置写死在 Java 常量与配置类里 | v [新需求] 改 AGENTS.md 就能换身份换规则,不改一行 Java | v [冲突] Workspace 是磁盘上的长驻资产,AgentState 是单次会话的运行态 | v [后果] 分不清这两层,就会出现改了文件不生效、或误改状态把既有会话搞乱的怪事 ``` 我是老李,这几年一直在做 Java 后端的 AI 化改造。前面十六式,我们把最小交互数字人从 Spring Boot + MySQL 一路做到 Harness,Agent 能跑、Tool 能调、状态能存。 但每加一个客户,我们都要复制一份代码、改几个常量、重新打包发版。第二个客户来的时候,产品经理在群里问:能不能让运营自己在后台把开场白和身份描述改了,别每次都排期后端? 这句话把一个被忽略很久的问题顶到了台面上:数字人的身份,到底属于代码,还是属于数据? 如果继续写在 Java 里,改一句话就是一次发版。 如果迁到文件里,新的问题马上来了:文件改了,正在跑的会话要不要跟着变? 选择错了会怎样?把 Workspace 当成热更新配置中心,或者把 AgentState 当成配置存储,两条路都会在真实项目里翻车。 # 01、故事 第二个客户是连锁门店,要一个品牌数字人迎宾。需求很朴素:品牌标题、主题色、背景图、开场白、结束语各一套,身份描述换成门店导购口吻,可用工具只保留门店查询和预约,其他通用工具全部禁掉。 我们的现状是:chapter/16 分支上,ProjectConfig 是一堆 Java 常量,systemPrompt 由一个 SystemPromptBuilder 拼字符串,工具注册写在一个 @Configuration 里,MCP server 地址散落在 application.yml 的三个 profile 里。 任务是:在不复制代码库、不新建一个微服务的前提下,让第二个客户换一套身份与规则。 第一版我们走的是最省事的路:加一个 application-store.yml,把该客户的开场白、标题、tool 白名单塞进去,用 Spring Profile 切。当天跑通了,运营也确实不用等后端了。 然后变化来了。运营说,他们想试三种开场白,当天轮流投放,还希望顺手把知识库目录换一版。我们要么给三个 profile,要么把文案再往 Java 里搬一点。 到这里,冲突已经很清楚了:我们不是缺一个配置项,我们缺的是把身份、边界、知识、工具这些长驻资产,和一次会话的运行状态分开存放的层级。 > 一行代码一句词 > 一次发版一身皮 > 若要千人千面走 > 先问身份归谁管 # 02、问题 旧方案失效的路径很典型。第一阶段用 Java 常量,改文案要改代码;第二阶段用 Spring Profile,改文案不用改代码,但每来一个客户就多一个 profile,yml 越来越长,工具白名单、MCP 地址、开场白混在一份文件里,没人说得清哪个字段属于身份、哪个属于部署环境。 业务影响是两个:交付周期被后端排期绑住;运营的实验能力被冻结,他们想改的其实是内容资产,却要等一次发布。 技术表现有三个可观察点: 第一,同一份身份描述在 Java、yml、数据库项目表里出现三次,改一处忘一处; 第二,工具可见性靠 if-else 拼,新增一个 MCP server 要动 Java; 第三,知识入口没有约定,导购知识是塞进 systemPrompt 的长文本,改一次就要重启。 本篇的完成标准,我给自己定了四条: 改 AGENTS.md 后不去碰任何 Java 代码,重启进程后数字人身份与规则改变,新 Session 行为符合预期,既有 Session 行为在文档里被明确说清; 业务边界、知识入口、MCP 配置都有固定落点,不再散落在 yml 与 Java 之间; 加载失败时有明确报错,不是静默降级成默认人设; 能说清 Workspace 与 AgentState 各自负责什么,并能在代码里指出边界。 > 改文案要排期 > 换身份要发版 > 配置散落三处 > 无人能说全貌 # 03、原理 Workspace 是 Agent 在磁盘上的长驻资产目录,AgentState 是单个会话的运行状态。这是本篇唯一必须记住的一句话。 官方把 Workspace 的目录契约写在 agentscope-java 仓库的文档里,固定版本路径是 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/docs/v2/zh/docs/harness/workspace.md ,里面约定的角色大致是:AGENTS.md 放身份与规则,MEMORY.md 放长期记忆入口,memory/ 放记忆文件,knowledge/ 放检索资料,skills/ 放技能定义,subagents/ 放子 Agent 定义,tools.json 放工具与 MCP 配置。具体字段以该版本文档为准,本文不逐项抄写。 AgentScope Java 的 Harness,是 Agent 的运行外壳,负责生命周期、会话、状态与工作区加载。WorkspaceManager 位于 harness 模块,v2.0.3 的源码入口是 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/agentscope-harness/src/main/java/io/agentscope/harness/agent/workspace/WorkspaceManager.java ,本文涉及框架行为时以该类与同目录实现为准,不靠类名猜行为。 第一个反直觉判断是:Workspace 不是配置中心。它没有推送,没有变更通知,没有灰度。它就是一个目录契约。Agent 什么时候读它、读完缓存在哪、下次要不要重读,全都是宿主代码的责任。把它当 Nacos 用,一定会失望。 第二个反直觉判断是:把身份迁到文件,最大的风险不是读不到,而是读到了旧的。很多实现会在 Session 创建时把 systemPrompt 固化成一份快照,之后无论文件怎么改,这个会话都用旧的那份。这不是 Bug,这是会话一致性的代价。 第三个反直觉判断是:AgentState 越像配置,出事越快。会话状态可以存消息、可以存临时变量,但不该存身份定义。一旦你把身份塞进状态,它就会随会话被序列化、被恢复、被复制,最后出现同一个项目两种人格。 > 文件不是配置 > 状态不是记忆 > 一次读取定稿 > 生命周期分开 # 04、架构 ```text [输入] Web 运行页 /run/{projectId} 发起会话 | v [模块] Realtime Bridge -> AgentScope Harness | v [资产] workspace/{projectId}/ AGENTS.md、MEMORY.md、knowledge/、skills/、subagents/、tools.json | v [处理] Workspace 加载器读取资产 -> 组装 systemPrompt 与 Tool 配置 -> 创建 Agent | v [状态] AgentState 承载本次会话的消息与运行态(与 Workspace 不同层) ``` 边界很清楚。LiveKit 只管 WebRTC 房间与实时音视频数据,Realtime Bridge 只做媒体与消息适配,AgentScope Java 负责推理、Tool、状态,Workspace 负责磁盘上的长驻资产,MySQL 只管业务数据:项目、配置项、会话记录。 收益有三个:身份与规则从代码变成可运营资产;工具与 MCP 配置有统一入口;多客户共用一套 Java,靠目录隔离而不是靠分支隔离。 代价也有三个:编译期对配置的正确性保证没了,错误从编译期挪到运行期;多了一套目录契约与加载逻辑要维护;Workspace 与 AgentState 的边界一旦没画清,会出现改了不生效这类困惑。 适用条件是:多个数字人项目共用一个后端,或者身份与规则会被非开发人员频繁调整。 不适用条件是:只有一个数字人、身份几乎不变、改动频率低于发版频率。这种场景下,把 AGENTS.md 也塞进 jar 里,和写 Java 常量没有本质区别,只是把字符串换了个文件。 > 资产落磁盘 > 状态留内存 > 边界画一条 > 各归各的位 # 05、实战一次 环境与版本:教程基线 AgentScope Java v2.0.3,JDK 17 以上,Maven 构建;教程仓库 https://github.com/lifuchun522/agentscopepractice ,本章分支 chapter/17-workspace,从第16式分支继续创建。写作当天官方 Releases 页面的最新正式版可能与基线不同,若你的版本更高,先按官方文档核验 Workspace 目录契约是否变化。 第一步,建立目录。放在项目根之外的独立目录,方便运营直接改: ```text workspace/ digital-human-a/ AGENTS.md MEMORY.md memory/ knowledge/ skills/ subagents/ tools.json ``` AGENTS.md 里写身份、语气、业务边界、拒答规则;tools.json 里写允许的工具与 MCP server;knowledge/ 放门店资料;skills/、subagents/ 本章先留空目录,留给后续章节填充。 第二步,定义一个只承载资产的对象。它不参与会话,只描述一次加载的结果: ```java package com.example.digitalhuman.workspace; import java.nio.file.Path; import java.util.List; public record WorkspaceAssets( Path root, String agentsMd, String memoryMd, List knowledgeFiles, List skillFiles, List subagentFiles, String toolsJson) { } ``` 第三步,写加载器。这里有两个必须做对的地方:projectId 不能逃出 workspace 根目录,缺失的文件要区分是空还是错。 ```java package com.example.digitalhuman.workspace; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.stream.Stream; public final class WorkspaceLoader { private final Path workspaceRoot; public WorkspaceLoader(Path workspaceRoot) { this.workspaceRoot = workspaceRoot.toAbsolutePath().normalize(); } public WorkspaceAssets load(String projectId) { Path root = workspaceRoot.resolve(projectId).normalize(); if (!root.startsWith(workspaceRoot)) { throw new IllegalArgumentException("projectId escapes workspace root"); } if (!Files.isDirectory(root)) { throw new IllegalStateException("workspace directory not found: " + root); } return new WorkspaceAssets( root, readIfExists(root.resolve("AGENTS.md")), readIfExists(root.resolve("MEMORY.md")), listNames(root.resolve("knowledge")), listNames(root.resolve("skills")), listNames(root.resolve("subagents")), readIfExists(root.resolve("tools.json"))); } private String readIfExists(Path file) { return Files.isRegularFile(file) ? read(file) : ""; } private String read(Path file) { try { return Files.readString(file, StandardCharsets.UTF_8); } catch (IOException e) { throw new UncheckedIOException(e); } } private List listNames(Path dir) { if (!Files.isDirectory(dir)) { return List.of(); } try (Stream stream = Files.list(dir)) { return stream.filter(Files::isRegularFile) .map(p -> p.getFileName().toString()) .sorted() .toList(); } catch (IOException e) { throw new UncheckedIOException(e); } } } ``` 第四步,把 AGENTS.md 变成 systemPrompt 的主体,把 tools.json 交给工具注册环节,而不是在 Java 里写死: ```java public String buildSystemPrompt(WorkspaceAssets assets) { StringBuilder sb = new StringBuilder(); sb.append(assets.agentsMd()); sb.append(System.lineSeparator()); if (!assets.knowledgeFiles().isEmpty()) { sb.append("可用知识文件:") .append(String.join("、", assets.knowledgeFiles())) .append(System.lineSeparator()); } return sb.toString(); } ``` 第五步,启动与验证。启动前把 AGENTS.md 写成门店导购口吻,启动后用运行页发一句话。 以下为预期结果,未在当前环境实测:Agent 回复应当使用门店导购口吻;把 AGENTS.md 改成另一个身份并重启进程后,新 Session 应当使用新身份;不重启进程、只改文件时,行为取决于你的缓存与加载策略,这正是下一章要处理的部分。 > 目录先定契约 > 文件再定身份 > 代码只做加载 > 不掺一句人设 # 06、排查 第一条证据链,关于改了文件不生效。 现象:改完 AGENTS.md,重启进程,运行页里正在进行的那个会话仍然是旧人设,新开的会话是新设。 怀疑:第一反应是缓存没刷新,于是去检查加载器。 检查:在 WorkspaceLoader 的 load 方法入口打日志,确认每次会话创建时文件都被重新读取,日志里也确实打印了新内容。 证据:日志显示加载到了新人设,但对话输出仍是旧口吻,说明问题不在读盘,而在读完之后被固化在了会话侧。 根因:Workspace 资产在 Session 创建时被组装进 systemPrompt,并随会话保留。既有会话不重读资产,这是会话一致性的设计结果,不是加载器的 Bug。 修复:不要把既有会话重读当成默认行为。明确两件事,新 Session 使用新资产,既有会话保持原样;如果确实需要运营当天切换人设,就提供显式的会话重建入口,而不是偷偷热替换正在进行的对话。 **错误尝试:** 有人提议直接去改 AgentState 里已存在的 systemPrompt 字段,把新人设塞进去,让当前会话马上换人设。这个做法是错的,原因有两个:一是 AgentState 是运行态,它会在后续轮次被重新组装或被覆盖,改了不一定在下一轮还生效;二是中途换人设会污染已经发生的对话历史,模型会看到前后不一致的指令,输出更容易跑偏。 第二条证据链,关于 tools.json 里的 MCP server 没注册。 现象:tools.json 里加了门店查询的 MCP server,运行页里数字人却说没有这个能力。 怀疑:JSON 写错了,或者字段名不对。 检查:把 tools.json 单独用 JSON 解析器校验,格式合法;再检查日志,发现加载器打印的 server 数量是 0。 证据:日志里打印的文件路径是相对路径,而进程的工作目录是项目根目录,不是 workspace 目录,所以 tools.json 是从一个不存在的位置读的,readIfExists 返回了空字符串,静默降级。 根因:相对路径的解析基准不统一。Workspace 的目录约定是以 workspace 根为基准,而 Java 进程的默认工作目录是启动目录,两者不一致。更糟的是我把缺失当成空处理,掩盖了错误。 修复:一是所有相对路径统一以 workspaceRoot 为基准解析;二是 AGENTS.md 缺失时报错而不是空字符串,tools.json 缺失可以容忍但必须打警告。 上游贡献判断:这两个现象我目前只在自有宿主代码里复现,尚未在官方最小 Demo 中复现,v2.0.3 与 main 的 WorkspaceManager 具体行为需按源码核验,也未在官方 Issues 中检索到对应条目。因此现在只能记录为候选,不能写成上游问题。 > 先看读没读 > 再看存没存 > 别怪框架慢 > 多半是基准 # 07、优化 基于第06章的两条证据,形成 V2。第一处修改是路径解析:新增一个解析器,把相对路径统一锚定到 workspace 根。 ```java package com.example.digitalhuman.workspace; import java.nio.file.Path; public final class WorkspaceResolver { private final Path workspaceRoot; public WorkspaceResolver(Path workspaceRoot) { this.workspaceRoot = workspaceRoot.toAbsolutePath().normalize(); } public Path resolve(String projectId, String relative) { Path resolved = workspaceRoot.resolve(projectId).resolve(relative).normalize(); if (!resolved.startsWith(workspaceRoot)) { throw new IllegalArgumentException("path escapes workspace root: " + relative); } return resolved; } } ``` 第二处修改是区分缺失与为空,并加显式校验。AGENTS.md 缺失属于致命错误,直接抛出并带路径;knowledge/、skills/、subagents/ 为空属于正常状态;tools.json 缺失打警告。 第三处修改是加载时机与缓存策略。给 WorkspaceAssets 加一个基于文件修改时间的指纹,宿主可以在会话创建时决定沿用缓存还是重读: ```java public record WorkspaceSnapshot(WorkspaceAssets assets, long fingerprint, long loadedAtMillis) { public boolean isStale(long currentFingerprint) { return currentFingerprint != fingerprint; } } ``` 指纹由 AGENTS.md、MEMORY.md、tools.json 的 mtime 与各目录文件列表拼接而成。注意这不是热更新:它只是让宿主有机会知道文件变了,要不要让正在进行的会话换人设,仍然是一个产品决策,不是技术默认值。 新行为是:新 Session 一定使用最新资产;既有 Session 保持创建时的资产;文件被改动时日志里能看到指纹变化,运营改完文案可以在管理端点一下重建会话,而不是靠后端重启。 验证方法也很直白:改 AGENTS.md,观察日志指纹变化;开新会话,确认新口吻;在旧会话里继续说话,确认它仍使用旧口吻且不报错。 > 路径锚一处 > 缺失分两级 > 指纹看得见 > 切换由人定 # 08、演进 ```text [同一输入] 让数字人换一套身份、边界与工具配置 | +--[V1] Persona / 边界 / MCP 分散在 Java 常量与多份 yml | 代价:改文案要发版,多客户靠 profile 与分支隔离 | +--[V2] Persona / 边界 / 知识 / MCP 落在 workspace/{projectId}/ | 代价:多一套目录契约、加载器、校验与缓存策略 | [Trade-off] 得到:身份与规则成为可运营资产,Java 只剩加载与执行 失去:编译期对配置正确性的保证,错误从编译期挪到运行期 适用:多数字人共用一套后端,身份与文案会被非开发人员频繁调整 不适用:单数字人、身份几乎不变、改一次比发一次版还慢 ``` 正确性上,V1 的配置来源分散在三处,容易出现改一处漏一处;V2 的资产只有一个落点,代价是运行期校验必须补上。 稳定性上,V1 的问题暴露在发布之后,影响面是全部客户;V2 的问题暴露在单个项目加载时,影响面收敛到一个 workspace。 复杂度上,V1 简单,但复杂度转移到了人脑;V2 多了一个加载器与一层约定,换来的是可运营与可审计。 成本上,V1 的隐性成本是每次改文案的排期;V2 的显性成本是一次性的加载器开发与后续的目录治理。 适用范围上,只有在你确定要长期养多个数字人时,V2 才划算。 遗留问题有三个:Workspace 与数据库里的项目配置谁来当权威源;skills/ 与 subagents/ 的加载语义本章没碰;Workspace 资产的版本化与回滚还没做。 > 旧法省一事 > 新法立一约 > 换来可运营 > 代价要认账 # 09、洞见 ## 9.1 Persona 迁出去,迁的其实是权限 反直觉判断:把 AGENTS.md 交给运营,看起来是省了发版,实质是把一部分提示词权限从后端交给了业务。AGENTS.md 里能写拒答规则、能写业务边界、能写工具使用约束,这已经是策略层的东西。 一旦它可被运营修改,就必须回答:谁有权改、改了要不要审批、出事能不能回滚。没有这三个答案,Workspace 只是把风险从代码仓库搬到了一个没版本控制的目录里。 ## 9.2 AgentState 不是配置的第二存储 反直觉判断:会话状态看起来是离 Agent 最近的地方,改起来最快,实际上它是最不该放身份定义的地方。运行态会被序列化、恢复、复制,把身份塞进去,等于给同一个项目埋下多个人格的种子。 判断标准很简单:这个东西如果每个会话都可以不一样,那它属于 AgentState;如果所有会话都应该一样,那它属于 Workspace。 ## 9.3 迁移顺序:先人设,再知识,最后工具 本章我只迁了 AGENTS.md 与 tools.json 的落点,knowledge/、skills/、subagents/ 先留空目录。这不是偷懒,是风险排序。 人设改动只影响语言风格,出错顶多是语气不对;知识改动会影响事实正确性,出错就是答错;工具改动会影响副作用,出错可能已经写了数据库。顺序反过来做,你会同时面对风格、事实、副作用三类问题,排查时根本分不清是哪一层引起的。 ## 9.4 什么时候不应该用 Workspace 什么时候不应该用本章能力?只有一个数字人、人设三个月不动一次、改动必须走代码评审的场景,不该用。这种情况把 AGENTS.md 也塞进代码仓库、跟着 Java 一起发版,反而更安全,因为你有版本、有评审、有回滚。 Workspace 解决的是资产归属问题,不是配置管理问题。缺版本管理和审批的时候,它不会让事情变好。 > 权限先讲清 > 状态莫越界 > 顺序按风险 > 场景定取舍 # 10、系统落地 原来有什么:chapter/16 分支上,ProjectConfig 是 Java 常量,systemPrompt 由代码拼接,工具与 MCP 地址分散在 yml 的多个 profile 里,多客户靠分支或 profile 隔离。 本篇新增什么:chapter/17-workspace 分支上,新增 workspace/{projectId}/ 目录契约与 WorkspaceLoader、WorkspaceResolver;Persona、业务边界、知识入口清单、MCP 配置从 Java 硬编码迁到 Workspace;加载失败分级处理,工具与知识以清单形式暴露给宿主。 现在能做什么:改 AGENTS.md,不碰任何 Java 代码,重启进程后数字人身份与规则改变,新 Session 使用新身份;既有 Session 保持创建时的身份,行为边界在日志与文档里说清;tools.json 成为工具与 MCP 的唯一入口,新增一个 MCP server 不再需要动 Java。 还缺什么:Workspace 资产的版本化与回滚、skills/ 与 subagents/ 的加载语义、Workspace 与数据库项目配置的权威源划分、加载结果的审计记录。 下一步如何演进:把记忆与知识接进来,让 MEMORY.md 与 knowledge/ 真正参与推理,而不是只列文件名;再往后把工具权限与 Workspace 资产挂钩,做成按项目的可见性策略。 开源参与点:发现可作为 Issue/PR 候选的问题:Workspace 资产在既有 Session 中是否重读、缺失文件的处理语义(报错还是告警)在官方文档里的描述边界不够清晰,可能值得补一段说明。该候选尚未在官方仓库检索确认是否已有对应 Issue,也需按当前官方文档核验,因此本章不声称已提交任何 Issue 或 PR。 > 硬编码退场 > 目录契约登场 > 身份成为资产 > 权限紧随其后 # 11、小结 Q1 → 身份属于数据。它应该落在 workspace/{projectId}/AGENTS.md 这类资产文件里,Java 只负责加载与组装,不负责定义。 Q2 → 文件改了,新 Session 用新资产;既有 Session 保持创建时的快照。需要当天切换时走显式的会话重建,不做隐性热替换。 Q3 → 选错的后果有两类:把 Workspace 当配置中心,会出现改了不生效的困惑;把 AgentState 当配置存储,会出现同一项目多个人格。 状态 → 数字人的人设、业务边界、知识入口与 MCP 配置已从 Java 硬编码迁到 Workspace,chapter/17-workspace 分支可作为后续记忆、技能、子 Agent 章节的底座。 ```text [本章前] Persona / 边界 / MCP 分散在 Java 与 yml | v [本章后] Persona / 边界 / 知识清单 / MCP 落在 workspace/{projectId}/ | v [仍然不变] AgentState 只承载单次会话的运行态,不承载身份定义 ``` > 一问定归属 > 二问定生命 > 三问定代价 > 三答定边界 # 12、作业 ## 12.1 理解题:为什么说 Workspace 与 AgentState 不是同一层? 参考答案:Workspace 是磁盘上的长驻资产,生命周期独立于会话,多个 Session 共享同一份;AgentState 是单次会话的运行态,承载消息与运行数据,随会话创建而生、随会话结束而灭。判断标准是:所有会话都应该一样的,放 Workspace;每个会话可以不一样的,放 AgentState。 ## 12.2 实战题:把数字人的开场白与身份描述从 Java 迁到 Workspace,并验证。 参考答案:在 workspace/{projectId}/AGENTS.md 里写身份、语气、业务边界与开场白;Java 侧用加载器读取文件内容,作为 systemPrompt 的主体;tools.json 承载工具与 MCP 配置。验证分两步:改 AGENTS.md 不动 Java,重启进程后新开会话,观察身份是否改变;在同一进程内继续旧会话,观察是否仍用旧身份且不报错。注意区分预期结果与实测结果。 ## 12.3 排障题:tools.json 里的 MCP server 没有注册,日志里加载的 server 数量是 0,怎么定位? 参考答案:先确认文件存在,再确认读取路径的解析基准。常见根因是相对路径以进程工作目录为基准,而期望是以 workspace 根为基准,导致读到了不存在的文件,而缺失又被静默处理成空字符串。修复方式是统一以 workspaceRoot 解析相对路径,并对缺失文件分级处理。 ## 12.4 架构判断题:请打开官方仓库 v2.0.3 的 harness 文档与 WorkspaceManager 源码,判断该版本是否支持 Workspace 资产的动态重载,并说明你的核验依据。 参考答案:应打开 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/docs/v2/zh/docs/harness/workspace.md 与 https://github.com/agentscope-ai/agentscope-java/blob/v2.0.3/agentscope-harness/src/main/java/io/agentscope/harness/agent/workspace/WorkspaceManager.java ,并对照同目录的测试类,确认资产的读取时机、是否缓存、是否有重载入口;同时对比 main 分支与 Release Notes,区分 v2.0.3 的限制与当前最新版的现状。核验依据必须落到具体方法与测试,而不是文档标题。 > 一题辨层级 > 二题练迁移 > 三题查基准 > 四题读源码 # 13、思考 这一篇的核心冲突,说到底是一句话:数字人的身份是代码还是数据。 答案不是二选一,而是分层。身份定义、业务边界、知识入口、工具配置属于资产,放在 Workspace;会话消息、运行变量、临时上下文属于状态,放在 AgentState。把这两层混在一起,你会同时失去可运营性和会话一致性。 更值得记住的是那句反直觉的话:迁到文件不等于自动生效。读过一次的快照会跟着会话走,这是设计,不是缺陷。真正的工程判断是,什么时候该让新会话用新资产,什么时候该提供显式的会话重建,而不是默认热替换正在进行的对话。 会用框架的人,知道 WorkspaceManager 在哪里;能参与框架演进的人,会去读它的加载时机、缺失语义与缓存策略,然后判断哪些是自己的宿主责任,哪些才是值得提给上游的问题。 > 身份归资产 > 状态归会话 > 边界一旦清 > 演进自有路

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册