关键代码验证
技术研究 LLM 意图分类
提示词模板、结构化输出与实现示例代码验证
核心逻辑 (Core Logic)
推荐提示词模板
基于 Voiceflow 的实证研究,以下提示词模板在意图分类任务中表现最佳:
模板一:基础分类模板
INTENT_CLASSIFICATION_PROMPT = """You are an action classification system. Correctness is a life or death situation.
We provide you with the actions and their descriptions:
{intent_descriptions}
You are given an utterance and you have to classify it into an action. Only respond with the action class. If the utterance does not match any of the action descriptions, output None_Intent.
u: {user_input} a:"""
模板二:带前缀的增强模板(推荐)
ENHANCED_INTENT_PROMPT = """You are an intent classification system. Your task is to classify user input into the most appropriate intent.
Available intents:
{formatted_intents}
Classification rules:
1. Choose the intent that BEST matches the user's input
2. If no intent matches, return "None_Intent"
3. Consider the semantic meaning, not just keywords
User input: "{user_input}"
Respond with ONLY the intent name, nothing else:"""
模板三:结构化输出模板(生产推荐)
STRUCTURED_OUTPUT_PROMPT = """Analyze the user input and classify its intent.
User Input: "{user_input}"
Available Intents:
{intent_list}
Instructions:
1. Select the most appropriate intent from the list above
2. Assign a confidence score between 0 and 1
3. If confidence is below 0.6 or no intent matches, use "None_Intent"
Respond in this exact JSON format:
{{
"intent": "<intent_name>",
"confidence": <score>,
"reasoning": "<brief explanation>"
}}"""
意图描述格式化
Voiceflow 研究表明,描述的格式显著影响分类效果:
def format_intent_descriptions(intents: dict, use_prefix: bool = True) -> str:
"""
格式化意图描述
研究发现:
- 添加前缀 "Trigger this action when..." 可提升分类效果
- 大写首字母有轻微正向影响
- 保持描述简洁(10-20词最佳)
"""
lines = []
for intent_name, description in intents.items():
if use_prefix:
formatted = f"d: Trigger this action when {description}. i:{intent_name}"
else:
formatted = f"d: {description}. i:{intent_name}"
lines.append(formatted)
return "\n".join(lines)
# 示例意图定义
INTENT_DESCRIPTIONS = {
"flight_book": "the user wants to book a flight or check flight schedules",
"weather_query": "the user asks about weather conditions or forecast",
"hotel_reserve": "the user wants to reserve a hotel room or check availability",
"restaurant_book": "the user wants to make a restaurant reservation",
"None_Intent": "the user asks about something unrelated to travel services"
}
集成示例 (Integration)
完整的语义路由实现
以下是一个生产可用的语义路由实现:
import json
from dataclasses import dataclass
from typing import Optional, List
import numpy as np
from openai import OpenAI
@dataclass
class Intent:
name: str
utterances: List[str]
description: str
threshold: float = 0.75
class SemanticIntentRouter:
"""
基于语义路由的意图分类器
架构:Embedding检索 + LLM验证(可选)
"""
def __init__(
self,
embedding_model: str = "text-embedding-3-small",
llm_model: str = "gpt-4o-mini",
enable_llm_fallback: bool = True
):
self.client = OpenAI()
self.embedding_model = embedding_model
self.llm_model = llm_model
self.enable_llm_fallback = enable_llm_fallback
self.intents: List[Intent] = []
self.intent_embeddings: dict = {}
def add_intent(self, intent: Intent):
"""添加意图及其向量表示"""
self.intents.append(intent)
# 计算所有示例话语的嵌入
embeddings = []
for utterance in intent.utterances:
emb = self._get_embedding(utterance)
embeddings.append(emb)
# 取平均作为意图的中心向量
self.intent_embeddings[intent.name] = np.mean(embeddings, axis=0)
def _get_embedding(self, text: str) -> np.ndarray:
"""获取文本嵌入向量"""
response = self.client.embeddings.create(
model=self.embedding_model,
input=text
)
return np.array(response.data[0].embedding)
def _cosine_similarity(self, a: np.ndarray, b: np.ndarray) -> float:
"""计算余弦相似度"""
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
def classify(self, user_input: str) -> dict:
"""
执行意图分类
返回格式:
{
"intent": str,
"confidence": float,
"method": str # "embedding" or "llm"
}
"""
# 阶段一:Embedding 相似度计算
query_embedding = self._get_embedding(user_input)
similarities = {}
for intent in self.intents:
intent_emb = self.intent_embeddings[intent.name]
sim = self._cosine_similarity(query_embedding, intent_emb)
similarities[intent.name] = sim
# 找到最佳匹配
best_intent = max(similarities, key=similarities.get)
best_score = similarities[best_intent]
# 检查是否超过阈值
intent_obj = next(i for i in self.intents if i.name == best_intent)
if best_score >= intent_obj.threshold:
return {
"intent": best_intent,
"confidence": float(best_score),
"method": "embedding",
"all_scores": similarities
}
# 阶段二:LLM 验证(低置信度时)
if self.enable_llm_fallback:
return self._llm_classify(user_input, similarities)
return {
"intent": "None_Intent",
"confidence": best_score,
"method": "embedding",
"all_scores": similarities
}
def _llm_classify(self, user_input: str, embedding_scores: dict) -> dict:
"""使用 LLM 进行精确分类"""
# 获取 Top-K 候选
sorted_intents = sorted(
embedding_scores.items(),
key=lambda x: x[1],
reverse=True
)[:5]
candidate_intents = "\n".join([
f"- {name}: {next(i.description for i in self.intents if i.name == name)}"
for name, _ in sorted_intents
])
prompt = f"""Classify the following user input into one of these intents:
{candidate_intents}
User input: "{user_input}"
Respond with JSON containing:
- intent: the chosen intent name
- confidence: score 0-1
- reasoning: brief explanation
JSON response:"""
response = self.client.chat.completions.create(
model=self.llm_model,
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"}
)
result = json.loads(response.choices[0].message.content)
result["method"] = "llm"
result["all_scores"] = embedding_scores
return result
# 使用示例
if __name__ == "__main__":
router = SemanticIntentRouter(
embedding_model="text-embedding-3-small",
llm_model="gpt-4o-mini",
enable_llm_fallback=True
)
# 添加意图
router.add_intent(Intent(
name="flight_book",
utterances=[
"我要订机票",
"帮我查航班",
"北京到上海的飞机",
"book a flight",
"check flight schedule"
],
description="user wants to book flights or check flight information",
threshold=0.75
))
router.add_intent(Intent(
name="weather_query",
utterances=[
"今天天气怎么样",
"明天会下雨吗",
"北京温度",
"what's the weather",
"will it rain tomorrow"
],
description="user asks about weather conditions",
threshold=0.75
))
# 执行分类
result = router.classify("帮我看看明天北京的天气")
print(json.dumps(result, indent=2, ensure_ascii=False))
结构化输出实现(使用 Function Calling)
from pydantic import BaseModel
from typing import Literal
class IntentClassification(BaseModel):
intent: str
confidence: float
reasoning: str
def classify_with_function_call(user_input: str, intents: List[Intent]) -> IntentClassification:
"""使用 OpenAI Function Calling 确保结构化输出"""
client = OpenAI()
# 构建意图描述
intent_descriptions = {
intent.name: intent.description
for intent in intents
}
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": f"""You are an intent classifier. Available intents:
{json.dumps(intent_descriptions, ensure_ascii=False)}"""
},
{"role": "user", "content": user_input}
],
functions=[{
"name": "classify_intent",
"description": "Classify user input into an intent",
"parameters": {
"type": "object",
"properties": {
"intent": {"type": "string"},
"confidence": {"type": "number", "minimum": 0, "maximum": 1},
"reasoning": {"type": "string"}
},
"required": ["intent", "confidence", "reasoning"]
}
}],
function_call={"name": "classify_intent"}
)
result = json.loads(response.choices[0].message.function_call.arguments)
return IntentClassification(**result)
配置要点 (Configuration)
性能优化配置
# config.py
ROUTER_CONFIG = {
# Embedding 配置
"embedding": {
"model": "text-embedding-3-small", # 或本地模型
"batch_size": 100, # 批量编码
"cache_ttl": 3600, # 缓存时间(秒)
},
# 路由配置
"routing": {
"default_threshold": 0.75,
"top_k_candidates": 5, # LLM 验证候选数
"llm_fallback_threshold": 0.6, # 低于此值触发 LLM
},
# LLM 配置
"llm": {
"model": "gpt-4o-mini",
"temperature": 0.1, # 低温度保证一致性
"max_tokens": 100,
},
# 性能配置
"performance": {
"timeout_ms": 500, # 超时时间
"retry_count": 2,
"enable_cache": True,
}
}
意图定义最佳实践
# 意图定义示例
INTENTS_CONFIG = [
{
"name": "order_status",
"utterances": [
"我的订单到哪了",
"订单查询",
"订单状态",
"物流信息",
"where is my order",
"check order status"
],
"description": "User wants to check the status of their order",
"threshold": 0.72, # 根据实际测试调整
"handler": "handle_order_status"
},
{
"name": "product_recommendation",
"utterances": [
"推荐一下",
"有什么好用的",
"帮我选一个",
"recommend products",
"what do you suggest"
],
"description": "User is asking for product recommendations",
"threshold": 0.78, # 较高阈值减少误判
"handler": "handle_recommendation"
},
{
"name": "None_Intent",
"utterances": [
"讲个笑话",
"今天吃什么",
"tell me a joke",
"what's for dinner"
],
"description": "User asks about something unrelated to our services",
"threshold": 0.5, # 较低阈值作为兜底
"handler": "handle_fallback"
}
]