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:
@@ -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)
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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."""
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user