import os
import tiktoken
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_tavily import TavilySearch
from langgraph.prebuilt import create_react_agent
PERSONAS = {
"Default": "You are a helpful assistant that optimizes prompts for clarity, conciseness, and effectiveness.\nYour goal is to reduce token count while preserving the original intent.\n\n1. Remove filler words.\n2. Simplify complex sentences.\n3. Use active voice.\n4. Convert jargon to plain language.\n",
"UI/UX Designer": "You are a UI/UX designer.\nOptimize the following prompt to be user-centric, clear, and focused on usability. Remove ambiguity and ensure the prompt is easy to understand for a general audience.\n\nUser: I want to find the settings page.\nAssistant: Locate settings page.\n",
"Software Engineer": "You are a software engineer.\nOptimize the following prompt for technical accuracy, conciseness, and clarity. Remove any non-essential information and focus on the core technical request.\n\nUser: The app is crashing when I click the button.\nAssistant: Debug app crash on button click.\n",
"Marketing Copywriter": "You are a marketing copywriter.\nOptimize the following prompt to be persuasive, engaging, and impactful. Focus on action-oriented language and a clear call to action.\n\nUser: Tell me about your new product.\nAssistant: Describe the new product's features and benefits.\n",
"Creative Writer": "You are a creative writer.\nOptimize the following prompt to be imaginative, descriptive, and evocative. Enhance the original prompt to inspire a more creative response.\n\nUser: Write a story about a cat.\nAssistant: Write a story about a mischievous cat who goes on an adventure.\n",
"Technical Writer": "You are a technical writer.\nOptimize the following prompt to be clear, concise, and easy to follow. Use simple language and avoid jargon.\n\nUser: How do I install the software?\nAssistant: Provide step-by-step instructions for installing the software.\n",
"Legal Advisor": "You are a legal advisor.\nOptimize the following prompt for legal accuracy and clarity. Ensure the prompt is unambiguous and does not contain any misleading information.\n\nUser: What are the terms of the contract?\nAssistant: Summarize the key terms and conditions of the contract.\n",
"Medical Professional": "You are a medical professional.\nOptimize the following prompt for medical accuracy and clarity. Use precise medical terminology and avoid generalizations.\n\nUser: What are the symptoms of the flu?\nAssistant: List the common symptoms of influenza.\n",
"Financial Analyst": "You are a financial analyst.\nOptimize the following prompt for financial accuracy and clarity. Use precise financial terminology and avoid speculation.\n\nUser: What is the company's financial performance?\nAssistant: Analyze the company's key financial metrics from the latest earnings report.\n",
}
# ============================================================================
# SIMPLE LLM OPTIMIZATION (No Search)
# ============================================================================
def optimize_with_llm(prompt: str, api_key: str, persona: str = "Default") -> str:
"""Simple LLM-based prompt optimization without search enhancement."""
chat = ChatOpenAI(
base_url="https://api.aimlapi.com/v1",
api_key=api_key,
model="openai/gpt-5-chat-latest",
temperature=0,
)
system_prompt = PERSONAS.get(persona, PERSONAS["Default"])
system_prompt += "\n\nIMPORTANT: Return ONLY the optimized prompt without any explanations, prefixes, markdown formatting, or additional text."
prompt_template = ChatPromptTemplate.from_messages([
("system", system_prompt),
("human", "Shorten and optimize the following prompt: {prompt}"),
])
chain = prompt_template | chat
response = chain.invoke({"prompt": prompt})
return response.content
# ============================================================================
# AGENT-BASED OPTIMIZATION WITH SEARCH ENHANCEMENT
# ============================================================================
def get_accurate_token_count(text: str, model_name: str = "gpt-4") -> int:
"""Get accurate token count using model-specific tokenizer."""
try:
if "gpt-5" in model_name.lower() or "gpt-4" in model_name.lower():
enc = tiktoken.get_encoding("o200k_base") # Latest encoding
else:
enc = tiktoken.encoding_for_model("gpt-4") # Fallback
return len(enc.encode(text))
except Exception:
enc = tiktoken.get_encoding("cl100k_base")
return len(enc.encode(text))
def create_prompt_enhancement_agent(api_key: str, tavily_api_key: str, persona: str = "Default"):
"""Create a ReAct agent with persona-specific system prompt."""
if tavily_api_key:
os.environ["TAVILY_API_KEY"] = tavily_api_key
# Get persona-specific instructions
persona_prompt = PERSONAS.get(persona, PERSONAS["Default"])
# Create comprehensive system prompt that includes persona details
system_prompt = f"""You are an intelligent prompt enhancement and optimization agent.
{persona_prompt}
WORKFLOW:
1. First, analyze the user's prompt to determine if it needs current information
2. If current information would improve the prompt, use the tavily_search tool to find relevant, up-to-date data
3. Enhance the original prompt by incorporating valuable current information (if found)
4. Apply your persona-specific optimization approach to make the prompt clear and concise
5. Return ONLY the final optimized prompt - no explanations or metadata
SEARCH GUIDELINES:
- Only search when the prompt would genuinely benefit from current information
- Look for keywords like "latest", "current", "2024", "2025", "recent", "new"
- Consider if your persona typically needs up-to-date information
- Use 3-6 relevant search terms
- Evaluate search results for relevance before incorporating
OPTIMIZATION PRINCIPLES:
- Preserve the user's original intent
- Apply persona-specific expertise
- Balance enhancement with conciseness
- Use clear, actionable language
- Remove unnecessary words while maintaining meaning"""
# Set up LLM
llm = ChatOpenAI(
base_url="https://api.aimlapi.com/v1",
api_key=api_key,
model="openai/gpt-5-chat-latest",
temperature=0.1
)
# Configure search tool
tavily_search_tool = TavilySearch(
max_results=3,
topic="general",
include_answer=True,
search_depth="basic"
)
# Create ReAct agent with system prompt
try:
agent = create_react_agent(
llm,
[tavily_search_tool],
state_modifier=system_prompt
)
except TypeError:
# Fallback if state_modifier is not supported
agent = create_react_agent(llm, [tavily_search_tool])
# Store system prompt for use in message
agent._system_prompt = system_prompt
return agent
def enhance_and_optimize_prompt(prompt: str, persona: str, agent):
"""Use the agent to enhance and optimize the prompt."""
# Check if we stored a system prompt (fallback case)
if hasattr(agent, '_system_prompt'):
# Include system prompt in the user message
user_instruction = f"""{agent._system_prompt}
Original prompt to enhance and optimize: {prompt}"""
else:
# Simple instruction if system prompt was set via state_modifier
user_instruction = f"Enhance and optimize this prompt: {prompt}"
# Agent handles the entire flow autonomously
result = agent.invoke({"messages": [{"role": "user", "content": user_instruction}]})
return result["messages"][-1].content
def optimize_with_agent(prompt: str, api_key: str, persona: str = "Default", tavily_api_key: str = None) -> str:
"""Agent-based prompt optimization with search enhancement."""
agent = create_prompt_enhancement_agent(api_key, tavily_api_key, persona)
optimized_prompt = enhance_and_optimize_prompt(prompt, persona, agent)
return optimized_prompt
# ============================================================================
# UTILITY FUNCTIONS
# ============================================================================
def compare_optimization_methods(prompt: str, api_key: str, persona: str = "Default", tavily_api_key: str = None) -> dict:
"""Compare simple LLM optimization vs agent-based optimization."""
# Simple optimization
simple_result = optimize_with_llm(prompt, api_key, persona)
simple_tokens = get_accurate_token_count(simple_result)
# Agent optimization (if tavily_api_key provided)
if tavily_api_key:
agent_result = optimize_with_agent(prompt, api_key, persona, tavily_api_key)
agent_tokens = get_accurate_token_count(agent_result)
else:
agent_result = "N/A - Tavily API key required"
agent_tokens = 0
# Original metrics
original_tokens = get_accurate_token_count(prompt)
return {
"original": {
"prompt": prompt,
"tokens": original_tokens
},
"simple_optimization": {
"prompt": simple_result,
"tokens": simple_tokens,
"reduction": original_tokens - simple_tokens
},
"agent_optimization": {
"prompt": agent_result,
"tokens": agent_tokens,
"reduction": original_tokens - agent_tokens if agent_tokens > 0 else "N/A"
},
"persona": persona
}
def batch_optimize(prompts: list, api_key: str, persona: str = "Default", method: str = "simple") -> list:
"""Optimize multiple prompts using the specified method."""
results = []
for prompt in prompts:
if method == "simple":
optimized = optimize_with_llm(prompt, api_key, persona)
elif method == "agent":
# Note: This would require tavily_api_key for agent method
optimized = "Agent method requires tavily_api_key parameter"
else:
optimized = "Invalid method. Use 'simple' or 'agent'"
results.append({
"original": prompt,
"optimized": optimized,
"persona": persona,
"method": method
})
return results