Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions astrbot/builtin_stars/builtin_commands/commands/conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,16 +206,33 @@ async def convs(self, message: AstrMessageEvent, page: int = 1) -> None:
_titles[conv.cid] = title

"""遍历分页后的对话生成列表显示"""
provider_settings = cfg.get("provider_settings", {})
platform_name = message.get_platform_name()
for conv in conversations_paged:
persona_id = conv.persona_id
if not persona_id or persona_id == "[%None]":
persona = await self.context.persona_manager.get_default_persona_v3(
umo=message.unified_msg_origin,
)
persona_id = persona["name"]
(
persona_id,
_,
force_applied_persona_id,
_,
) = await self.context.persona_manager.resolve_selected_persona(
umo=message.unified_msg_origin,
conversation_persona_id=conv.persona_id,
platform_name=platform_name,
provider_settings=provider_settings,
)
if persona_id == "[%None]":
persona_name = "无"
elif persona_id:
persona_name = persona_id
else:
persona_name = "无"
Comment on lines +223 to +228
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

这部分用于确定 persona_name 的逻辑可以被简化。当前的 if/elif/else 结构有些冗长,可以精简为更简洁的形式。

            if persona_id and persona_id != "[%None]":
                persona_name = persona_id
            else:
                persona_name = "无"


if force_applied_persona_id:
persona_name = f"{persona_name} (自定义规则)"

title = _titles.get(conv.cid, "新对话")
parts.append(
f"{global_index}. {title}({conv.cid[:4]})\n 人格情景: {persona_id}\n 上次更新: {datetime.datetime.fromtimestamp(conv.updated_at).strftime('%m-%d %H:%M')}\n"
f"{global_index}. {title}({conv.cid[:4]})\n 人格情景: {persona_name}\n 上次更新: {datetime.datetime.fromtimestamp(conv.updated_at).strftime('%m-%d %H:%M')}\n"
)
global_index += 1

Expand Down
34 changes: 23 additions & 11 deletions astrbot/builtin_stars/builtin_commands/commands/persona.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import builtins
from typing import TYPE_CHECKING

from astrbot.api import sp, star
from astrbot.api import star
from astrbot.api.event import AstrMessageEvent, MessageEventResult

if TYPE_CHECKING:
Expand Down Expand Up @@ -59,12 +59,7 @@ async def persona(self, message: AstrMessageEvent) -> None:
default_persona = await self.context.persona_manager.get_default_persona_v3(
umo=umo,
)

force_applied_persona_id = (
await sp.get_async(
scope="umo", scope_id=umo, key="session_service_config", default={}
)
).get("persona_id")
force_applied_persona_id = None

curr_cid_title = "无"
if cid:
Expand All @@ -80,10 +75,27 @@ async def persona(self, message: AstrMessageEvent) -> None:
),
)
return
if not conv.persona_id and conv.persona_id != "[%None]":
curr_persona_name = default_persona["name"]
else:
curr_persona_name = conv.persona_id

provider_settings = self.context.get_config(umo=umo).get(
"provider_settings",
{},
)
(
persona_id,
_,
force_applied_persona_id,
_,
) = await self.context.persona_manager.resolve_selected_persona(
umo=umo,
conversation_persona_id=conv.persona_id,
platform_name=message.get_platform_name(),
provider_settings=provider_settings,
)

if persona_id == "[%None]":
curr_persona_name = "无"
elif persona_id:
curr_persona_name = persona_id
Comment on lines +95 to +98
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

这部分用于确定 curr_persona_name 的逻辑可以变得更独立和易读。目前的实现依赖于该变量在函数前面被初始化为 "无"。一个独立的 if/else 代码块会更清晰。

Suggested change
if persona_id == "[%None]":
curr_persona_name = "无"
elif persona_id:
curr_persona_name = persona_id
if persona_id and persona_id != "[%None]":
curr_persona_name = persona_id
else:
curr_persona_name = "无"


if force_applied_persona_id:
curr_persona_name = f"{curr_persona_name} (自定义规则)"
Expand Down
49 changes: 13 additions & 36 deletions astrbot/core/astr_main_agent.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

import asyncio
import builtins
import copy
import datetime
import json
Expand All @@ -10,7 +9,6 @@
from collections.abc import Coroutine
from dataclasses import dataclass, field

from astrbot.api import sp
from astrbot.core import logger
from astrbot.core.agent.handoff import HandoffTool
from astrbot.core.agent.mcp_client import MCPTool
Expand Down Expand Up @@ -275,47 +273,26 @@ async def _ensure_persona_and_skills(
if not req.conversation:
return

# get persona ID

# 1. from session service config - highest priority
persona_id = (
await sp.get_async(
scope="umo",
scope_id=event.unified_msg_origin,
key="session_service_config",
default={},
)
).get("persona_id")

if not persona_id:
# 2. from conversation setting - second priority
persona_id = req.conversation.persona_id

if persona_id == "[%None]":
# explicitly set to no persona
pass
elif persona_id is None:
# 3. from config default persona setting - last priority
persona_id = cfg.get("default_personality")

persona = next(
builtins.filter(
lambda persona: persona["name"] == persona_id,
plugin_context.persona_manager.personas_v3,
),
None,
(
persona_id,
persona,
_,
use_webchat_special_default,
) = await plugin_context.persona_manager.resolve_selected_persona(
umo=event.unified_msg_origin,
conversation_persona_id=req.conversation.persona_id,
platform_name=event.get_platform_name(),
provider_settings=cfg,
)

if persona:
# Inject persona system prompt
if prompt := persona["prompt"]:
req.system_prompt += f"\n# Persona Instructions\n\n{prompt}\n"
if begin_dialogs := copy.deepcopy(persona.get("_begin_dialogs_processed")):
req.contexts[:0] = begin_dialogs
else:
# special handling for webchat persona
if event.get_platform_name() == "webchat" and persona_id != "[%None]":
persona_id = "_chatui_default_"
req.system_prompt += CHATUI_SPECIAL_DEFAULT_PERSONA_PROMPT
elif use_webchat_special_default:
req.system_prompt += CHATUI_SPECIAL_DEFAULT_PERSONA_PROMPT

# Inject skills prompt
runtime = cfg.get("computer_use_runtime", "local")
Expand Down
55 changes: 55 additions & 0 deletions astrbot/core/persona_mgr.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from astrbot import logger
from astrbot.api import sp
from astrbot.core.astrbot_config_mgr import AstrBotConfigManager
from astrbot.core.db import BaseDatabase
from astrbot.core.db.po import Persona, PersonaFolder, Personality
Expand Down Expand Up @@ -58,6 +59,60 @@ async def get_default_persona_v3(
except Exception:
return DEFAULT_PERSONALITY

async def resolve_selected_persona(
self,
*,
umo: str | MessageSession,
conversation_persona_id: str | None,
platform_name: str,
provider_settings: dict | None = None,
) -> tuple[str | None, Personality | None, str | None, bool]:
"""解析当前会话最终生效的人格。

Returns:
tuple:
- selected persona_id
- selected persona object
- force applied persona_id from session rule
- whether use webchat special default persona
"""
session_service_config = (
await sp.get_async(
scope="umo",
scope_id=str(umo),
key="session_service_config",
default={},
)
or {}
)

force_applied_persona_id = session_service_config.get("persona_id")
persona_id = force_applied_persona_id

if not persona_id:
persona_id = conversation_persona_id
if persona_id == "[%None]":
pass
elif persona_id is None:
persona_id = (provider_settings or {}).get("default_personality")

persona = next(
(item for item in self.personas_v3 if item["name"] == persona_id),
None,
)

use_webchat_special_default = False
if not persona and platform_name == "webchat" and persona_id != "[%None]":
persona_id = "_chatui_default_"
use_webchat_special_default = True

return (
persona_id,
persona,
force_applied_persona_id,
use_webchat_special_default,
)

async def delete_persona(self, persona_id: str) -> None:
"""删除指定 persona"""
if not await self.db.get_persona_by_id(persona_id):
Expand Down
4 changes: 3 additions & 1 deletion astrbot/dashboard/routes/conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ async def upd_conv(self):
user_id = data.get("user_id")
cid = data.get("cid")
title = data.get("title")
persona_id = data.get("persona_id", "")

if not user_id or not cid:
return Response().error("缺少必要参数: user_id 和 cid").__dict__
Expand All @@ -158,6 +157,9 @@ async def upd_conv(self):
)
if not conversation:
return Response().error("对话不存在").__dict__

persona_id = data.get("persona_id", conversation.persona_id)

if title is not None or persona_id is not None:
await self.conv_mgr.update_conversation(
unified_msg_origin=user_id,
Expand Down