Skip to content

feat: add group message flow context mode#8243

Open
Tsukumi233 wants to merge 1 commit into
AstrBotDevs:masterfrom
Tsukumi233:feature/group-context-flow
Open

feat: add group message flow context mode#8243
Tsukumi233 wants to merge 1 commit into
AstrBotDevs:masterfrom
Tsukumi233:feature/group-context-flow

Conversation

@Tsukumi233
Copy link
Copy Markdown
Contributor

@Tsukumi233 Tsukumi233 commented May 19, 2026

为群聊上下文感知新增 flow 模式,让现代长上下文模型可以按群聊消息流增量接收上下文,而不是每次只依赖滑动窗口。默认仍为 sliding_window,现有用户不启用新模式时行为保持不变。

Modifications / 改动点

  • 新增 GroupMessageFlowRecordGroupMessageFlowCursor 数据表,用于持久化群聊消息流以及每个 conversation 的消费游标。
  • 在群聊上下文感知中新增 group_context_mode,支持 sliding_windowflow 两种模式;flow 模式会在 LLM 请求前注入 <group_messages_delta>,并排除当前触发消息,避免重复上下文。
  • 为 flow delta 增加安全边界:group_flow_max_delta_messages 每次只注入最近 N 条消息,默认 200;group_flow_max_message_chars 每条消息只保留前 N 个字符,默认 1000;两者均可设为 0 关闭对应限制。
  • 兼容 /reset/new 等会话清理路径:清理后将 flow 游标推进到最新消息,使新会话不会带入旧 delta。
  • 默认不记录 LLM 自己的回复;新增 group_flow_record_bot_messages 仅控制命令或插件产生的普通机器人消息。
  • 增加消息组件 JSON-safe 序列化,覆盖 Reply 内嵌 Plain 等嵌套组件,并兼容同步/异步 to_dict(),避免 flow 落库时报 not JSON serializable
  • 增加 WebUI 配置项和中/英/俄 i18n,包括 flow/sliding_window 选项标签。
  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

验证步骤:

jq empty dashboard/src/i18n/locales/zh-CN/features/config-metadata.json dashboard/src/i18n/locales/en-US/features/config-metadata.json dashboard/src/i18n/locales/ru-RU/features/config-metadata.json
node - <<'NODE'
const fs = require('fs');
const files = [
  'dashboard/src/i18n/locales/zh-CN/features/config-metadata.json',
  'dashboard/src/i18n/locales/en-US/features/config-metadata.json',
  'dashboard/src/i18n/locales/ru-RU/features/config-metadata.json',
];
const keys = [
  'ext_group.ltm.provider_ltm_settings.group_context_mode.description',
  'ext_group.ltm.provider_ltm_settings.group_context_mode.hint',
  'ext_group.ltm.provider_ltm_settings.group_context_mode.labels',
  'ext_group.ltm.provider_ltm_settings.group_flow_max_records.description',
  'ext_group.ltm.provider_ltm_settings.group_flow_max_delta_messages.description',
  'ext_group.ltm.provider_ltm_settings.group_flow_max_message_chars.description',
  'ext_group.ltm.provider_ltm_settings.group_flow_record_bot_messages.description',
];
for (const file of files) {
  const data = JSON.parse(fs.readFileSync(file, 'utf8'));
  for (const key of keys) {
    let value = data;
    for (const part of key.split('.')) value = value && value[part];
    if (!value) throw new Error(`${file} missing ${key}`);
  }
}
console.log('i18n keys ok');
NODE
uv run ruff format --check astrbot/builtin_stars/astrbot/long_term_memory.py astrbot/core/config/default.py astrbot/core/db/__init__.py astrbot/core/db/sqlite.py tests/test_group_message_flow.py
uv run ruff check astrbot/builtin_stars/astrbot/long_term_memory.py astrbot/core/config/default.py astrbot/core/db/__init__.py astrbot/core/db/sqlite.py tests/test_group_message_flow.py
uv run pytest tests/test_group_message_flow.py
uv run pytest
cd dashboard && pnpm install --frozen-lockfile && pnpm typecheck

