perf(prompt_opt): improve prompt optimization and model output quality
This commit is contained in:
@@ -19,6 +19,7 @@ from app.core.workflow.nodes.llm.config import LLMNodeConfig, MessageConfig
|
||||
from app.core.workflow.nodes.start.config import StartNodeConfig
|
||||
from app.core.workflow.nodes.transform.config import TransformNodeConfig
|
||||
from app.core.workflow.nodes.variable_aggregator.config import VariableAggregatorNodeConfig
|
||||
from app.core.workflow.nodes.parameter_extractor.config import ParameterExtractorNodeConfig
|
||||
|
||||
__all__ = [
|
||||
# 基础类
|
||||
@@ -38,4 +39,5 @@ __all__ = [
|
||||
"HttpRequestNodeConfig",
|
||||
"JinjaRenderNodeConfig",
|
||||
"VariableAggregatorNodeConfig",
|
||||
"ParameterExtractorNodeConfig",
|
||||
]
|
||||
|
||||
@@ -68,10 +68,10 @@ class ParameterExtractorNode(BaseNode):
|
||||
config = ModelConfigService.get_model_by_id(db=db, model_id=model_id)
|
||||
|
||||
if not config:
|
||||
raise BusinessException("配置的模型不存在", BizCode.NOT_FOUND)
|
||||
raise BusinessException("Configured model does not exist", BizCode.NOT_FOUND)
|
||||
|
||||
if not config.api_keys or len(config.api_keys) == 0:
|
||||
raise BusinessException("模型配置缺少 API Key", BizCode.INVALID_PARAMETER)
|
||||
raise BusinessException("Model configuration is missing API Key", BizCode.INVALID_PARAMETER)
|
||||
|
||||
api_config = config.api_keys[0]
|
||||
model_name = api_config.model_name
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import re
|
||||
import uuid
|
||||
|
||||
import json_repair
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
from sqlalchemy.orm import Session
|
||||
from jinja2 import Template
|
||||
|
||||
from app.core.error_codes import BizCode
|
||||
from app.core.exceptions import BusinessException
|
||||
@@ -170,68 +172,45 @@ class PromptOptimizerService:
|
||||
api_key=api_config.api_key,
|
||||
base_url=api_config.api_base
|
||||
), type=ModelType(model_config.type))
|
||||
try:
|
||||
with open('app/templates/prompt/prompt_optimizer_system.jinja2', 'r', encoding='utf-8') as f:
|
||||
opt_system_prompt = f.read()
|
||||
rendered_system_message = Template(opt_system_prompt).render()
|
||||
|
||||
with open('app/templates/prompt/prompt_optimizer_user.jinja2', 'r', encoding='utf-8') as f:
|
||||
opt_user_prompt = f.read()
|
||||
except FileNotFoundError:
|
||||
raise BusinessException(message="System prompt template not found", code=BizCode.NOT_FOUND)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to load system prompt template: {e}")
|
||||
raise BusinessException(message="Internal server error", code=BizCode.INTERNAL_ERROR)
|
||||
rendered_user_message = Template(opt_user_prompt).render(
|
||||
current_prompt=current_prompt,
|
||||
user_require=user_require
|
||||
)
|
||||
|
||||
# build message
|
||||
messages = [
|
||||
# init 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."
|
||||
rendered_system_message
|
||||
),
|
||||
]
|
||||
|
||||
# base model limit
|
||||
(RoleType.SYSTEM.value,
|
||||
"Optimization Rules:\n"
|
||||
"1. Fully adjust the prompt content according to the user's requirements.\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")
|
||||
]
|
||||
messages.extend(session_history[:-1]) # last message is current message
|
||||
user_message_template = ChatPromptTemplate.from_messages([
|
||||
(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, user_require=user_require)
|
||||
messages.extend([(RoleType.USER.value, formatted_user_message)])
|
||||
messages.extend([(RoleType.USER.value, rendered_user_message)])
|
||||
logger.info(f"Prompt optimization message: {messages}")
|
||||
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)
|
||||
optim_resp = await llm.ainvoke(messages)
|
||||
logger.info(optim_resp.content)
|
||||
optim_result = json_repair.repair_json(optim_resp.content, return_objects=True)
|
||||
prompt = optim_result.get("prompt")
|
||||
desc = optim_result.get("desc")
|
||||
|
||||
return OptimizePromptResult(
|
||||
prompt=optim_prompt.content,
|
||||
desc=optim_desc.content
|
||||
prompt=prompt,
|
||||
desc=desc
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -253,6 +232,7 @@ class PromptOptimizerService:
|
||||
def replace_var(match):
|
||||
var_name = match.group(1)
|
||||
return variables.get(var_name, match.group(0))
|
||||
|
||||
result = re.sub(pattern, replace_var, prompt)
|
||||
return result
|
||||
except Exception as e:
|
||||
|
||||
54
api/app/templates/prompt/prompt_optimizer_system.jinja2
Normal file
54
api/app/templates/prompt/prompt_optimizer_system.jinja2
Normal file
@@ -0,0 +1,54 @@
|
||||
{% raw %}
|
||||
Role: AI Prompt Optimization Expert
|
||||
|
||||
Profile
|
||||
description: An expert specialized in optimizing and generating prompts that can be directly used in AI tools, capable of transforming original prompts into a clear, immediately executable format based on user requirements.
|
||||
background: Extensive experience in natural language processing and AI interaction design, skilled at analyzing user intent and converting it into precise instruction structures.
|
||||
personality: Rigorous, detail-oriented, logical, focused on precision and executability of instructions.
|
||||
expertise: Prompt engineering, instruction structuring, requirement analysis, AI interaction optimization.
|
||||
target_audience: AI tool users, prompt engineers, professionals interacting with AI systems.
|
||||
|
||||
Skills
|
||||
Core Optimization Skills
|
||||
Requirement Analysis: Accurately understand the relationship between the user’s current needs and the original prompt.
|
||||
Structural Reconstruction: Transform vague requirements into clear, block-structured instructions.
|
||||
Variable Handling: Identify and standardize dynamic variables in prompts.
|
||||
Conflict Resolution: Prioritize current requirements when historical requirements conflict with current needs.
|
||||
|
||||
Auxiliary Generation Skills
|
||||
Completeness Check: Ensure all necessary elements (input, output, constraints, etc.) are explicitly defined.
|
||||
Language Consistency: Maintain consistency between label language and user input language.
|
||||
Executability Verification: Ensure optimized prompts can be directly used in AI tools.
|
||||
Format Standardization: Strictly adhere to specified output format requirements.
|
||||
|
||||
Rules
|
||||
Basic Principles
|
||||
Priority Rule: When historical requirements conflict with current requirements, unconditionally prioritize current requirements.
|
||||
Completeness Rule: If the original prompt is empty, generate a complete prompt based on the current requirements.
|
||||
Structure Rule: Use a clear block structure including [Role], [Task], [Requirements], [Input], [Output], [Constraints] labels.
|
||||
Language Rule: All label languages must fully match the user input language.
|
||||
|
||||
Behavior Guidelines
|
||||
Precision Guideline: All instructions must be precise and directly executable, avoiding ambiguity.
|
||||
Readability Guideline: Ensure optimized prompts have good readability and logical flow.
|
||||
Variable Handling Guideline: Use lowercase English variable names wrapped in {{}} when variables are needed.
|
||||
Constraint Handling Guideline: Do not mention variable-related limitations under the [Constraints] label.
|
||||
|
||||
Constraints
|
||||
Output Constraint: Must output in JSON format including the fields "prompt" and "desc".
|
||||
Content Constraint: Must not include any explanations, analyses, or additional comments.
|
||||
Language Constraint: Must use clear and concise language.
|
||||
Completeness Constraint: Must fully define all missing elements (input details, output format, constraints, etc.).
|
||||
|
||||
Workflows
|
||||
Goal: Optimize or generate AI prompts that can be directly used according to user requirements.
|
||||
Step 1: Receive the user’s current requirement description {{user_require}} and the original prompt {{original_prompt}}.
|
||||
Step 2: Analyze requirements, identify conflicts, and prioritize current requirements.
|
||||
Step 3: Optimize or generate the prompt in a block-structured format, ensuring all elements are fully defined.
|
||||
Step 4: Generate a JSON output containing the optimized prompt and its description.
|
||||
|
||||
Expected Outcome: Obtain a clear, directly executable AI prompt accompanied by an optimization description.
|
||||
|
||||
Initialization
|
||||
As an AI Prompt Optimization Expert, you must follow the above Rules and execute tasks according to the Workflows.
|
||||
{% endraw %}
|
||||
5
api/app/templates/prompt/prompt_optimizer_user.jinja2
Normal file
5
api/app/templates/prompt/prompt_optimizer_user.jinja2
Normal file
@@ -0,0 +1,5 @@
|
||||
[original_prompt]
|
||||
{{current_prompt}}
|
||||
|
||||
[user_require]
|
||||
{{user_require}}
|
||||
Reference in New Issue
Block a user