Skip to content

适配记忆注入与全局记忆#3

Merged
piexian merged 2 commits into
masterfrom
chore/v0.3.2-memory-i18n
May 13, 2026
Merged

适配记忆注入与全局记忆#3
piexian merged 2 commits into
masterfrom
chore/v0.3.2-memory-i18n

Conversation

@piexian
Copy link
Copy Markdown
Owner

@piexian piexian commented May 13, 2026

Summary by Sourcery

添加全局记忆作用域和仅管理员可用的全局记忆存储,并更新记忆注入逻辑,以更好地集成新版 AstrBot API,并对新行为和配置进行文档说明。

New Features:

  • 引入 GLOBAL 记忆作用域,并将其纳入记忆格式化和检索流程。
  • 添加仅管理员可用的 memory_store_global LLM 工具,该工具受 enable_admin_global_memory_tool 配置开关控制。
  • 为 AstrBot 插件提供 i18n 元数据,包含 zh-CN 和 en-US WebUI 文本及配置标签。

Enhancements:

  • 在相关代码路径中,将全局记忆的可见性规范化,并使其与群组记忆的处理方式保持一致。
  • 改进记忆注入逻辑:优先使用 AstrBot v4.24+ 的临时用户内容区域;若不可用,则回退到最早的用户上下文消息,而不是将内容前置到提示词开头。
  • 明确注入记忆的包装文本,强调其作为历史参考的作用,并提示在需要更多上下文时使用 memory_recall(query)

Documentation:

  • 更新 README 和 changelog,记录新的全局记忆工具、全局作用域语义、配置选项以及修订后的记忆注入行为。
Original summary in English

Summary by Sourcery

Add global memory scope and admin-only global memory storage, and update memory injection to better integrate with newer AstrBot APIs while documenting the new behavior and configuration.

New Features:

  • Introduce a GLOBAL memory scope and include it in memory formatting and retrieval flows.
  • Add an admin-only memory_store_global LLM tool gated by the enable_admin_global_memory_tool configuration flag.
  • Provide AstrBot plugin i18n metadata with zh-CN and en-US WebUI texts and configuration labels.

Enhancements:

  • Normalize and handle global memory visibility similarly to group memory in relevant code paths.
  • Improve memory injection by preferring AstrBot v4.24+ temporary user content areas, with fallback to the earliest user context message, instead of prepending to the prompt.
  • Clarify injected memory wrapper text to emphasize its role as historical reference and to hint at using memory_recall(query) when more context is needed.

Documentation:

  • Update README and changelog to document the new global memory tool, global scope semantics, configuration options, and revised memory injection behavior.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 13, 2026

Reviewer's Guide

添加全局(GLOBAL)记忆作用域和仅管理员可用的全局记忆存储工具,更新记忆召回/注入行为,更好地利用 AstrBot 的临时用户内容区域并明确记忆语义,同时引入 i18n 元数据以及针对新配置与行为的文档/更新日志。

使用临时用户内容的更新版记忆注入时序图

sequenceDiagram
    actor User
    participant Event as AstrMessageEvent
    participant Plugin as SimpleLongMemoryPlugin
    participant Request as ProviderRequest

    User ->> Event: send message
    Event ->> Plugin: inject_memories(event, request)
    Plugin ->> Plugin: format_memory_for_injection(memories)
    Plugin ->> Plugin: _inject_memory_context(request, safe_memory_context)
    Plugin ->> Plugin: _append_extra_user_content(request, content)
    alt extra_user_content_parts available
        Plugin ->> Request: extra_user_content_parts.append(_make_memory_text_part)
        Plugin -->> Plugin: return "extra_user_content_parts"
    else no extra_user_content_parts or unsupported
        Plugin ->> Plugin: _normalize_contexts(request.contexts)
        Plugin ->> Request: set contexts = [memory_msg] + contexts
        Plugin -->> Plugin: return "contexts 底部"
    end
    Plugin -->> Event: continue LLM request with injected memory
Loading

仅管理员可用的全局 memory_store_global 工具时序图

