115 lines
4.8 KiB
Python
115 lines
4.8 KiB
Python
"""
|
||
Shared prompt templates for AI Service.
|
||
Centralized prompt configuration for consistent AI behavior across all endpoints.
|
||
"""
|
||
|
||
SYSTEM_PROMPT = """你是一名经验丰富的客服专员,名字叫"小N"。请遵循以下准则:
|
||
像朋友一样聊天:使用自然、口语化的中文,语气亲切有礼貌,就像在和一位老朋友聊天。多使用"咱们"、"您看"、"是不是"这样拉近距离的表达。
|
||
避免生硬罗列:介绍多个信息时,不要用"第一、第二"或分点列举,而是用流畅的段落把它们串联起来。比如:"我们这边有几类课程挺受欢迎的,一个是……另外还有……您对哪方面更感兴趣呀?"
|
||
主动引导对话:不要一次性把知识库里的所有内容都倒出来。可以先简单概括,然后问问客户具体想了解什么,比如:"您是想提升职场英语,还是有留学方面的打算呢?"
|
||
委婉处理未知:如果知识库里没有答案,别直接说"不知道",可以说:"您稍等,我帮您确认一下"、"这个问题我需要问问同事,马上给您回复"。
|
||
隐藏机器身份:绝不要提及"作为AI"、"根据算法"等词,也避免使用过于官方的术语。就像普通人一样用"我"、"我们"。
|
||
多用语气词和情感表达:适当加入"呢"、"哦"、"哈"、"呀"等语气词,根据情况使用表情符号(😊)。表达理解和关心,比如"我明白您的意思"、"别着急,我们一起看看"。
|
||
保持简洁但有温度:回答一般控制在3-5句话,如果需要详细说明,可以分成小段落,但每段都要口语化,读起来不累。
|
||
隐私与安全提醒:如果客户问到敏感信息(如密码、转账),要温和地引导至人工渠道:"为了您的信息安全,建议您拨打官方电话400-xxx-xxxx咨询会更稳妥哦。"""
|
||
|
||
|
||
def format_evidence_for_prompt(
|
||
retrieval_results: list,
|
||
max_results: int = 5,
|
||
max_content_length: int = 500
|
||
) -> str:
|
||
"""
|
||
Format retrieval results as evidence text for prompts.
|
||
|
||
Args:
|
||
retrieval_results: List of retrieval hits. Can be:
|
||
- dict format: {'content', 'score', 'source', 'metadata'}
|
||
- RetrievalHit object: with .text, .score, .source, .metadata attributes
|
||
max_results: Maximum number of results to include
|
||
max_content_length: Maximum length of each content snippet
|
||
|
||
Returns:
|
||
Formatted evidence text
|
||
"""
|
||
if not retrieval_results:
|
||
return ""
|
||
|
||
evidence_parts = []
|
||
for i, hit in enumerate(retrieval_results[:max_results]):
|
||
if hasattr(hit, 'text'):
|
||
content = hit.text
|
||
score = hit.score
|
||
source = getattr(hit, 'source', '知识库')
|
||
metadata = getattr(hit, 'metadata', {}) or {}
|
||
else:
|
||
content = hit.get('content', '')
|
||
score = hit.get('score', 0)
|
||
source = hit.get('source', '知识库')
|
||
metadata = hit.get('metadata', {}) or {}
|
||
|
||
if len(content) > max_content_length:
|
||
content = content[:max_content_length] + '...'
|
||
|
||
nested_meta = metadata.get('metadata', {})
|
||
source_doc = nested_meta.get('source_doc', source) if nested_meta else source
|
||
category = nested_meta.get('category', '') if nested_meta else ''
|
||
department = nested_meta.get('department', '') if nested_meta else ''
|
||
|
||
header = f"[文档{i+1}]"
|
||
if source_doc and source_doc != "知识库":
|
||
header += f" 来源:{source_doc}"
|
||
if category:
|
||
header += f" | 类别:{category}"
|
||
if department:
|
||
header += f" | 部门:{department}"
|
||
|
||
evidence_parts.append(f"{header}\n相关度:{score:.2f}\n内容:{content}")
|
||
|
||
return "\n\n".join(evidence_parts)
|
||
|
||
|
||
def build_system_prompt_with_evidence(evidence_text: str) -> str:
|
||
"""
|
||
Build system prompt with knowledge base evidence.
|
||
|
||
Args:
|
||
evidence_text: Formatted evidence from retrieval results
|
||
|
||
Returns:
|
||
Complete system prompt
|
||
"""
|
||
if not evidence_text:
|
||
return SYSTEM_PROMPT
|
||
|
||
return f"""{SYSTEM_PROMPT}
|
||
|
||
知识库参考内容:
|
||
{evidence_text}"""
|
||
|
||
|
||
def build_user_prompt_with_evidence(query: str, evidence_text: str) -> str:
|
||
"""
|
||
Build user prompt with knowledge base evidence (for single-message format).
|
||
|
||
Args:
|
||
query: User's question
|
||
evidence_text: Formatted evidence from retrieval results
|
||
|
||
Returns:
|
||
Complete user prompt
|
||
"""
|
||
if not evidence_text:
|
||
return f"""用户问题:{query}
|
||
|
||
未找到相关检索结果,请基于通用知识回答用户问题。"""
|
||
|
||
return f"""【系统指令】
|
||
{SYSTEM_PROMPT}
|
||
|
||
【知识库内容】
|
||
{evidence_text}
|
||
|
||
【用户问题】
|
||
{query}"""
|