diff --git a/apps/llm/patterns/core.py b/apps/llm/patterns/core.py
index 4ef8133a9fed1b1e62f1ceb578c6bdb5a93b12a5..dec94f5d2ac4282d46a6ef349f3c72a6c0e98713 100644
--- a/apps/llm/patterns/core.py
+++ b/apps/llm/patterns/core.py
@@ -4,39 +4,41 @@
from abc import ABC, abstractmethod
from textwrap import dedent
+from apps.schemas.enum_var import LanguageType
+
class CorePattern(ABC):
"""基础大模型范式抽象类"""
- system_prompt: str = ""
- """系统提示词"""
- user_prompt: str = ""
- """用户提示词"""
- input_tokens: int = 0
- """输入Token数量"""
- output_tokens: int = 0
- """输出Token数量"""
-
+ @staticmethod
+ def _default() -> tuple[dict[LanguageType, str], dict[LanguageType, str]]:
+ """默认的Prompt内容;分别返回系统提示词和用户提示词"""
+ return {}, {}
- def __init__(self, system_prompt: str | None = None, user_prompt: str | None = None) -> None:
+ def __init__(
+ self,
+ system_prompt: dict[LanguageType, str] | None = None,
+ user_prompt: dict[LanguageType, str] | None = None,
+ ) -> None:
"""
检查是否已经自定义了Prompt;有的话就用自定义的;同时对Prompt进行空格清除
:param system_prompt: 系统提示词,f-string格式
:param user_prompt: 用户提示词,f-string格式
"""
+ self.input_tokens = 0
+ self.output_tokens = 0
+
+ self.system_prompt, self.user_prompt = self._default()
+
if system_prompt is not None:
self.system_prompt = system_prompt
if user_prompt is not None:
self.user_prompt = user_prompt
- if not self.user_prompt:
- err = "必须设置用户提示词!"
- raise ValueError(err)
-
- self.system_prompt = dedent(self.system_prompt).strip("\n")
- self.user_prompt = dedent(self.user_prompt).strip("\n")
+ self.system_prompt = {lang: dedent(prompt).strip("\n") for lang, prompt in self.system_prompt.items()}
+ self.user_prompt = {lang: dedent(prompt).strip("\n") for lang, prompt in self.user_prompt.items()}
@abstractmethod
async def generate(self, **kwargs): # noqa: ANN003, ANN201
diff --git a/apps/llm/patterns/executor.py b/apps/llm/patterns/executor.py
index 94d66575083f8c22de68f12bfe95f98137a58153..ecb514a6ea0770cb05a81d7a7e2d153c0721949e 100644
--- a/apps/llm/patterns/executor.py
+++ b/apps/llm/patterns/executor.py
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Any
from apps.llm.reasoning import ReasoningLLM
from apps.llm.snippet import convert_context_to_prompt, facts_to_prompt
+from apps.schemas.enum_var import LanguageType
from .core import CorePattern
@@ -15,40 +16,84 @@ if TYPE_CHECKING:
class ExecutorThought(CorePattern):
"""通过大模型生成Executor的思考内容"""
- user_prompt: str = r"""
-
-
- 你是一个可以使用工具的智能助手。
- 在回答用户的问题时,你为了获取更多的信息,使用了一个工具。
- 请简明扼要地总结工具的使用过程,提供你的见解,并给出下一步的行动。
-
- 注意:
- 工具的相关信息在标签中给出。
- 为了使你更好的理解发生了什么,你之前的思考过程在标签中给出。
- 输出时请不要包含XML标签,输出时请保持简明和清晰。
-
-
-
-
- {tool_name}
- {tool_description}
-
-
-
-
- {last_thought}
-
-
-
- 你当前需要解决的问题是:
- {user_question}
-
-
- 请综合以上信息,再次一步一步地进行思考,并给出见解和行动:
- """
- """用户提示词"""
-
- def __init__(self, system_prompt: str | None = None, user_prompt: str | None = None) -> None:
+ @staticmethod
+ def _default() -> tuple[dict[LanguageType, str], dict[LanguageType, str]]:
+ """默认的Prompt内容"""
+ return {
+ LanguageType.CHINESE: r"You are a helpful assistant.",
+ LanguageType.ENGLISH: r"You are a helpful assistant.",
+ }, {
+ LanguageType.CHINESE: r"""
+
+
+ 你是一个可以使用工具的智能助手。
+ 在回答用户的问题时,你为了获取更多的信息,使用了一个工具。
+ 请简明扼要地总结工具的使用过程,提供你的见解,并给出下一步的行动。
+
+ 注意:
+ 工具的相关信息在标签中给出。
+ 为了使你更好的理解发生了什么,你之前的思考过程在标签中给出。
+ 输出时请不要包含XML标签,输出时请保持简明和清晰。
+
+
+
+
+ {tool_name}
+ {tool_description}
+
+
+
+
+ {last_thought}
+
+
+
+ 你当前需要解决的问题是:
+ {user_question}
+
+
+ 请综合以上信息,再次一步一步地进行思考,并给出见解和行动:
+ """,
+ LanguageType.ENGLISH: r"""
+
+
+ You are an intelligent assistant who can use tools.
+ When answering user questions, you use a tool to get more information.
+ Please summarize the process of using the tool briefly, provide your insights, \
+and give the next action.
+
+ Note:
+ The information about the tool is given in the tag.
+ To help you better understand what happened, your previous thought process is given in the \
+ tag.
+ Do not include XML tags in the output, and keep the output brief and clear.
+
+
+
+
+ {tool_name}
+ {tool_description}
+
+
+
+
+ {last_thought}
+
+
+
+ The question you need to solve is:
+ {user_question}
+
+
+ Please integrate the above information, think step by step again, provide insights, and give actions:
+ """,
+ }
+
+ def __init__(
+ self,
+ system_prompt: dict[LanguageType, str] | None = None,
+ user_prompt: dict[LanguageType, str] | None = None,
+ ) -> None:
"""处理Prompt"""
super().__init__(system_prompt, user_prompt)
@@ -57,16 +102,20 @@ class ExecutorThought(CorePattern):
last_thought: str = kwargs["last_thought"]
user_question: str = kwargs["user_question"]
tool_info: dict[str, Any] = kwargs["tool_info"]
+ language: LanguageType = kwargs.get("language", LanguageType.CHINESE)
messages = [
{"role": "system", "content": "You are a helpful assistant."},
- {"role": "user", "content": self.user_prompt.format(
- last_thought=last_thought,
- user_question=user_question,
- tool_name=tool_info["name"],
- tool_description=tool_info["description"],
- tool_output=tool_info["output"],
- )},
+ {
+ "role": "user",
+ "content": self.user_prompt[language].format(
+ last_thought=last_thought,
+ user_question=user_question,
+ tool_name=tool_info["name"],
+ tool_description=tool_info["description"],
+ tool_output=tool_info["output"],
+ ),
+ },
]
llm = ReasoningLLM()
@@ -82,45 +131,76 @@ class ExecutorThought(CorePattern):
class ExecutorSummary(CorePattern):
"""使用大模型进行生成Executor初始背景"""
- user_prompt: str = r"""
-
- 根据给定的对话记录和关键事实,生成一个三句话背景总结。这个总结将用于后续对话的上下文理解。
-
- 生成总结的要求如下:
- 1. 突出重要信息点,例如时间、地点、人物、事件等。
- 2. “关键事实”中的内容可在生成总结时作为已知信息。
- 3. 输出时请不要包含XML标签,确保信息准确性,不得编造信息。
- 4. 总结应少于3句话,应少于300个字。
-
- 对话记录将在标签中给出,关键事实将在标签中给出。
-
-
- {conversation}
-
-
- {facts}
-
-
- 现在,请开始生成背景总结:
- """
- """用户提示词"""
-
- def __init__(self, system_prompt: str | None = None, user_prompt: str | None = None) -> None:
- """初始化Background模式"""
- super().__init__(system_prompt, user_prompt)
+ @staticmethod
+ def _default() -> tuple[dict[LanguageType, str], dict[LanguageType, str]]:
+ """默认的Prompt内容"""
+ return {
+ LanguageType.CHINESE: r"You are a helpful assistant.",
+ LanguageType.ENGLISH: r"You are a helpful assistant.",
+ }, {
+ LanguageType.CHINESE: r"""
+
+ 根据给定的对话记录和关键事实,生成一个三句话背景总结。这个总结将用于后续对话的上下文理解。
+
+ 生成总结的要求如下:
+ 1. 突出重要信息点,例如时间、地点、人物、事件等。
+ 2. “关键事实”中的内容可在生成总结时作为已知信息。
+ 3. 输出时请不要包含XML标签,确保信息准确性,不得编造信息。
+ 4. 总结应少于3句话,应少于300个字。
+
+ 对话记录将在标签中给出,关键事实将在标签中给出。
+
+
+ {conversation}
+
+
+ {facts}
+
+
+ 现在,请开始生成背景总结:
+ """,
+ LanguageType.ENGLISH: r"""
+
+ Based on the given conversation records and key facts, generate a three-sentence background \
+summary.This summary will be used for context understanding in subsequent conversations.
+
+ The requirements for generating the summary are as follows:
+ 1. Highlight important information points, such as time, location, people, events, etc.
+ 2. The content in the "key facts" can be used as known information when generating the summary.
+ 3. Do not include XML tags in the output, ensure the accuracy of the information, and do not \
+make up information.
+ 4. The summary should be less than 3 sentences and less than 300 words.
+
+ The conversation records will be given in the tag, and the key facts will be given \
+in the tag.
+
+
+ {conversation}
+
+
+ {facts}
+
+
+ Now, please start generating the background summary:
+ """,
+ }
async def generate(self, **kwargs) -> str: # noqa: ANN003
"""进行初始背景生成"""
background: ExecutorBackground = kwargs["background"]
conversation_str = convert_context_to_prompt(background.conversation)
facts_str = facts_to_prompt(background.facts)
+ language = kwargs.get("language", LanguageType.CHINESE)
messages = [
{"role": "system", "content": "You are a helpful assistant."},
- {"role": "user", "content": self.user_prompt.format(
- facts=facts_str,
- conversation=conversation_str,
- )},
+ {
+ "role": "user",
+ "content": self.user_prompt[language].format(
+ facts=facts_str,
+ conversation=conversation_str,
+ ),
+ },
]
result = ""
diff --git a/apps/llm/patterns/facts.py b/apps/llm/patterns/facts.py
index 0cafbc7752aa64c724c55770df640f8073038518..c8510b271491bb04be21f894e2956f9aa819e47e 100644
--- a/apps/llm/patterns/facts.py
+++ b/apps/llm/patterns/facts.py
@@ -8,6 +8,7 @@ from pydantic import BaseModel, Field
from apps.llm.function import JsonGenerator
from apps.llm.reasoning import ReasoningLLM
from apps.llm.snippet import convert_context_to_prompt
+from apps.schemas.enum_var import LanguageType
from .core import CorePattern
@@ -23,62 +24,112 @@ class FactsResult(BaseModel):
class Facts(CorePattern):
"""事实提取"""
- system_prompt: str = "You are a helpful assistant."
- """系统提示词(暂不使用)"""
-
- user_prompt: str = r"""
-
-
- 从对话中提取关键信息,并将它们组织成独一无二的、易于理解的事实,包含用户偏好、关系、实体等有用信息。
- 以下是需要关注的信息类型以及有关如何处理输入数据的详细说明。
-
- **你需要关注的信息类型**
- 1. 实体:对话中涉及到的实体。例如:姓名、地点、组织、事件等。
- 2. 偏好:对待实体的态度。例如喜欢、讨厌等。
- 3. 关系:用户与实体之间,或两个实体之间的关系。例如包含、并列、互斥等。
- 4. 动作:对实体产生影响的具体动作。例如查询、搜索、浏览、点击等。
-
- **要求**
- 1. 事实必须准确,只能从对话中提取。不要将样例中的信息体现在输出中。
- 2. 事实必须清晰、简洁、易于理解。必须少于30个字。
- 3. 必须按照以下JSON格式输出:
-
- {{
- "facts": ["事实1", "事实2", "事实3"]
- }}
-
-
-
-
- 杭州西湖有哪些景点?
- 杭州西湖是中国浙江省杭州市的一个著名景点,以其美丽的自然风光和丰富的文化遗产而闻名。西湖周围有许多著名的景点,包括著名的苏堤、白堤、断桥、三潭印月等。西湖以其清澈的湖水和周围的山脉而著名,是中国最著名的湖泊之一。
-
-
+ @staticmethod
+ def _default() -> tuple[dict[LanguageType, str], dict[LanguageType, str]]:
+ """默认的Prompt内容"""
+ return {
+ LanguageType.CHINESE: r"You are a helpful assistant.",
+ LanguageType.ENGLISH: r"You are a helpful assistant.",
+ }, {
+ LanguageType.CHINESE: r"""
+
+
+ 从对话中提取关键信息,并将它们组织成独一无二的、易于理解的事实,包含用户偏好、关系、实体等有用信息。
+ 以下是需要关注的信息类型以及有关如何处理输入数据的详细说明。
+
+ **你需要关注的信息类型**
+ 1. 实体:对话中涉及到的实体。例如:姓名、地点、组织、事件等。
+ 2. 偏好:对待实体的态度。例如喜欢、讨厌等。
+ 3. 关系:用户与实体之间,或两个实体之间的关系。例如包含、并列、互斥等。
+ 4. 动作:对实体产生影响的具体动作。例如查询、搜索、浏览、点击等。
+
+ **要求**
+ 1. 事实必须准确,只能从对话中提取。不要将样例中的信息体现在输出中。
+ 2. 事实必须清晰、简洁、易于理解。必须少于30个字。
+ 3. 必须按照以下JSON格式输出:
+
+ {{
+ "facts": ["事实1", "事实2", "事实3"]
+ }}
+
+
+
+
+ 杭州西湖有哪些景点?
+ 杭州西湖是中国浙江省杭州市的一个著名景点,以其美丽的自然风光和丰富的文化遗产而闻名。\
+西湖周围有许多著名的景点,包括著名的苏堤、白堤、断桥、三潭印月等。西湖以其清澈的湖水和周围的山脉而著名,是中国最著名的湖泊之一。
+
+
+
+
+
+
+ {conversation}
-
-
-
- {conversation}
-