diff --git a/astrbot/core/agent/runners/tool_loop_agent_runner.py b/astrbot/core/agent/runners/tool_loop_agent_runner.py
index 1e04001e4..82ab11b05 100644
--- a/astrbot/core/agent/runners/tool_loop_agent_runner.py
+++ b/astrbot/core/agent/runners/tool_loop_agent_runner.py
@@ -81,7 +81,7 @@ class ToolLoopAgentRunner(BaseAgentRunner[TContext]):
"func_tool": self.req.func_tool,
"model": self.req.model, # NOTE: in fact, this arg is None in most cases
"session_id": self.req.session_id,
- "extra_content_blocks": self.req.extra_content_blocks,
+ "extra_user_content_parts": self.req.extra_user_content_parts,
}
if self.streaming:
diff --git a/astrbot/core/provider/entities.py b/astrbot/core/provider/entities.py
index 5f794442e..5ddca16c9 100644
--- a/astrbot/core/provider/entities.py
+++ b/astrbot/core/provider/entities.py
@@ -14,6 +14,7 @@ import astrbot.core.message.components as Comp
from astrbot import logger
from astrbot.core.agent.message import (
AssistantMessageSegment,
+ ContentPart,
ToolCall,
ToolCallMessageSegment,
)
@@ -92,8 +93,10 @@ class ProviderRequest:
"""会话 ID"""
image_urls: list[str] = field(default_factory=list)
"""图片 URL 列表"""
- extra_content_blocks: list[dict] = field(default_factory=list)
- """额外的内容块列表,用于在用户消息后添加额外的文本块(如系统提醒、指令等)"""
+ extra_user_content_parts: list[dict] | list[ContentPart] = field(
+ default_factory=list
+ )
+ """额外的用户消息内容部分列表,用于在用户消息后添加额外的内容块(如系统提醒、指令等)。支持 dict 或 ContentPart 对象"""
func_tool: ToolSet | None = None
"""可用的函数工具"""
contexts: list[dict] = field(default_factory=list)
@@ -179,7 +182,14 @@ class ProviderRequest:
content_blocks.append({"type": "text", "text": "[图片]"})
# 2. 额外的内容块(系统提醒、指令等)
- content_blocks.extend(self.extra_content_blocks)
+ if self.extra_user_content_parts:
+ for part in self.extra_user_content_parts:
+ if hasattr(part, "model_dump"):
+ # ContentPart 对象,需要 model_dump
+ content_blocks.append(part.model_dump())
+ else:
+ # 已经是 dict
+ content_blocks.append(part)
# 3. 图片内容
if self.image_urls:
@@ -203,7 +213,7 @@ class ProviderRequest:
if (
len(content_blocks) == 1
and content_blocks[0]["type"] == "text"
- and not self.extra_content_blocks
+ and not self.extra_user_content_parts
and not self.image_urls
):
return {"role": "user", "content": content_blocks[0]["text"]}
diff --git a/astrbot/core/provider/provider.py b/astrbot/core/provider/provider.py
index b81e24da6..fdcc6f238 100644
--- a/astrbot/core/provider/provider.py
+++ b/astrbot/core/provider/provider.py
@@ -103,7 +103,7 @@ class Provider(AbstractProvider):
system_prompt: str | None = None,
tool_calls_result: ToolCallsResult | list[ToolCallsResult] | None = None,
model: str | None = None,
- extra_content_blocks: list[dict] | None = None,
+ extra_user_content_parts: list[dict] | None = None,
**kwargs,
) -> LLMResponse:
"""获得 LLM 的文本对话结果。会使用当前的模型进行对话。
@@ -115,7 +115,7 @@ class Provider(AbstractProvider):
tools: tool set
contexts: 上下文,和 prompt 二选一使用
tool_calls_result: 回传给 LLM 的工具调用结果。参考: https://platform.openai.com/docs/guides/function-calling
- extra_content_blocks: 额外的内容块列表,用于在用户消息后添加额外的文本块(如系统提醒、指令等)
+ extra_user_content_parts: 额外的内容块列表,用于在用户消息后添加额外的文本块(如系统提醒、指令等)
kwargs: 其他参数
Notes:
diff --git a/astrbot/core/provider/sources/anthropic_source.py b/astrbot/core/provider/sources/anthropic_source.py
index 788047375..a4ad9e832 100644
--- a/astrbot/core/provider/sources/anthropic_source.py
+++ b/astrbot/core/provider/sources/anthropic_source.py
@@ -296,7 +296,7 @@ class ProviderAnthropic(Provider):
system_prompt=None,
tool_calls_result=None,
model=None,
- extra_content_blocks=None,
+ extra_user_content_parts=None,
**kwargs,
) -> LLMResponse:
if contexts is None:
@@ -304,7 +304,7 @@ class ProviderAnthropic(Provider):
new_record = None
if prompt is not None:
new_record = await self.assemble_context(
- prompt, image_urls, extra_content_blocks
+ prompt, image_urls, extra_user_content_parts
)
context_query = self._ensure_message_to_dicts(contexts)
if new_record:
@@ -353,7 +353,7 @@ class ProviderAnthropic(Provider):
system_prompt=None,
tool_calls_result=None,
model=None,
- extra_content_blocks=None,
+ extra_user_content_parts=None,
**kwargs,
):
if contexts is None:
@@ -361,7 +361,7 @@ class ProviderAnthropic(Provider):
new_record = None
if prompt is not None:
new_record = await self.assemble_context(
- prompt, image_urls, extra_content_blocks
+ prompt, image_urls, extra_user_content_parts
)
context_query = self._ensure_message_to_dicts(contexts)
if new_record:
@@ -398,7 +398,7 @@ class ProviderAnthropic(Provider):
self,
text: str,
image_urls: list[str] | None = None,
- extra_content_blocks: list[dict] | None = None,
+ extra_user_content_parts: list[dict] | None = None,
):
"""组装上下文,支持文本和图片"""
content = []
@@ -409,15 +409,17 @@ class ProviderAnthropic(Provider):
elif image_urls:
# 如果没有文本但有图片,添加占位文本
content.append({"type": "text", "text": "[图片]"})
- elif extra_content_blocks:
+ elif extra_user_content_parts:
# 如果只有额外内容块,也需要添加占位文本
content.append({"type": "text", "text": " "})
# 2. 额外的内容块(系统提醒、指令等)
- if extra_content_blocks:
+ if extra_user_content_parts:
# 过滤出文本块,因为 Anthropic 主要支持文本和图片
text_blocks = [
- block for block in extra_content_blocks if block.get("type") == "text"
+ block
+ for block in extra_user_content_parts
+ if block.get("type") == "text"
]
content.extend(text_blocks)
@@ -460,7 +462,7 @@ class ProviderAnthropic(Provider):
# 如果只有主文本且没有额外内容块和图片,返回简单格式以保持向后兼容
if (
text
- and not extra_content_blocks
+ and not extra_user_content_parts
and not image_urls
and len(content) == 1
and content[0]["type"] == "text"
diff --git a/astrbot/core/provider/sources/gemini_source.py b/astrbot/core/provider/sources/gemini_source.py
index 918bb1f87..0dfe048de 100644
--- a/astrbot/core/provider/sources/gemini_source.py
+++ b/astrbot/core/provider/sources/gemini_source.py
@@ -680,7 +680,7 @@ class ProviderGoogleGenAI(Provider):
system_prompt=None,
tool_calls_result=None,
model=None,
- extra_content_blocks=None,
+ extra_user_content_parts=None,
**kwargs,
) -> LLMResponse:
if contexts is None:
@@ -688,7 +688,7 @@ class ProviderGoogleGenAI(Provider):
new_record = None
if prompt is not None:
new_record = await self.assemble_context(
- prompt, image_urls, extra_content_blocks
+ prompt, image_urls, extra_user_content_parts
)
context_query = self._ensure_message_to_dicts(contexts)
if new_record:
@@ -735,7 +735,7 @@ class ProviderGoogleGenAI(Provider):
system_prompt=None,
tool_calls_result=None,
model=None,
- extra_content_blocks=None,
+ extra_user_content_parts=None,
**kwargs,
) -> AsyncGenerator[LLMResponse, None]:
if contexts is None:
@@ -743,7 +743,7 @@ class ProviderGoogleGenAI(Provider):
new_record = None
if prompt is not None:
new_record = await self.assemble_context(
- prompt, image_urls, extra_content_blocks
+ prompt, image_urls, extra_user_content_parts
)
context_query = self._ensure_message_to_dicts(contexts)
if new_record:
@@ -807,7 +807,7 @@ class ProviderGoogleGenAI(Provider):
self,
text: str,
image_urls: list[str] | None = None,
- extra_content_blocks: list[dict] | None = None,
+ extra_user_content_parts: list[dict] | None = None,
):
"""组装上下文。"""
# 构建内容块列表
@@ -819,13 +819,13 @@ class ProviderGoogleGenAI(Provider):
elif image_urls:
# 如果没有文本但有图片,添加占位文本
content_blocks.append({"type": "text", "text": "[图片]"})
- elif extra_content_blocks:
+ elif extra_user_content_parts:
# 如果只有额外内容块,也需要添加占位文本
content_blocks.append({"type": "text", "text": " "})
# 2. 额外的内容块(系统提醒、指令等)
- if extra_content_blocks:
- content_blocks.extend(extra_content_blocks)
+ if extra_user_content_parts:
+ content_blocks.extend(extra_user_content_parts)
# 3. 图片内容
if image_urls:
@@ -851,7 +851,7 @@ class ProviderGoogleGenAI(Provider):
# 如果只有主文本且没有额外内容块和图片,返回简单格式以保持向后兼容
if (
text
- and not extra_content_blocks
+ and not extra_user_content_parts
and not image_urls
and len(content_blocks) == 1
and content_blocks[0]["type"] == "text"
diff --git a/astrbot/core/provider/sources/openai_source.py b/astrbot/core/provider/sources/openai_source.py
index 8a9346cef..5a7baf53f 100644
--- a/astrbot/core/provider/sources/openai_source.py
+++ b/astrbot/core/provider/sources/openai_source.py
@@ -348,7 +348,7 @@ class ProviderOpenAIOfficial(Provider):
system_prompt: str | None = None,
tool_calls_result: ToolCallsResult | list[ToolCallsResult] | None = None,
model: str | None = None,
- extra_content_blocks: list[dict] | None = None,
+ extra_user_content_parts: list[dict] | None = None,
**kwargs,
) -> tuple:
"""准备聊天所需的有效载荷和上下文"""
@@ -357,7 +357,7 @@ class ProviderOpenAIOfficial(Provider):
new_record = None
if prompt is not None:
new_record = await self.assemble_context(
- prompt, image_urls, extra_content_blocks
+ prompt, image_urls, extra_user_content_parts
)
context_query = self._ensure_message_to_dicts(contexts)
if new_record:
@@ -479,7 +479,7 @@ class ProviderOpenAIOfficial(Provider):
system_prompt=None,
tool_calls_result=None,
model=None,
- extra_content_blocks=None,
+ extra_user_content_parts=None,
**kwargs,
) -> LLMResponse:
payloads, context_query = await self._prepare_chat_payload(
@@ -489,7 +489,7 @@ class ProviderOpenAIOfficial(Provider):
system_prompt,
tool_calls_result,
model=model,
- extra_content_blocks=extra_content_blocks,
+ extra_user_content_parts=extra_user_content_parts,
**kwargs,
)
@@ -629,7 +629,7 @@ class ProviderOpenAIOfficial(Provider):
self,
text: str,
image_urls: list[str] | None = None,
- extra_content_blocks: list[dict] | None = None,
+ extra_user_content_parts: list[dict] | None = None,
) -> dict:
"""组装成符合 OpenAI 格式的 role 为 user 的消息段"""
# 构建内容块列表
@@ -641,13 +641,13 @@ class ProviderOpenAIOfficial(Provider):
elif image_urls:
# 如果没有文本但有图片,添加占位文本
content_blocks.append({"type": "text", "text": "[图片]"})
- elif extra_content_blocks:
+ elif extra_user_content_parts:
# 如果只有额外内容块,也需要添加占位文本
content_blocks.append({"type": "text", "text": " "})
# 2. 额外的内容块(系统提醒、指令等)
- if extra_content_blocks:
- content_blocks.extend(extra_content_blocks)
+ if extra_user_content_parts:
+ content_blocks.extend(extra_user_content_parts)
# 3. 图片内容
if image_urls:
@@ -673,7 +673,7 @@ class ProviderOpenAIOfficial(Provider):
# 如果只有主文本且没有额外内容块和图片,返回简单格式以保持向后兼容
if (
text
- and not extra_content_blocks
+ and not extra_user_content_parts
and not image_urls
and len(content_blocks) == 1
and content_blocks[0]["type"] == "text"
diff --git a/packages/astrbot/process_llm_request.py b/packages/astrbot/process_llm_request.py
index f787970c7..28d0a34f4 100644
--- a/packages/astrbot/process_llm_request.py
+++ b/packages/astrbot/process_llm_request.py
@@ -7,6 +7,7 @@ from astrbot.api import logger, sp, star
from astrbot.api.event import AstrMessageEvent
from astrbot.api.message_components import Image, Reply
from astrbot.api.provider import Provider, ProviderRequest
+from astrbot.core.agent.message import TextPart
from astrbot.core.provider.func_tool_manager import ToolSet
@@ -85,11 +86,8 @@ class ProcessLLMRequest:
req.image_urls,
)
if caption:
- req.extra_content_blocks.append(
- {
- "type": "text",
- "text": f"{caption}",
- }
+ req.extra_user_content_parts.append(
+ TextPart(text=f"{caption}")
)
req.image_urls = []
except Exception as e:
@@ -231,17 +229,17 @@ class ProcessLLMRequest:
except BaseException as e:
logger.error(f"处理引用图片失败: {e}")
- # 3. 将所有部分组合成文本并添加到 extra_content_blocks 中
+ # 3. 将所有部分组合成文本并添加到 extra_user_content_parts 中
# 确保引用内容被正确的标签包裹
quoted_content = "\n".join(content_parts)
# 确保所有内容都在标签内
quoted_text = f"\n{quoted_content}\n"
- req.extra_content_blocks.append({"type": "text", "text": quoted_text})
+ req.extra_user_content_parts.append(TextPart(text=quoted_text))
# 统一包裹所有系统提醒
if system_parts:
system_content = (
"" + "\n".join(system_parts) + ""
)
- req.extra_content_blocks.append({"type": "text", "text": system_content})
+ req.extra_user_content_parts.append(TextPart(text=system_content))