sequenceDiagram
    actor Admin
    participant Event as AstrMessageEvent
    participant Plugin as SimpleLongMemoryPlugin
    participant Manager as MemoryManager

    Admin ->> Event: request LLM tool memory_store_global
    Event ->> Plugin: tool_store_global(event, content, memory_type, disclosure)
    Plugin ->> Plugin: self.config.get(enable_admin_global_memory_tool)
    alt global tool disabled
        Plugin -->> Event: "Global memory tool is disabled in plugin config"
    else enabled
        Plugin ->> Event: event.is_admin()
        alt not admin
            Plugin -->> Event: "Only administrators can store global memories"
        else is admin
            Plugin ->> Plugin: _sanitize_memory_content(content)
            Plugin ->> Plugin: normalize_domain(memory_type)
            Plugin ->> Plugin: MemoryURI.generate(domain)
            Plugin ->> Manager: store_memory(event, content, domain, uri, memory_type=MemoryType.PERMANENT, disclosure, importance=5, memory_scope=MemoryScope.GLOBAL, visibility="group", subject="global")
            Manager -->> Plugin: ok
            Plugin -->> Event: "Global memory stored: {uri}"
        end
    end
Loading

文件级变更

Change Details Files
调整记忆作用域归一化和默认召回行为,以支持新的 GLOBAL 作用域,并在未指定作用域时优先召回全局 + 个人记忆。
  • 在 MemoryScope 中添加 GLOBAL,并允许 normalize_memory_scope 接受该值。
  • 在用于格式化注入记忆的分组区段中包含 GLOBAL。
  • 更新 normalize_visibility 和元数据归一化逻辑,使 GLOBAL 记忆在适当情况下默认为类似 GROUP 作用域的 group 可见性。
  • 修改 _scope_filter 和 _build_recall_filters 中基于作用域的过滤逻辑,显式处理 GLOBAL,并在未提供作用域时将 GLOBAL 与 PERSONAL 一并包含。
  • 调整 flush/write 过滤逻辑,使 GLOBAL 记忆不再受 owner_session_id 约束,而 GROUP/CONVERSATION 保持原有行为。
memory_protocol.py
memory_manager.py
引入仅管理员可用的全局记忆存储 LLM 工具,并在代码和文档中暴露启用该工具的配置。
  • 添加 tool_store_global LLM 工具,在存储 GLOBAL、group 可见、永久记忆前,验证插件配置、管理员身份以及记忆管理器是否可用,并对内容和披露信息进行清洗。
  • 在写入全局记忆时使用 MemoryScope.GLOBAL 以及合适的元数据(visibility、subject、importance)。
  • 在 README 中记录新的 enable_admin_global_memory_tool 配置开关和 memory_store_global 工具,包括全局作用域语义说明和使用注意事项。
  • 在 CHANGELOG 中添加新的 v0.3.2 条目,描述全局记忆工具功能及其配置开关。
main.py
README.md
CHANGELOG.md
优化召回记忆注入到 LLM 请求的方式,以利用 AstrBot v4.24+ 的临时用户内容片段,避免污染提示词/历史。
  • 添加 _make_memory_text_part 辅助函数,用于构造 AstrBot TextPart,并在受支持时将其标记为仅当前轮次临时生效。
  • 添加 _append_extra_user_content,将记忆 TextPart 追加到 request.extra_user_content_parts 中,并在需要时初始化该列表。
  • 添加 _inject_memory_context,优先将记忆注入 extra_user_content_parts;若不可用,则退回为在 contexts 开头预置一个 user 角色的记忆消息,而不是拼接到 prompt 中。
  • 修改 inject_memories 调用 _inject_memory_context,并记录实际的注入目标,同时移除旧的 prompt 前置路径。
main.py
明确模型侧记忆注入语义,并使 README/CHANGELOG/文档与新的行为及 i18n 支持保持一致。
  • 更新 format_memory_for_injection 的头部文案,将这些片段描述为长期记忆检索结果,强调它们是历史参考而非当前指令,并建议在需要更多上下文时使用 memory_recall(query)。
  • 在格式化注入内容中,将 GLOBAL 记忆视为单独分组,并标注为“适用于所有会话的全局记忆(Global memory for all chats)”。
  • 调整 _normalize_extracted_scope,使 GLOBAL 在非 group/非 global 的抽取流程中实质表现为 PERSONAL,同时仍通过 normalize_memory_scope 对作用域进行归一化。
  • 更新 README,描述新的注入路径(优先临时用户内容区域,其次最早的用户上下文),并记录全局作用域及工具表项。
  • 在 v0.3.2 的 changelog 中加入关于强化注入包装文案和新增召回提示的说明。
  • 在 metadata.yaml 中提升插件版本,并在 .astrbot-plugin/i18n 下为 WebUI 元数据和配置文案添加 zh-CN 和 en-US 的 i18n 文件。
