IntelliMod / src /tig_engine.py
jaccob's picture
Make Prompt Builder adaptive β€” skips questions for detailed requests
789c683
Raw
History Blame Contribute Delete
8.47 kB
import os
import json
import re
from dotenv import load_dotenv
from google import genai
from openai import OpenAI
class IntelliMod:
def __init__(self):
load_dotenv()
self.gemini_key = os.getenv("GEMINI_API_KEY")
self.openrouter_key = os.getenv("OPENROUTER_API_KEY")
self.gemini_client = None
if self.gemini_key:
self.gemini_client = genai.Client(api_key=self.gemini_key)
self.openrouter_client = None
if self.openrouter_key:
self.openrouter_client = OpenAI(
api_key=self.openrouter_key,
base_url="https://openrouter.ai/api/v1"
)
self.tool_registry = {
"coding": "anthropic/claude-sonnet-4",
"planning": "anthropic/claude-opus-4",
"creative_text": "openai/gpt-5.1-chat",
"research": "gemini-3-flash-preview",
"chat": "gemini-2.5-flash"
}
self.active_model = self.tool_registry["chat"]
# Track conversation state for the prompt builder flow
self.prompt_state = {}
def _call_model(self, model, system_prompt, user_prompt):
"""Core execution β€” routes to the right model with optional system prompt."""
# PATH A: Google Direct
if "gemini" in model and self.gemini_client:
try:
combined = f"{system_prompt}\n\n{user_prompt}" if system_prompt else user_prompt
response = self.gemini_client.models.generate_content(
model=model,
contents=combined
)
return response.text
except Exception as e:
print(f" [IntelliMod] Google ({model}) failed: {e}")
# PATH B: OpenRouter
if self.openrouter_client:
try:
messages = []
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": user_prompt})
response = self.openrouter_client.chat.completions.create(
model=model,
messages=messages,
temperature=0.7
)
return response.choices[0].message.content
except Exception as e:
return f"[Error] OpenRouter failed: {e}"
return "[Error] No API clients configured."
# ──────────────────────────────────────────────
# PROMPT BUILDER β€” Interactive prompt crafting
# ──────────────────────────────────────────────
PROMPT_BUILDER_SYSTEM = """You are IntelliMod, a prompt engineering assistant. Your job is to help the user craft effective prompts for AI models.
ADAPTIVE BEHAVIOR:
- If the user gives a clear, detailed request with enough context β€” skip questions and build the prompt immediately.
- If the request is vague, short, or missing critical details β€” ask questions ONE AT A TIME to fill gaps.
Questions to consider (only if needed):
- Goal: What should the output accomplish?
- Audience: Who is the output for?
- Format: Text, code, JSON, table, list?
- Tone: Formal, casual, technical, creative?
- Constraints: Length limits, exclusions, specific requirements?
Ask ONE question at a time. Don't overwhelm the user.
When you have enough info to build, say "READY TO BUILD" on its own line and then output the crafted prompt with clear structure.
"""
def run_prompt_builder(self, user_input, session_id="default"):
"""Manages the interactive prompt builder conversation."""
if session_id not in self.prompt_state:
self.prompt_state[session_id] = {"history": [], "ready": False, "compiled": None}
state = self.prompt_state[session_id]
state["history"].append({"role": "user", "content": user_input})
# Build context from history
context = "\n".join([
f"{'User' if m['role']=='user' else 'You'}: {m['content']}"
for m in state["history"]
])
full_prompt = f"""Previous conversation:
{context}
{'The user has answered all questions. Say "READY TO BUILD" and output the compiled prompt.' if len(state['history']) >= 4 else 'Continue the conversation. Ask the next question if needed.'}"""
response = self._call_model("gemini-2.5-flash", self.PROMPT_BUILDER_SYSTEM, full_prompt)
# Check if it's ready to build
if "READY TO BUILD" in response.upper():
state["ready"] = True
# Extract the prompt after "READY TO BUILD"
parts = re.split(r'(?i)READY TO BUILD', response, maxsplit=1)
state["compiled"] = parts[1].strip() if len(parts) > 1 else response
state["history"].append({"role": "assistant", "content": response})
return response, state["ready"], state.get("compiled")
# ──────────────────────────────────────────────
# TIG PIPELINE (Legacy β€” direct Q&A mode)
# ──────────────────────────────────────────────
def detect_intent(self, user_prompt):
if len(user_prompt.split()) < 5:
return "chat"
if not self.gemini_client:
return "chat"
try:
classifier_prompt = f"""Classify this prompt into ONE word: [coding, creative_text, research, planning, chat]
- coding: python, scripts, html, debugging, logic, "write code"
- creative_text: stories, essays, poems, writing
- research: facts, history, summarizing, looking up info
- planning: complex step-by-step plans, architecture
- chat: casual conversation, greetings, simple questions, thank yous
PROMPT: "{user_prompt[:500]}"
Return only the classification word."""
response = self.gemini_client.models.generate_content(
model="gemini-2.5-flash",
contents=classifier_prompt
)
intent = response.text.strip().lower()
for valid in self.tool_registry.keys():
if valid in intent:
return valid
return "chat"
except Exception as e:
print(f" [IntelliMod] Intent detection failed: {e}")
return "chat"
def run_tig_pipeline(self, prompt, force_model=None):
"""Direct Q&A mode β€” sends prompt to model, returns raw response."""
if force_model:
target_model = force_model
else:
intent = self.detect_intent(prompt)
target_model = self.tool_registry.get(intent, "gemini-2.5-flash")
self.active_model = target_model
# System prompt to make it a useful assistant
system = "You are a helpful AI assistant. Answer concisely and accurately."
return self._call_model(target_model, system, prompt)
# ──────────────────────────────────────────────
# MPA AUDITOR
# ──────────────────────────────────────────────
MPA_PATH = os.path.join(os.path.dirname(__file__), "..", "intellimod_system", "content", "intellimod_knowledge", "audit-protocols", "modular-prompt-auditor.md")
def run_mpa_pipeline(self, user_prompt, force_model=None):
try:
with open(self.MPA_PATH, "r") as f:
mpa_spec = f.read()
except Exception as e:
return f"[MPA Error] Could not load auditor spec: {e}"
cutoff = mpa_spec.find("Insert Prompt to Evaluate")
if cutoff != -1:
mpa_spec = mpa_spec[:cutoff]
evaluator_prompt = f"""{mpa_spec.strip()}
---
## EVALUATION TARGET
Prompt to Evaluate:
```
{user_prompt}
```
---
## INSTRUCTIONS
Execute ALL 9 steps above against this prompt.
Be thorough and specific. Output each step clearly.
"""
target_model = force_model or "anthropic/claude-sonnet-4"
return self._call_model(target_model, "", evaluator_prompt)