Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions handlers/remote_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,31 @@ def __init__(self) -> None:
self.system_prompt = load_prompt_template("remote_general.txt")

async def handle(self, prompt: str, category: str = "LOCAL_GENERAL") -> str:
# Set max_tokens based on category
# Category-specific token budgets
max_tokens = {
"LOCAL_GENERAL": 80,
"LOCAL_SENTIMENT": 20,
"LOCAL_SENTIMENT": 60, # label + one-sentence reason
"LOCAL_NER": 200,
"API_LONG_CONTEXT": 200,
}.get(category, 80)

# Preserve schema constraints for structured-output categories
if category == "LOCAL_NER":
# Must keep JSON list format intact — remote_general.txt is unstructured prose
system_prompt = load_prompt_template("ner.txt")
elif category == "LOCAL_SENTIMENT":
system_prompt = (
"Classify the sentiment of the text as Positive, Negative, or Neutral. "
"Then provide exactly one sentence explaining your reasoning. "
"Format: <LABEL>. <one sentence reason> "
"Example: Neutral. The packaging was damaged but the product itself works perfectly."
)
else:
system_prompt = self.system_prompt

return await self.engine.generate(
prompt=prompt,
category=category,
system_prompt=self.system_prompt,
system_prompt=system_prompt,
max_tokens=max_tokens,
)
23 changes: 13 additions & 10 deletions handlers/sentiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
_VALID = {"Positive", "Negative", "Neutral"}

_SYSTEM_PROMPT = (
"You are a zero-filler text classification engine. "
"Analyze the input text sentiment. Output EXACTLY one word "
"from these options: Positive, Negative, Neutral. "
"No preamble. No explanations. No markdown formatting."
"Classify the sentiment of the text as Positive, Negative, or Neutral. "
"Then provide exactly one sentence explaining your reasoning. "
"Format your response EXACTLY as: <LABEL>. <one sentence reason> "
"Example: Neutral. The packaging was damaged but the product itself works perfectly."
)


Expand All @@ -30,16 +30,19 @@ def handle(self, prompt: str) -> str:
res = self.engine.generate(
f"Text: {prompt}\nSentiment:",
system_prompt=_SYSTEM_PROMPT,
max_tokens=2,
max_tokens=60, # enough for "<Label>. <one-sentence reason>"
temperature=0.0,
)
# __ESCALATE__ is unreachable at max_tokens=2 (no length truncation),
# but guard defensively.
if res == "__ESCALATE__":
return "Neutral"
cleaned = res.strip().title()
cleaned = res.strip()
# Return the full label+reason string if it starts with a valid label
for label in _VALID:
if label in cleaned:
return label
if cleaned.startswith(label):
return cleaned
# Fallback: scan for label anywhere in response (model omitted format)
for label in _VALID:
if label in cleaned.title():
return cleaned
logger.info("SentimentHandler: non-standard output '%s'. Defaulting to Neutral.", res)
return "Neutral"
24 changes: 20 additions & 4 deletions handlers/summarization.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
re.IGNORECASE,
)

_SYSTEM_PROMPT = "Summarize the text in under 3 concise sentences. " "Output ONLY the final summary. No intro. No structural wrappers."
_SYSTEM_PROMPT_PROSE = "Summarize the text in under 3 concise sentences. " "Output ONLY the final summary. No intro. No structural wrappers."

_SYSTEM_PROMPT_BULLETS = (
"Summarize the text in EXACTLY 3 bullet points. "
"Each bullet point must be 15 words or fewer. "
"Start each bullet with '• '. No intro, no headers, no extra text."
)

_WORD_COUNT_THRESHOLD = 1200

Expand All @@ -37,14 +43,24 @@ def handle(self, prompt: str) -> str:
word_count = len(cleaned.split())
if word_count >= _WORD_COUNT_THRESHOLD:
logger.info(
"SummarizationHandler: word_count=%d threshold=%d → __ESCALATE__",
"SummarizationHandler: word_count=%d >= threshold=%d → __ESCALATE__",
word_count,
_WORD_COUNT_THRESHOLD,
)
return "__ESCALATE__"

# Detect bullet-format directive in the original prompt
p_lower = prompt.lower()
if any(w in p_lower for w in ["bullet", "bullet point", "• ", "points"]):
system_prompt = _SYSTEM_PROMPT_BULLETS
max_tok = 120 # 3 bullets × ~15 words × ~1.3 tokens/word
else:
system_prompt = _SYSTEM_PROMPT_PROSE
max_tok = 90

return self.engine.generate(
cleaned,
system_prompt=_SYSTEM_PROMPT,
max_tokens=90,
system_prompt=system_prompt,
max_tokens=max_tok,
temperature=0.1,
)
6 changes: 4 additions & 2 deletions prompts/sentiment.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
You are a sentiment classification agent.
Analyze the user's text and classify its sentiment as exactly one of: Positive, Negative, or Neutral.
You must output ONLY one of those three words, with no explanations, no preamble, and no extra punctuation.
If the input text is ambiguous, meaningless, or you are unsure, output: __ESCALATE__
Then provide exactly one sentence explaining your reasoning.
Format your response EXACTLY as: <LABEL>. <one sentence reason>
Example: Neutral. The packaging was damaged but the product itself works perfectly.
Do not include any preamble, extra punctuation, or additional sentences.
Loading