-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode.py
More file actions
72 lines (58 loc) · 2.96 KB
/
Copy pathcode.py
File metadata and controls
72 lines (58 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
"""Routing — classify the request first, then send it to a specialist.
One cheap classification call picks the lane; the chosen specialist prompt
handles the actual work. Adding a new lane means adding a dict entry, not
touching the ones that already work.
If the classifier isn't confident, we don't guess — we ask for clarification.
"""
from langchain_core.prompts import ChatPromptTemplate
from resources.agent import llm
from resources.helper import show_response
# The router. Kept deliberately small: its only job is to name a lane and rate
# its own confidence. Cheap prompt in, two words out.
route_prompt = ChatPromptTemplate.from_template(
"Classify the customer message into exactly one category: "
"tech, sales, or billing.\n"
"Reply with the category, a space, then your confidence 0.0-1.0. "
"Nothing else. Example: tech 0.9\n\nMessage: {message}"
)
# The specialists. Each one assumes it already has the right kind of request,
# which is exactly what lets its prompt be narrow and good at one thing.
SPECIALISTS = {
"tech": "You are a technical support engineer. Diagnose the issue and give "
"concrete troubleshooting steps.\n\nIssue: {message}",
"sales": "You are a sales rep. Answer the pricing or plan question and "
"suggest a next step.\n\nQuestion: {message}",
"billing": "You are a billing specialist. Explain the charge or process the "
"refund request clearly.\n\nRequest: {message}",
}
CONFIDENCE_FLOOR = 0.6 # below this we ask rather than guess
def route(message):
"""Classify, then dispatch. Returns the specialist's response message."""
decision = llm.invoke(route_prompt.format(message=message))
show_response(decision)
# Parse "tech 0.9" defensively — the model is being asked for a rigid
# format, but a router that crashes on odd output is worse than one that
# falls back to asking a human.
parts = decision.content.strip().split()
lane = parts[0].lower().strip(".,") if parts else ""
try:
confidence = float(parts[1])
except (IndexError, ValueError):
confidence = 0.0
if lane not in SPECIALISTS or confidence < CONFIDENCE_FLOOR:
print(f"\n[router] lane={lane!r} confidence={confidence} -> too unsure, asking")
return llm.invoke(
"Ask the customer one short clarifying question about this "
f"ambiguous message: {message}"
)
print(f"\n[router] lane={lane!r} confidence={confidence} -> dispatching")
return llm.invoke(SPECIALISTS[lane].format(message=message))
if __name__ == "__main__":
# Three messages, three lanes — same entry point, different specialists.
for message in [
"My deployment keeps failing with a 502 after the last update.",
"What's the price difference between the team and enterprise plan?",
"hey", # deliberately vague: should trip the confidence floor
]:
print(f"\n{'=' * 60}\nINCOMING: {message}\n{'=' * 60}")
show_response(route(message))