memory_protocol.py
main.py
README.md
CHANGELOG.md
metadata.yaml
.astrbot-plugin/i18n/en-US.json
.astrbot-plugin/i18n/zh-CN.json

Tips and commands

Interacting with Sourcery

  • 触发新评审: 在拉取请求中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的评审评论。
  • 从评审评论生成 GitHub issue: 在评审评论下回复,请求 Sourcery 从该评论创建 issue。你也可以在评审评论中回复 @sourcery-ai issue 来基于该评论创建 issue。
  • 生成拉取请求标题: 在拉取请求标题中任意位置写入 @sourcery-ai,即可随时生成标题。你也可以在拉取请求中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成拉取请求摘要: 在拉取请求正文中任意位置写入 @sourcery-ai summary,即可在该位置生成 PR 摘要。你也可以在拉取请求中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成审阅者指南: 在拉取请求中评论 @sourcery-ai guide,可随时(重新)生成审阅者指南。
  • 解决所有 Sourcery 评论: 在拉取请求中评论 @sourcery-ai resolve,以解决所有 Sourcery 评论。若你已处理所有评论且不想再看到它们,这会很有用。
  • 关闭所有 Sourcery 评审: 在拉取请求中评论 @sourcery-ai dismiss,以关闭所有现有的 Sourcery 评审。若你希望从一次全新的评审开始,这尤其有用——别忘了再评论 @sourcery-ai review 触发新的评审!

Customizing Your Experience

访问你的 dashboard 以:

  • 启用或禁用评审功能,例如 Sourcery 生成的拉取请求摘要、审阅者指南等。
  • 更改评审语言。
  • 添加、删除或编辑自定义评审指令。
  • 调整其他评审设置。

Getting Help

Original review guide in English

Reviewer's Guide

Adds global memory scope and admin-only global memory storage tool, updates memory recall/injection behavior to better use AstrBot’s temporary user content area and clarify memory semantics, and introduces i18n metadata plus docs/changelog for the new configuration and behavior.

Sequence diagram for updated memory injection with temporary user content

sequenceDiagram
    actor User
    participant Event as AstrMessageEvent
    participant Plugin as SimpleLongMemoryPlugin
    participant Request as ProviderRequest

    User ->> Event: send message
    Event ->> Plugin: inject_memories(event, request)
    Plugin ->> Plugin: format_memory_for_injection(memories)
    Plugin ->> Plugin: _inject_memory_context(request, safe_memory_context)
    Plugin ->> Plugin: _append_extra_user_content(request, content)
    alt extra_user_content_parts available
        Plugin ->> Request: extra_user_content_parts.append(_make_memory_text_part)
        Plugin -->> Plugin: return "extra_user_content_parts"
    else no extra_user_content_parts or unsupported
        Plugin ->> Plugin: _normalize_contexts(request.contexts)
        Plugin ->> Request: set contexts = [memory_msg] + contexts
        Plugin -->> Plugin: return "contexts 底部"
    end
    Plugin -->> Event: continue LLM request with injected memory
Loading

Sequence diagram for admin-only global memory_store_global tool

sequenceDiagram
    actor Admin
    participant Event as AstrMessageEvent
    participant Plugin as SimpleLongMemoryPlugin
    participant Manager as MemoryManager

    Admin ->> Event: request LLM tool memory_store_global
    Event ->> Plugin: tool_store_global(event, content, memory_type, disclosure)
    Plugin ->> Plugin: self.config.get(enable_admin_global_memory_tool)
    alt global tool disabled
        Plugin -->> Event: "Global memory tool is disabled in plugin config"
    else enabled
        Plugin ->> Event: event.is_admin()
        alt not admin
            Plugin -->> Event: "Only administrators can store global memories"
        else is admin
            Plugin ->> Plugin: _sanitize_memory_content(content)
            Plugin ->> Plugin: normalize_domain(memory_type)
            Plugin ->> Plugin: MemoryURI.generate(domain)
            Plugin ->> Manager: store_memory(event, content, domain, uri, memory_type=MemoryType.PERMANENT, disclosure, importance=5, memory_scope=MemoryScope.GLOBAL, visibility="group", subject="global")
            Manager -->> Plugin: ok
            Plugin -->> Event: "Global memory stored: {uri}"
        end
    end
Loading

File-Level Changes