结果:

i18n keys ok
5 files already formatted
All checks passed!
tests/test_group_message_flow.py: 7 passed
uv run pytest: 1293 passed, 4 warnings
pnpm install --frozen-lockfile: Done
pnpm typecheck: passed

Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. area:core The bug / feature is about astrbot's core, backend labels May 19, 2026
Copy link
Copy Markdown
Contributor

@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 - I've found 2 issues, and left some high level feedback:

  • In LongTermMemory._json_safe you call isinstance(value, list | tuple), but list | tuple creates a types.UnionType which isinstance does not accept and will raise a TypeError; use a tuple of types instead (e.g., isinstance(value, (list, tuple))).
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `LongTermMemory._json_safe` you call `isinstance(value, list | tuple)`, but `list | tuple` creates a `types.UnionType` which `isinstance` does not accept and will raise a `TypeError`; use a tuple of types instead (e.g., `isinstance(value, (list, tuple))`).

## Individual Comments

### Comment 1
<location path="astrbot/builtin_stars/astrbot/long_term_memory.py" line_range="239" />
<code_context>
+            return await self._json_safe(value.toDict())
+        if isinstance(value, dict):
+            return {k: await self._json_safe(v) for k, v in value.items()}
+        if isinstance(value, list | tuple):
+            return [await self._json_safe(item) for item in value]
+        return value
</code_context>
<issue_to_address>
**issue (bug_risk):** Using `isinstance(value, list | tuple)` will raise at runtime; `isinstance` does not accept `|` unions here.

`isinstance` requires a type or a tuple of types as its second argument; `list | tuple` (PEP 604 union) will raise `TypeError` at runtime, so this branch will fail for lists/tuples. Use `isinstance(value, (list, tuple))`, or `collections.abc.Sequence` if you need broader sequence support.
</issue_to_address>

### Comment 2
<location path="astrbot/builtin_stars/astrbot/long_term_memory.py" line_range="224-225" />
<code_context>
+        return content
+
+    async def _component_to_json_safe_dict(self, comp) -> dict:
+        if hasattr(comp, "to_dict"):
+            data = await comp.to_dict()
+        elif hasattr(comp, "toDict"):
+            data = comp.toDict()
</code_context>
<issue_to_address>
**issue (bug_risk):** Blindly awaiting `comp.to_dict()` assumes it is async; if it is sync this will fail at runtime.

Both `_component_to_json_safe_dict` and `_json_safe` currently assume any `to_dict` is async. If `to_dict` is a regular sync method returning a dict (a common case), `await comp.to_dict()` will raise `TypeError: object dict can't be used in 'await' expression`. Consider checking whether `to_dict` is awaitable (e.g. via `inspect.iscoroutinefunction` / `inspect.isawaitable`) and only `await` it when appropriate, otherwise call it synchronously.
</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 astrbot/builtin_stars/astrbot/long_term_memory.py Outdated
Comment thread astrbot/builtin_stars/astrbot/long_term_memory.py Outdated
Copy link
Copy Markdown
Contributor

@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 new 'flow' mode for group chat context management, which persists group messages and uses conversation cursors to provide a more stable long-term memory compared to the traditional sliding window. The implementation includes new database models for message records and cursors, a dedicated GroupMessageFlowManager, and updates to the configuration and core lifecycle to support these features. I have no feedback to provide.

@Tsukumi233 Tsukumi233 force-pushed the feature/group-context-flow branch 2 times, most recently from aee15ee to 91791db Compare May 19, 2026 14:56
@Tsukumi233 Tsukumi233 force-pushed the feature/group-context-flow branch from 91791db to f5e1d09 Compare May 20, 2026 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant