fix(prompt-optimizer): switch to built-in system prompt

- Replace the system prompt of the prompt optimization model with a built-in prompt.
- Remove system prompt entries from the database.
- Remove the API endpoint for managing system prompt configuration.
This commit is contained in:
mengyonghao
2025-12-19 14:08:54 +08:00
committed by 谢俊男
parent 15fac38e30
commit 5cd46e441e
5 changed files with 86 additions and 269 deletions

View File

@@ -117,7 +117,7 @@ async def get_prompt_opt(
session_id=session_id,
user_id=current_user.id,
current_prompt=data.current_prompt,
message=data.message
user_require=data.message
)
service.create_message(
tenant_id=current_user.tenant_id,
@@ -136,35 +136,3 @@ async def get_prompt_opt(
return success(data=result_schema)
@router.put(
"/model",
summary="Create or update prompt model config",
response_model=ApiResponse
)
def set_system_prompt(
data: PromptOptModelSet = ...,
db: Session = Depends(get_db),
current_user=Depends(get_current_user),
):
"""
Create or update a system prompt model configuration for the tenant.
Args:
data (PromptOptModelSet): Model configuration data including model ID,
system prompt, and optional configuration ID
db (Session): Database session
current_user: Current user information
Returns:
UUID: The ID of the created or updated model configuration.
"""
if data.id is None:
data.id = uuid.uuid4()
model_config = PromptOptimizerService(db).create_update_model_config(
current_user.tenant_id,
data.id,
data.system_prompt
)
return success(data=model_config.id)

View File

@@ -20,7 +20,7 @@ from .data_config_model import DataConfig
from .multi_agent_model import MultiAgentConfig, AgentInvocation
from .workflow_model import WorkflowConfig, WorkflowExecution, WorkflowNodeExecution
from .retrieval_info import RetrievalInfo
from .prompt_optimizer_model import PromptOptimizerModelConfig, PromptOptimizerSession, PromptOptimizerSessionHistory
from .prompt_optimizer_model import PromptOptimizerSession, PromptOptimizerSessionHistory
from .tool_model import (
ToolConfig, BuiltinToolConfig, CustomToolConfig, MCPToolConfig,
ToolExecution, ToolType, ToolStatus, AuthType, ExecutionStatus
@@ -60,7 +60,6 @@ __all__ = [
"WorkflowExecution",
"WorkflowNodeExecution",
"RetrievalInfo",
"PromptOptimizerModelConfig",
"PromptOptimizerSession",
"PromptOptimizerSessionHistory",
"RetrievalInfo",

View File

@@ -27,49 +27,6 @@ class RoleType(StrEnum):
ASSISTANT = "assistant"
class PromptOptimizerModelConfig(Base):
"""
Prompt Optimization Model Configuration.
This table stores system-level prompt configurations for each tenant.
The configuration defines the base system prompt used during prompt
optimization sessions and serves as a foundational instruction set
for the optimization process.
Each tenant may have one or more model configurations depending on
business requirements.
Table Name:
prompt_model_config
Columns:
id (UUID):
Primary key. Unique identifier for the prompt model configuration.
tenant_id (UUID):
Foreign key referencing `tenants.id`.
Identifies the tenant that owns this configuration.
system_prompt (Text):
The system-level prompt used to guide prompt optimization logic.
created_at (DateTime):
Timestamp indicating when the configuration was created.
updated_at (DateTime):
Timestamp indicating the last update time of the configuration.
Usage:
- Loaded when initializing a prompt optimization session
- Acts as the root system instruction for all subsequent prompts
"""
__tablename__ = "prompt_model_config"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id"), nullable=False, comment="Tenant ID")
# model_id = Column(UUID(as_uuid=True), nullable=False, comment="Model ID")
system_prompt = Column(Text, nullable=False, comment="System Prompt")
created_at = Column(DateTime, default=datetime.datetime.now, comment="Creation Time")
updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now, comment="Update Time")
class PromptOptimizerSession(Base):
"""
Prompt Optimization Session Registry.

View File

@@ -1,120 +1,15 @@
import uuid
from typing import Optional
from sqlalchemy.orm import Session
from app.core.logging_config import get_db_logger
from app.models.prompt_optimizer_model import (
PromptOptimizerModelConfig,
PromptOptimizerSession, PromptOptimizerSessionHistory, RoleType
)
db_logger = get_db_logger()
class PromptOptimizerModelConfigRepository:
"""Repository for managing prompt optimizer model configurations."""
def __init__(self, db: Session):
self.db = db
def get_by_tenant_id(self, tenant_id: uuid.UUID) -> Optional[PromptOptimizerModelConfig]:
"""
Retrieve the prompt optimizer model configuration for a specific tenant.
Args:
tenant_id (uuid.UUID): The unique identifier of the tenant.
Returns:
Optional[PromptOptimizerModelConfig]: The model configuration if found, else None.
"""
db_logger.debug(f"Get prompt optimization model configuration: tenant_id={tenant_id}")
try:
config = self.db.query(PromptOptimizerModelConfig).filter(
PromptOptimizerModelConfig.tenant_id == tenant_id,
# PromptOptimizerModelConfig.model_id == model_id
).first()
if config:
db_logger.debug(f"Prompt optimization model configuration found: (ID: {config.id})")
else:
db_logger.debug(f"Prompt optimization model configuration not found: tenant_id={tenant_id}")
return config
except Exception as e:
db_logger.error(
f"Error retrieving prompt optimization model configuration: tenant_id={tenant_id} - {str(e)}")
raise
def get_by_config_id(self, tenant_id: uuid.UUID, config_id: uuid.UUID) -> Optional[PromptOptimizerModelConfig]:
"""
Retrieve a specific prompt optimizer model configuration by config ID and tenant ID.
Args:
tenant_id (uuid.UUID): The unique identifier of the tenant.
config_id (uuid.UUID): The unique identifier of the model configuration.
Returns:
Optional[PromptOptimizerModelConfig]: The model configuration if found, else None.
"""
db_logger.debug(f"Get prompt optimization model configuration: config_id={config_id}, tenant_id={tenant_id}")
try:
model = self.db.query(PromptOptimizerModelConfig).filter(
PromptOptimizerModelConfig.tenant_id == tenant_id,
PromptOptimizerModelConfig.id == config_id
).first()
if model:
db_logger.debug(f"Prompt optimization model configuration found: (ID: {model.id})")
else:
db_logger.debug(f"Prompt optimization model configuration not found: config_id={config_id}")
return model
except Exception as e:
db_logger.error(
f"Error retrieving prompt optimization model configuration: model_id={config_id} - {str(e)}")
raise
def create_or_update(
self,
config_id: uuid.UUID,
tenant_id: uuid.UUID,
system_prompt: str,
) -> Optional[PromptOptimizerModelConfig]:
"""
Create a new or update an existing prompt optimizer model configuration.
If a configuration with the given config_id exists, it updates its system_prompt.
Otherwise, it creates a new configuration record.
Args:
config_id (uuid.UUID): The unique identifier for the configuration.
tenant_id (uuid.UUID): The tenant's unique identifier.
system_prompt (str): The system prompt content for prompt optimization.
Returns:
Optional[PromptOptimizerModelConfig]: The created or updated model configuration.
"""
db_logger.debug(f"Create/Update prompt optimization model configuration: tenant_id={tenant_id}")
existing_config = self.get_by_config_id(tenant_id, config_id)
if existing_config:
existing_config.system_prompt = system_prompt
self.db.commit()
self.db.refresh(existing_config)
db_logger.debug(f"Prompt optimization model configuration update: ID:{config_id}")
return existing_config
else:
config = PromptOptimizerModelConfig(
id=config_id,
# model_id=model_id,
tenant_id=tenant_id,
system_prompt=system_prompt
)
self.db.add(config)
self.db.commit()
self.db.refresh(config)
db_logger.debug(f"Prompt optimization model configuration created: ID:{config.id}")
return config
class PromptOptimizerSessionRepository:
"""Repository for managing prompt optimization sessions and session history."""

View File

@@ -1,4 +1,3 @@
import json
import re
import uuid
@@ -12,13 +11,11 @@ from app.core.models import RedBearModelConfig
from app.core.models.llm import RedBearLLM
from app.models import ModelConfig, ModelApiKey, ModelType, PromptOptimizerSessionHistory
from app.models.prompt_optimizer_model import (
PromptOptimizerModelConfig,
PromptOptimizerSession,
RoleType
)
from app.repositories.model_repository import ModelConfigRepository
from app.repositories.prompt_optimizer_repository import (
PromptOptimizerModelConfigRepository,
PromptOptimizerSessionRepository
)
from app.schemas.prompt_optimizer_schema import OptimizePromptResult
@@ -34,32 +31,24 @@ class PromptOptimizerService:
self,
tenant_id: uuid.UUID,
model_id: uuid.UUID
) -> tuple[PromptOptimizerModelConfig, ModelConfig]:
) -> ModelConfig:
"""
Retrieve the prompt optimizer model configuration and model configuration.
Retrieve the model configuration for a specific tenant.
This method retrieves the prompt optimizer model configuration associated
with the specified model ID and tenant. It also fetches the corresponding
model configuration.
This method fetches the model configuration associated with the given
tenant_id and model_id. If no configuration is found, a BusinessException
is raised.
Args:
tenant_id (uuid.UUID): The unique identifier of the tenant.
model_id (uuid.UUID): The unique identifier of the prompt optimization model.
model_id (uuid.UUID): The unique identifier of the model.
Returns:
tuple[PromptOptimzerModelConfig, ModelConfig]:
A tuple containing the prompt optimizer model configuration
and the corresponding model configuration.
ModelConfig: The corresponding model configuration object.
Raises:
BusinessException: If the prompt optimizer model configuration does not exist.
BusinessException: If the model configuration does not exist.
"""
prompt_config = PromptOptimizerModelConfigRepository(self.db).get_by_tenant_id(
tenant_id
)
if not prompt_config:
raise BusinessException("提示词模型配置不存在", BizCode.NOT_FOUND)
model = ModelConfigRepository.get_by_id(
self.db, model_id, tenant_id=tenant_id
@@ -67,35 +56,7 @@ class PromptOptimizerService:
if not model:
raise BusinessException("模型配置不存在", BizCode.MODEL_NOT_FOUND)
return prompt_config, model
def create_update_model_config(
self,
tenant_id: uuid.UUID,
config_id: uuid.UUID,
system_prompt: str,
) -> PromptOptimizerModelConfig:
"""
Create or update a prompt optimizer model configuration.
This method creates a new prompt optimizer model configuration or updates
an existing one identified by the given configuration ID. The configuration
defines the system prompt used for prompt optimization.
Args:
tenant_id (uuid.UUID): The unique identifier of the tenant.
config_id (uuid.UUID): The unique identifier of the configuration to create or update.
system_prompt (str): The system prompt content used for prompt optimization.
Returns:
PromptOptimzerModelConfig: The created or updated prompt optimizer model configuration.
"""
prompt_config = PromptOptimizerModelConfigRepository(self.db).create_or_update(
config_id=config_id,
tenant_id=tenant_id,
system_prompt=system_prompt,
)
return prompt_config
return model
def create_session(
self,
@@ -159,37 +120,46 @@ class PromptOptimizerService:
session_id: uuid.UUID,
user_id: uuid.UUID,
current_prompt: str,
message: str
user_require: str
) -> OptimizePromptResult:
"""
Optimize a prompt using a prompt optimizer LLM.
Optimize a user-provided prompt using a configured prompt optimizer LLM.
This method uses a configured prompt optimizer model to refine an existing
prompt based on the user's requirements. The optimized prompt is generated
according to predefined system rules, including Jinja2 variable syntax and
a strict JSON output format.
This method refines the original prompt according to the user's requirements,
generating an optimized version that is directly usable by AI tools. The
optimization process follows strict rules, including:
- Wrapping user-inserted variables in double curly braces {{}}.
- Adhering to Jinja2 variable syntax if applicable.
- Ensuring a clear logic flow, explicit instructions, and strong executability.
- Producing output in a strict JSON format.
Steps performed:
1. Retrieve the model configuration for the given tenant and model.
2. Fetch the session message history for context.
3. Instantiate the LLM with the appropriate API key and model configuration.
4. Build system messages outlining optimization rules.
5. Format the user's original prompt and requirements as a user message.
6. Send messages to the LLM to generate the optimized prompt.
7. Generate a concise description summarizing the changes made during optimization.
Args:
tenant_id (uuid.UUID): The unique identifier of the tenant.
model_id (uuid.UUID): The unique identifier of the prompt optimizer model.
session_id (uuid.UUID): The unique identifier of the prompt optimization session.
user_id (uuid.UUID): The unique identifier of the user associated with the session.
current_prompt (str): The original prompt to be optimized.
message (str): The user's requirements or modification instructions.
tenant_id (uuid.UUID): Tenant identifier.
model_id (uuid.UUID): Prompt optimizer model identifier.
session_id (uuid.UUID): Prompt optimization session identifier.
user_id (uuid.UUID): Identifier of the user associated with the session.
current_prompt (str): Original prompt to optimize.
user_require (str): User's requirements or instructions for optimization.
Returns:
dict: A dictionary containing the optimized prompt and the description
of changes, in the following format:
{
"prompt": "<optimized_prompt>",
"desc": "<change_description>"
}
OptimizePromptResult: An object containing:
- prompt: The optimized prompt string.
- desc: A short description summarizing the changes.
Raises:
BusinessException: If the model response cannot be parsed as valid JSON
BusinessException: If the LLM response cannot be parsed as valid JSON
or does not conform to the expected output format.
"""
prompt_config, model_config = self.get_model_config(tenant_id, model_id)
model_config = self.get_model_config(tenant_id, model_id)
session_history = self.get_session_message_history(session_id=session_id, user_id=user_id)
# Create LLM instance
@@ -204,36 +174,65 @@ class PromptOptimizerService:
# build message
messages = [
# init system_prompt
(RoleType.SYSTEM.value, prompt_config.system_prompt),
(
RoleType.SYSTEM.value,
"Your task is to optimize the original prompt provided by the user so that it can be directly used by AI tools,"
"and the variables that the user needs to insert must be wrapped in {{}}. "
"The optimized prompt should align with the optimization direction specified by the user (if any) and ensure clear logic, explicit instructions, and strong executability. "
"Please follow these rules when optimizing: "
'1. Ensure variables are wrapped in {{}}, e.g., optimize "Please enter your question" to "Please enter your {{question}}"'
"2. Instructions must be specific and operable, avoiding vague expressions"
"3. If the original prompt lacks key elements (such as output format requirements), supplement them completely "
"4. Keep the language concise and avoid redundancy "
"5. If the user does not specify an optimization direction, the default optimization is to make the prompt structurally clear and with explicit instructions"
"Please directly output the optimized prompt without additional explanations. The optimized prompt should be directly usable with correct variable positions."
),
# base model limit
(RoleType.SYSTEM.value,
"Optimization Rules:\n"
"1. Fully adjust the prompt content according to the user's requirements.\n"
"2. When the user requests the insertion of variables, you must use Jinja2 syntax {{variable_name}} "
"(the variable name should be determined based on the user's requirement).\n"
"When variables are required, use double curly braces {{variable_name}} as placeholders."
"Variable names must be derived from the user's requirements.\n"
"3. Keep the prompt logic clear and instructions explicit.\n"
"4. Ensure that the modified prompt can be directly used.\n\n"
"Output Requirements:\n"
"Provide the result in JSON format, containing exactly two fields:\n"
" - prompt: The modified prompt (string).\n"
" - desc: A response addressing the user's optimization request (string).")
"4. Ensure that the modified prompt can be directly used.\n\n")
]
messages.extend(session_history[:-1]) # last message is current message
user_message_template = ChatPromptTemplate.from_messages([
(RoleType.USER.value, "[current_prompt]\n{current_prompt}\n[user_require]\n{message}")
(RoleType.USER.value, "[original_prompt]\n{current_prompt}\n[user_require]\n{user_require}")
])
formatted_user_message = user_message_template.format(current_prompt=current_prompt, message=message)
formatted_user_message = user_message_template.format(current_prompt=current_prompt, user_require=user_require)
messages.extend([(RoleType.USER.value, formatted_user_message)])
logger.info(f"Prompt optimization message: {messages}")
result = await llm.ainvoke(messages)
try:
data_dict = json.loads(result.content)
model_resp = OptimizePromptResult.model_validate(data_dict)
except Exception as e:
logger.error(f"Failed to parse model reponse to json - Error: {str(e)}", exc_info=True)
raise BusinessException("Failed to parse model response", BizCode.PARSER_NOT_SUPPORTED)
return model_resp
optim_prompt = await llm.ainvoke(messages)
optim_desc = [
(
RoleType.SYSTEM.value,
"You are a prompt optimization assistant.\n"
"Compare the original prompt, the user's requirements, "
"and the optimized prompt.\n"
"Summarize the changes made during optimization.\n\n"
"Rules:\n"
"1. Output must be a single short sentence.\n"
"2. Be concise and factual.\n"
"3. Do not explain the prompts themselves.\n"
"4. Do not include any extra text."
),
(
"[Original Prompt]\n"
f"{current_prompt}\n\n"
"[User Requirements]\n"
f"{user_require}\n\n"
"[Optimized Prompt]\n"
f"{optim_prompt.content}"
)
]
optim_desc = await llm.ainvoke(optim_desc)
return OptimizePromptResult(
prompt=optim_prompt.content,
desc=optim_desc.content
)
@staticmethod
def parser_prompt_variables(prompt: str):
@@ -277,4 +276,3 @@ class PromptOptimizerService:
content=content
)
return message