Change Details Files
Adjust memory scope normalization and recall defaults to support a new GLOBAL scope and prioritize global+personal recall when scope is unspecified.
  • Add GLOBAL to MemoryScope and allow normalize_memory_scope to accept it.
  • Include GLOBAL in the grouped sections used when formatting memories for injection.
  • Update normalize_visibility and metadata normalization so GLOBAL memories default to group visibility similar to GROUP scope where appropriate.
  • Change scope-based filters in _scope_filter and _build_recall_filters to handle GLOBAL explicitly and include GLOBAL alongside PERSONAL when no scope is provided.
  • Adjust flush/write filters so GLOBAL memories are not constrained by owner_session_id while GROUP/CONVERSATION retain their existing behavior.
memory_protocol.py
memory_manager.py
Introduce an admin-only global memory storage LLM tool and expose configuration for enabling it in code and docs.
  • Add tool_store_global LLM tool that validates plugin config, admin status, and memory manager availability before storing a GLOBAL, group-visible, permanent memory with sanitized content and disclosure.
  • Use MemoryScope.GLOBAL and appropriate metadata (visibility, subject, importance) when writing global memories.
  • Document the new enable_admin_global_memory_tool config flag and memory_store_global tool in README, including description of global scope semantics and usage notes.
  • Update CHANGELOG with a new v0.3.2 entry describing the global memory tool feature and config flag.
main.py
README.md
CHANGELOG.md
Refine how recalled memories are injected into LLM requests to leverage AstrBot v4.24+ temporary user content parts and avoid polluting prompt/history.
  • Add _make_memory_text_part helper that constructs an AstrBot TextPart and, when supported, marks it as temporary for the current turn only.
  • Add _append_extra_user_content to append memory TextParts into request.extra_user_content_parts when available, initializing the list if needed.
  • Add _inject_memory_context to prefer injecting memories into extra_user_content_parts and fall back to pre-pending a user-role memory message at the start of contexts instead of concatenating into the prompt.
  • Change inject_memories to call _inject_memory_context and log the actual injection target, removing the old prompt-prepending path.
main.py
Clarify memory injection semantics for the model and align README/CHANGELOG/docs with the new behavior and i18n support.
  • Update format_memory_for_injection header text to describe the snippets as long-term memory retrieval, emphasize they are historical reference not current instructions, and suggest using memory_recall(query) when more context is needed.
  • Treat GLOBAL memories as a separate group labeled “Global memory for all chats” in the formatted injection body.
  • Adjust _normalize_extracted_scope so GLOBAL effectively behaves as PERSONAL for non-group/non-global extraction flows while still normalizing scopes via normalize_memory_scope.
  • Update README to describe the new injection path (temporary user content area first, then earliest user context) and document the global scope and tools table entry.
  • Add v0.3.2 changelog notes covering strengthened injection wrapper wording and the new recall hint.
  • Bump plugin version in metadata.yaml and add i18n files under .astrbot-plugin/i18n for zh-CN and en-US WebUI metadata and configuration text.
memory_protocol.py
main.py
README.md
CHANGELOG.md
metadata.yaml
.astrbot-plugin/i18n/en-US.json
.astrbot-plugin/i18n/zh-CN.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题,并提供了一些高层次的反馈:

  • _inject_memory_context 中,返回的字符串 "contexts 底部" 容易产生误导,因为记忆消息实际上是被插入到 contexts 的最前面;建议返回/记录类似 "contexts 顶部" 的字符串,或者以其他方式明确实际的注入位置,以免在调试时造成困惑。
  • _normalize_extracted_scope 中,GLOBAL 会被立即规范化为 PERSONAL,而代码的其他部分却将 MemoryScope.GLOBAL 视为一等作用域;如果这是有意设计(例如为了避免自动提取到全局记忆),建议要么在函数名/文档字符串中明确体现这一点,要么统一对 GLOBAL 的处理方式,以避免出现意外的作用域降级。
给 AI Agent 的提示词
Please address the comments from this code review:

## Overall Comments
- In `_inject_memory_context`, the returned string "contexts 底部" is misleading since the memory message is prepended to `contexts`; consider returning/ logging something like "contexts 顶部" or otherwise clarifying the actual injection position to avoid confusion when debugging.
- In `_normalize_extracted_scope`, `GLOBAL` is immediately normalized to `PERSONAL` while other parts of the code treat `MemoryScope.GLOBAL` as a first-class scope; if this is intentional (e.g., to prevent automatic extraction into global memory), it would be helpful to either encode that explicitly in the function name/docstring or handle `GLOBAL` consistently to avoid unexpected scope downgrades.

## Individual Comments

### Comment 1
<location path="main.py" line_range="174-183" />
<code_context>
+    return True
+
+
+def _inject_memory_context(request: ProviderRequest, content: str) -> str:
+    """注入记忆上下文,返回实际使用的注入位置。"""
+    if _append_extra_user_content(request, content):
+        return "extra_user_content_parts"
+
+    contexts = _normalize_contexts(getattr(request, "contexts", None))
+    memory_msg = {"role": "user", "content": content}
+    # 旧版回退:放在 contexts 最前面,使当前 prompt 仍保持最后、优先级更高。
+    request.contexts = [memory_msg] + contexts
+    return "contexts 底部"
+
+
</code_context>
<issue_to_address>
**issue:** 注入目标返回的标签具有误导性/不够准确。

在 `_inject_memory_context` 中,记忆消息被插入到 `contexts` 的前面(`[memory_msg] + contexts`),但函数却返回标签 `"contexts 底部"`,这与实际行为以及注释“放在 contexts 最前面”相矛盾。请重命名该标签(例如改为 `"contexts_top"` / `"contexts 顶部"`),以便日志和调试能够准确反映消息被注入的位置。
</issue_to_address>

Sourcery 对开源项目免费——如果你喜欢我们的代码审查,请考虑分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据这些反馈改进后续的代码审查。
Original comment in English

Hey - I've found 1 issue, and left some high level feedback:

  • In _inject_memory_context, the returned string "contexts 底部" is misleading since the memory message is prepended to contexts; consider returning/ logging something like "contexts 顶部" or otherwise clarifying the actual injection position to avoid confusion when debugging.
  • In _normalize_extracted_scope, GLOBAL is immediately normalized to PERSONAL while other parts of the code treat MemoryScope.GLOBAL as a first-class scope; if this is intentional (e.g., to prevent automatic extraction into global memory), it would be helpful to either encode that explicitly in the function name/docstring or handle GLOBAL consistently to avoid unexpected scope downgrades.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `_inject_memory_context`, the returned string "contexts 底部" is misleading since the memory message is prepended to `contexts`; consider returning/ logging something like "contexts 顶部" or otherwise clarifying the actual injection position to avoid confusion when debugging.
- In `_normalize_extracted_scope`, `GLOBAL` is immediately normalized to `PERSONAL` while other parts of the code treat `MemoryScope.GLOBAL` as a first-class scope; if this is intentional (e.g., to prevent automatic extraction into global memory), it would be helpful to either encode that explicitly in the function name/docstring or handle `GLOBAL` consistently to avoid unexpected scope downgrades.

## Individual Comments

### Comment 1
<location path="main.py" line_range="174-183" />
<code_context>
+    return True
+
+
+def _inject_memory_context(request: ProviderRequest, content: str) -> str:
+    """注入记忆上下文,返回实际使用的注入位置。"""
+    if _append_extra_user_content(request, content):
+        return "extra_user_content_parts"
+
+    contexts = _normalize_contexts(getattr(request, "contexts", None))
+    memory_msg = {"role": "user", "content": content}
+    # 旧版回退:放在 contexts 最前面,使当前 prompt 仍保持最后、优先级更高。
+    request.contexts = [memory_msg] + contexts
+    return "contexts 底部"
+
+
</code_context>
<issue_to_address>
**issue:** The returned label for the injection target is misleading/inaccurate.

In `_inject_memory_context`, the memory message is prepended to `contexts` (`[memory_msg] + contexts`), but the function returns the label `"contexts 底部"`, which contradicts both the behavior and the comment “放在 contexts 最前面”. Please rename this label (e.g. to `"contexts_top"` / `"contexts 顶部"`) so logs and debugging accurately reflect where the message is injected.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread main.py Outdated
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a global memory scope, allowing administrators to store facts and preferences accessible across all chat sessions via the new memory_store_global tool. It also adds internationalization support for English and Chinese and refines the memory injection logic to utilize AstrBot v4.24+ temporary content parts. The injection prompt was updated to better guide the AI on how to treat retrieved memories. Feedback was provided regarding a string mismatch in the fallback injection logic where the return value incorrectly described the injection position as the 'bottom' of the context instead of the 'top'.

Comment thread main.py Outdated
@piexian piexian merged commit b882fc9 into master May 13, 2026
4 checks passed
@piexian piexian deleted the chore/v0.3.2-memory-i18n branch May 13, 2026 22:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant