docs: system prompt guide

This commit is contained in:
Soulter
2026-05-03 20:14:15 +08:00
parent f2370cd1ba
commit 6eb8a51c70
3 changed files with 86 additions and 4 deletions

View File

@@ -266,10 +266,37 @@ from astrbot.api.provider import ProviderRequest
@filter.on_llm_request()
async def my_custom_hook_1(self, event: AstrMessageEvent, req: ProviderRequest): # Note there are three parameters
print(req) # Print the request text
req.system_prompt += "Custom system_prompt"
req.system_prompt += "Custom system_prompt" # If there is another suitable approach, avoid using this to append prompts that change every round. It can break prompt caching and greatly increase cost (7 - 20x).
```
> [!WARNING]
> **About appending prompts**
>
> `req.system_prompt += ...` is suitable for stable, long-lived role settings or global rules. Do not append content that changes every round to `system_prompt`, such as the current time, affinity score, status panel, short-term memory snippets, or retrieval summaries. Doing so makes the system prompt different for each request, which can break provider-side prompt caching and significantly increase both cost and time to first token.
>
> For small or medium-sized dynamic prompts that change every round, prefer appending them through `req.extra_user_content_parts`. These parts are added after the current user input as extra user-message content, which is more suitable for dynamic context such as "current time", "character affinity", or "relevant memory snippets":
>
> ```python
> from astrbot.core.agent.message import TextPart
>
> @filter.on_llm_request()
> async def add_dynamic_prompt(self, event: AstrMessageEvent, req: ProviderRequest):
> req.extra_user_content_parts.append(
> TextPart(
> text=(
> "<dynamic_context>\n"
> "Current time: 2026-05-03 20:00\n"
> "Affinity: 72\n"
> "Relevant memory: The user prefers concise and direct answers.\n"
> "</dynamic_context>"
> )
> )
> )
> ```
>
> For long-term memory, knowledge bases, or external system queries that may be large or unnecessary for every round, do not put everything directly into the prompt. Prefer registering them as `llm_tool` functions so the model can call them when needed, or retrieve only a small relevant summary in your plugin and append that summary through `extra_user_content_parts`.
> You cannot use yield to send messages here. If you need to send, please use the `event.send()` method directly.
#### On LLM Response Complete

View File

@@ -269,6 +269,8 @@ async def on_waiting_llm(self, event: AstrMessageEvent):
#### LLM 请求时
> 这里不能使用 yield 来发送消息。如需发送,请直接使用 `event.send()` 方法。
在 AstrBot 默认的执行流程中,在调用 LLM 前,会触发 `on_llm_request` 钩子。
可以获取到 `ProviderRequest` 对象,可以对其进行修改。
@@ -282,11 +284,37 @@ from astrbot.api.provider import ProviderRequest
@filter.on_llm_request()
async def my_custom_hook_1(self, event: AstrMessageEvent, req: ProviderRequest): # 请注意有三个参数
print(req) # 打印请求的文本
req.system_prompt += "自定义 system_prompt"
req.system_prompt += "自定义 system_prompt" # 如果有其他替代方法,不建议使用此种方式来追加每轮对话都会改变的提示词,否则会破坏缓存,大大增加价格(约增加 7-20 倍的价格)。
req.extra_user_content_parts.append(...)
```
> 这里不能使用 yield 来发送消息。如需发送,请直接使用 `event.send()` 方法。
> [!WARNING]
> **关于提示词的追加**
>
> `req.system_prompt += ...` 适合追加稳定、长期有效的角色设定或全局规则。不建议把每轮都会变化的内容追加到 `system_prompt`,例如当前时间、好感度、状态栏、短期记忆片段、检索摘要等。这类写法会让系统提示词在每轮请求中变化,容易破坏模型服务端的提示词缓存,显著增加请求成本和首 token 延迟。
>
> 对于每轮都会变化、内容量中小的提示词,优先通过 `req.extra_user_content_parts` 追加。它会作为额外的用户消息内容块放在本轮用户输入之后,更适合承载"当前时间""角色好感度""本轮相关记忆片段"等动态上下文:
>
> ```python
> from astrbot.core.agent.message import TextPart
>
> @filter.on_llm_request()
> async def add_dynamic_prompt(self, event: AstrMessageEvent, req: ProviderRequest):
> req.extra_user_content_parts.append(
> TextPart(
> text=(
> "<dynamic_context>\n"
> "当前时间2026-05-03 20:00\n"
> "好感度72\n"
> "相关记忆:用户喜欢简洁直接的回答。\n"
> "</dynamic_context>"
> )
> )
> )
> ```
>
> 对于长期记忆、知识库、外部系统查询等内容量较大或不一定每轮都需要的信息,不建议全部塞进提示词。可以优先注册为 `llm_tool`,让模型在需要时调用;也可以先在插件中检索出本轮真正相关的少量摘要,再放入 `extra_user_content_parts`。
#### LLM 请求完成时

View File

@@ -519,10 +519,37 @@ from astrbot.api.provider import ProviderRequest
@filter.on_llm_request()
async def my_custom_hook_1(self, event: AstrMessageEvent, req: ProviderRequest): # 请注意有三个参数
print(req) # 打印请求的文本
req.system_prompt += "自定义 system_prompt"
req.system_prompt += "自定义 system_prompt" # 如果有其他替代方法,不建议使用此种方式来追加每轮对话都会改变的提示词,否则会破坏缓存,大大增加价格(约增加 7-20 倍的价格)。
```
> [!WARNING]
> **关于提示词的追加**
>
> `req.system_prompt += ...` 适合追加稳定、长期有效的角色设定或全局规则。不建议把每轮都会变化的内容追加到 `system_prompt`,例如当前时间、好感度、状态栏、短期记忆片段、检索摘要等。这类写法会让系统提示词在每轮请求中变化,容易破坏模型服务端的提示词缓存,显著增加请求成本和首 token 延迟。
>
> 对于每轮都会变化、内容量中小的提示词,优先通过 `req.extra_user_content_parts` 追加。它会作为额外的用户消息内容块放在本轮用户输入之后,更适合承载"当前时间""角色好感度""本轮相关记忆片段"等动态上下文:
>
> ```python
> from astrbot.core.agent.message import TextPart
>
> @filter.on_llm_request()
> async def add_dynamic_prompt(self, event: AstrMessageEvent, req: ProviderRequest):
> req.extra_user_content_parts.append(
> TextPart(
> text=(
> "<dynamic_context>\n"
> "当前时间2026-05-03 20:00\n"
> "好感度72\n"
> "相关记忆:用户喜欢简洁直接的回答。\n"
> "</dynamic_context>"
> )
> )
> )
> ```
>
> 对于长期记忆、知识库、外部系统查询等内容量较大或不一定每轮都需要的信息,不建议全部塞进提示词。可以优先注册为 `llm_tool`,让模型在需要时调用;也可以先在插件中检索出本轮真正相关的少量摘要,再放入 `extra_user_content_parts`。
> 这里不能使用 yield 来发送消息。如需发送,请直接使用 `event.send()` 方法。
##### LLM 请求完成时