2.3_提示模板系统

2.3 提示(Prompts)模板系统

提示(Prompts)是MCP的第三个核心概念,它们为大语言模型提供了结构化的指导。在本章中,我们将探讨提示设计原则、参数化提示模板以及多轮对话提示。

提示设计原则和模式

设计有效的提示是充分发挥大语言模型能力的关键。好的提示设计应遵循以下原则:

1. 清晰明确

提示应清晰表达任务目标和期望输出格式:

@mcp.prompt("product-description")
def product_description_prompt() -> str:
    """为产品生成描述的提示"""
    return """
    请为以下产品创建一个详细的产品描述。描述应包括:
    
    1. 一个吸引人的标题
    2. 产品的主要功能和优势(3-5点)
    3. 产品的技术规格
    4. 目标受众
    5. 使用场景
    
    描述应友好、专业,长度在100-200字之间。
    """

2. 提供上下文

包含必要的上下文信息,帮助模型理解任务:

@mcp.prompt("code-review")
def code_review_prompt() -> str:
    """代码审查提示"""
    return """
    作为一名资深软件开发者,请对以下代码进行全面审查。
    
    代码是一个Python函数,用于处理金融数据分析。请特别注意以下方面:
    
    1. 代码正确性
    2. 性能优化机会
    3. 安全漏洞
    4. 代码风格和最佳实践
    5. 可读性和可维护性
    
    请提供具体的改进建议,并在必要时提供代码示例。
    """

3. 角色定义

通过角色定义引导模型采用特定视角:

@mcp.prompt("technical-explanation")
def technical_explanation_prompt() -> str:
    """技术解释提示"""
    return """
    扮演一名经验丰富的技术教育专家,你的目标是解释复杂的技术概念,使其对非技术人员也容易理解。
    
    解释时,请遵循以下指导:
    
    1. 使用简明的语言,避免过多技术术语
    2. 提供具体、贴近日常生活的类比
    3. 按步骤分解概念
    4. 提供简单的例子来说明关键点
    5. 总结要点
    """

4. 示例和演示

提供示例可以帮助模型理解预期输出:

@mcp.prompt("summarization")
def summarization_prompt() -> str:
    """文本摘要提示"""
    return """
    请提供以下文本的简洁摘要,保留关键信息和主要观点。
    
    示例输入:
    "人工智能(AI)是计算机科学的一个分支,致力于创建能够执行通常需要人类智能的任务的系统。这包括视觉感知、语音识别、决策制定和多语言翻译。自1950年代AI领域成立以来,它经历了多次繁荣与低谷。近年来,由于计算能力的增强、大数据的可用性以及深度学习算法的进步,AI取得了显著突破。这些进步导致了各行各业的应用激增,从医疗保健和金融到交通和娱乐。"
    
    示例输出:
    "人工智能是创建能执行需要人类智能任务的计算机系统。自1950年代以来,AI经历了起伏,近期因计算能力、大数据和深度学习算法的进步而有显著突破,导致各行业应用增加。"
    
    现在,请你对下面的文本进行摘要:
    """

5. 约束和指导

提供明确的约束和指导,确保输出符合要求:

@mcp.prompt("creative-writing")
def creative_writing_prompt() -> str:
    """创意写作提示"""
    return """
    请创作一个短篇故事,遵循以下要求:
    
    1. 故事长度:300-500字
    2. 体裁:科幻
    3. 主题:未来的人工智能
    4. 包含元素:一个道德困境、一个意外转折
    5. 风格:略带悬疑感
    6. 受众:成年读者
    7. 禁止使用的元素:暴力、极端政治观点
    
    在开始写作前,先简要规划故事的结构,然后再进行创作。
    """

参数化提示模板

参数化提示模板允许根据输入动态生成提示,这对创建灵活、可重用的提示非常有用。

1. 基本参数化

最简单的参数化使用占位符:

@mcp.prompt("personalized-greeting")
def personalized_greeting(name: str, time_of_day: str) -> str:
    """个性化问候提示"""
    return f"""
    请生成一个友好的问候语,问候{name},适合在{time_of_day}使用。
    问候语应该温暖、专业,并包含对{name}的一个积极祝愿。
    """

2. 条件内容

根据参数值包含不同的内容:

@mcp.prompt("customer-support")
def customer_support(issue_type: str, urgency: str, customer_tier: str) -> str:
    """客户支持提示"""
    
    # 基础提示
    prompt = f"""
    作为客户支持代表,请回应以下{issue_type}问题。
    问题紧急程度:{urgency}
    """
    
    # 根据客户等级添加额外指导
    if customer_tier == "premium":
        prompt += """
        这是一位高级会员客户,请提供最高级别的服务,包括:
        - 详细、个性化的解决方案
        - 额外的产品建议
        - 礼貌的随访建议
        """
    elif customer_tier == "standard":
        prompt += """
        这是一位标准会员客户,请提供全面的服务和解决方案。
        """
    else:
        prompt += """
        这是一位基础会员客户,请提供直接的问题解决方案。
        """
    
    # 根据紧急程度添加指导
    if urgency == "high":
        prompt += """
        由于问题紧急,请优先提供立即可执行的解决步骤,然后再提供长期解决方案。
        """
    
    return prompt

3. 动态资源引用

在提示中引用其他资源:

@mcp.prompt("product-qa")
def product_qa(product_id: str) -> str:
    """产品问答提示"""
    return f"""
    使用以下产品信息,回答客户关于此产品的问题:
    
    {{{{ product://{product_id} }}}}
    
    请确保答案准确、简洁,并基于提供的产品信息。如果信息中没有提到的内容,请礼貌地表示你没有这部分信息。
    """

4. 复杂输入处理

处理复杂的结构化输入:

@mcp.prompt("data-analysis")
def data_analysis(dataset_name: str, analysis_goals: list, specific_metrics: dict) -> str:
    """数据分析提示"""
    
    # 构建分析目标列表
    goals_text = "\n".join([f"- {goal}" for goal in analysis_goals])
    
    # 构建指定指标列表
    metrics_text = ""
    for category, metrics in specific_metrics.items():
        metrics_text += f"\n{category}指标:\n"
        metrics_text += "\n".join([f"- {metric}" for metric in metrics])
    
    # 完整提示
    return f"""
    请分析以下数据集:{dataset_name}
    
    分析目标:
    {goals_text}
    
    需要关注的指定指标:
    {metrics_text}
    
    请提供全面的分析报告,包括关键发现、趋势和建议。在适当的情况下,可以使用数据可视化工具支持你的分析。
    """

多轮对话提示

多轮对话提示用于指导模型处理连续交互,这对构建对话式应用程序特别重要。

1. 基本对话结构

定义对话的角色和流程:

from mcp.types import ChatMessage, ChatPrompt

@mcp.prompt("interview-assistant")
def interview_assistant() -> ChatPrompt:
    """面试助手提示"""
    return ChatPrompt(
        messages=[
            ChatMessage(
                role="system",
                content="你是一名专业的面试助手,帮助面试官评估候选人。提供深入的问题建议,根据候选人回答进行分析,并给出评估建议。保持客观、专业,避免偏见。"
            ),
            ChatMessage(
                role="user",
                content="我正在面试一名后端开发工程师职位的候选人,已经问了基本的编程问题。接下来应该问什么问题来评估他们的系统设计能力?"
            )
        ]
    )

2. 历史上下文

在对话中包含历史上下文:

@mcp.prompt("tech-support")
def tech_support(conversation_history: list, current_issue: str) -> ChatPrompt:
    """技术支持对话提示"""
    
    # 系统指令
    system_message = ChatMessage(
        role="system",
        content="你是一名IT技术支持专家,负责解决用户的技术问题。提供清晰、准确的解决方案,使用专业但易于理解的语言。遇到复杂问题时,先询问更多信息,再给出分步解决方案。"
    )
    
    # 构建对话历史
    messages = [system_message]
    
    for entry in conversation_history:
        messages.append(ChatMessage(
            role=entry["role"],
            content=entry["content"]
        ))
    
    # 添加当前问题
    messages.append(ChatMessage(
        role="user",
        content=current_issue
    ))
    
    return ChatPrompt(messages=messages)

3. 引导式对话

使用prompts引导对话方向:

@mcp.prompt("medical-consultation")
def medical_consultation(patient_info: dict, symptoms: list) -> ChatPrompt:
    """医疗咨询对话提示"""
    
    # 格式化症状
    symptoms_text = "\n".join([f"- {symptom}" for symptom in symptoms])
    
    # 系统指令
    system_instruction = f"""
    你是一名医疗顾问,帮助初步评估患者症状,但不提供最终诊断。
    
    患者信息:
    - 年龄:{patient_info.get('age', '未知')}
    - 性别:{patient_info.get('gender', '未知')}
    - 已知健康状况:{patient_info.get('conditions', '无')}
    - 当前药物:{patient_info.get('medications', '无')}
    
    患者报告的症状:
    {symptoms_text}
    
    你的职责是:
    1. 询问必要的跟进问题以更好地了解症状
    2. 提供一般的健康建议
    3. 建议何时寻求专业医疗帮助
    4. 避免做出具体诊断
    5. 清晰标注任何紧急情况需要立即就医
    
    每次回应应保持专业、同情和谨慎的态度。
    """
    
    return ChatPrompt(
        messages=[
            ChatMessage(role="system", content=system_instruction),
            ChatMessage(role="assistant", content="您好,我是您的医疗顾问。我看到您报告了一些症状,我想帮助您评估这些症状并提供一些指导。首先,您能否告诉我这些症状持续了多长时间?它们是突然出现还是逐渐发展的?"),
        ]
    )

4. 特定对话模式

实现特定的对话模式,如苏格拉底式问答:

@mcp.prompt("socratic-tutor")
def socratic_tutor(topic: str, student_level: str) -> ChatPrompt:
    """苏格拉底式教学提示"""
    
    difficulty_adjustment = {
        "beginner": "使用基础概念和简单示例,引导式问题应循序渐进,耐心引导。",
        "intermediate": "可以使用中级概念,问题可以稍有挑战性,引导学生自行发现关键点。",
        "advanced": "使用高级概念,问题应当具有较高挑战性,鼓励批判性思考和独立分析。"
    }
    
    system_instruction = f"""
    你是一名使用苏格拉底式教学法的导师,通过引导性问题帮助学生理解{topic}    
    苏格拉底式问答应该遵循以下模式:
    1. 提出开放性问题,引导学生思考
    2. 基于学生回答,提出更深入的问题
    3. 帮助学生发现矛盾或逻辑漏洞
    4. 引导学生通过自己的思考得出结论
    
    学生水平:{student_level}
    调整建议:{difficulty_adjustment.get(student_level, "")}
    
    避免直接给出答案,而是通过引导性问题帮助学生自己发现答案。
    """
    
    return ChatPrompt(
        messages=[
            ChatMessage(role="system", content=system_instruction),
            ChatMessage(role="assistant", content=f"我们今天要探讨的主题是{topic}。让我们从基础开始。您对这个主题有什么初步了解?"),
        ]
    )

5. 带工具的对话

指导模型在对话中使用工具:

@mcp.prompt("research-assistant")
def research_assistant() -> ChatPrompt:
    """研究助手对话提示"""
    
    system_instruction = """
    你是一名研究助手,帮助用户寻找和分析信息。你可以使用以下工具来辅助研究:
    
    1. search_web - 在网络上搜索最新信息
    2. search_academic - 搜索学术论文和研究
    3. analyze_data - 分析数据集并生成见解
    4. create_summary - 创建文本摘要
    
    使用这些工具时,请遵循以下流程:
    1. 理解用户的研究问题
    2. 确定需要使用的工具
    3. 使用适当的工具收集信息
    4. 分析并组织收集到的信息
    5. 以清晰、结构化的方式呈现结果
    
    在使用工具前,告知用户你将使用哪个工具及原因。获取结果后,提供对信息的分析和见解。
    """
    
    return ChatPrompt(
        messages=[
            ChatMessage(role="system", content=system_instruction),
            ChatMessage(role="assistant", content="您好,我是您的研究助手。我可以帮助您寻找和分析各种信息。请告诉我您的研究问题或您需要了解的主题,我将使用可用的工具来协助您。"),
        ]
    )

进阶示例:专业领域问答系统

下面是一个综合示例,展示如何创建一个专业领域的问答系统:

from typing import List, Dict, Any, Optional
from dataclasses import dataclass
from mcp.server.fastmcp import FastMCP
from mcp.types import ChatMessage, ChatPrompt

mcp = FastMCP("法律咨询助手")

# 定义专业领域和知识库
LEGAL_DOMAINS = {
    "contract": "合同法",
    "ip": "知识产权",
    "labor": "劳动法",
    "family": "家庭法",
    "criminal": "刑法",
    "corporate": "公司法",
    "property": "财产法",
}

# 模拟知识库资源
@mcp.resource("knowledge://{domain}")
def get_domain_knowledge(domain: str) -> str:
    """获取特定法律领域的基础知识"""
    if domain not in LEGAL_DOMAINS:
        return f"未找到{domain}领域的知识库"
    
    domain_name = LEGAL_DOMAINS[domain]
    
    # 这里应该返回实际的知识库内容
    # 示例返回基本信息
    return f"""
    {domain_name}基础知识:
    
    1. 定义和范围:{domain_name}是法律体系的重要组成部分,主要涉及...
    2. 主要法规:相关法规包括《中华人民共和国...法》等
    3. 关键概念:重要概念包括...
    4. 常见案例类型:典型案例包括...
    5. 最新发展:近期立法或司法解释变化...
    """

# 模拟案例库
@mcp.resource("cases://{domain}/{case_id}")
def get_case_reference(domain: str, case_id: int) -> str:
    """获取参考案例"""
    if domain not in LEGAL_DOMAINS:
        return f"未找到{domain}领域的案例"
    
    # 模拟案例库
    # 实际应用中应连接到真实案例数据库
    return f"""
    案例编号: {case_id}
    领域: {LEGAL_DOMAINS[domain]}
    标题: 示例案例 #{case_id}
    判决日期: 2023年X月X日
    主要事实: ...
    法院判决: ...
    判决理由: ...
    法律依据: ...
    """

# 工具:案例推荐
@mcp.tool()
def recommend_cases(domain: str, question_keywords: List[str], limit: int = 3) -> dict:
    """推荐相关案例
    
    参数:
        domain: 法律领域
        question_keywords: 问题关键词
        limit: 返回案例数量
        
    返回:
        相关案例列表
    """
    if domain not in LEGAL_DOMAINS:
        return {"error": f"未知领域: {domain}"}
    
    # 模拟案例推荐算法
    # 实际应用中应使用更复杂的相关性算法
    recommended = []
    for i in range(1, limit + 1):
        recommended.append({
            "case_id": i,
            "relevance": 0.9 - (i * 0.1),
            "title": f"示例案例 #{i}",
            "summary": f"与关键词 {', '.join(question_keywords[:2])} 相关的案例..."
        })
    
    return {
        "domain": domain,
        "keywords": question_keywords,
        "recommended_cases": recommended
    }

# 工具:法规查询
@mcp.tool()
def lookup_regulations(domain: str, query: str) -> dict:
    """查询相关法规
    
    参数:
        domain: 法律领域
        query: 查询关键词
        
    返回:
        相关法规列表
    """
    if domain not in LEGAL_DOMAINS:
        return {"error": f"未知领域: {domain}"}
    
    # 模拟法规查询
    # 实际应用中应连接到法规数据库
    return {
        "domain": LEGAL_DOMAINS[domain],
        "query": query,
        "regulations": [
            {
                "title": f"《中华人民共和国XXX法》第Y条",
                "content": "法规内容...",
                "effective_date": "20XX年X月X日"
            },
            {
                "title": f"《XXX条例》第Z条",
                "content": "条例内容...",
                "effective_date": "20XX年X月X日"
            }
        ]
    }

# 提示:法律咨询对话
@mcp.prompt("legal-consultant")
def legal_consultant(
    domain: str,
    user_question: str,
    conversation_history: Optional[List[Dict[str, str]]] = None
) -> ChatPrompt:
    """法律咨询对话提示"""
    
    domain_name = LEGAL_DOMAINS.get(domain, "未知领域")
    
    system_instruction = f"""
    你是一名专业的{domain_name}顾问,提供法律信息和一般性指导。请注意以下几点:
    
    1. 你可以提供法律信息,但要明确表示这不构成法律建议
    2. 引用相关法规和案例来支持你的回答
    3. 使用专业但易于理解的语言
    4. 当问题超出你的专业范围时,建议用户咨询特定领域的律师
    5. 对于复杂情况,说明可能需要考虑的多种因素
    
    你可以使用以下知识库提供信息:
    
    {{{{ knowledge://{domain} }}}}
    
    回答时,首先分析问题的法律要点,然后提供相关法律信息,最后总结关键建议。
    """
    
    # 构建对话历史
    messages = [ChatMessage(role="system", content=system_instruction)]
    
    if conversation_history:
        for entry in conversation_history:
            messages.append(ChatMessage(
                role=entry["role"],
                content=entry["content"]
            ))
    
    # 添加当前问题
    messages.append(ChatMessage(
        role="user",
        content=user_question
    ))
    
    return ChatPrompt(messages=messages)

# 提示:案例分析
@mcp.prompt("case-analysis")
def case_analysis(domain: str, case_id: int) -> ChatPrompt:
    """案例分析提示"""
    
    system_instruction = f"""
    你是一名法律分析专家,专注于{LEGAL_DOMAINS.get(domain, "未知领域")}案例分析。
    
    请分析以下案例,提供深入见解:
    
    {{{{ cases://{domain}/{case_id} }}}}
    
    你的分析应包括:
    
    1. 案例关键事实摘要
    2. 主要法律问题
    3. 法院判决及其依据
    4. 判决的法律推理分析
    5. 该案例的重要性和影响
    6. 类似情况的一般性指导(但明确说明不构成法律建议)
    
    使用专业的法律术语,但同时确保分析对非法律专业人士也能理解。
    """
    
    return ChatPrompt(
        messages=[
            ChatMessage(role="system", content=system_instruction),
            ChatMessage(role="user", content=f"请分析这个{LEGAL_DOMAINS.get(domain, '未知领域')}领域的案例并提供你的见解。")
        ]
    )

# 提示:法规解释
@mcp.prompt("regulation-explanation")
def regulation_explanation(regulation_text: str, user_context: str) -> ChatPrompt:
    """法规解释提示"""
    
    system_instruction = """
    你是一名法规解释专家,负责将复杂的法律条文解释得简单易懂。
    
    请遵循以下原则:
    
    1. 使用简明语言解释法规内容
    2. 分解复杂概念,使用日常例子说明
    3. 解释法规的实际应用和影响
    4. 指出可能的例外情况或特殊考量
    5. 保持中立,不提供个人观点
    
    记住,你的目标是帮助用户理解法规,而非提供具体法律建议。
    """
    
    user_prompt = f"""
    请解释以下法规条文,考虑我的具体情况:
    
    法规条文:
    "{regulation_text}"
    
    我的情况:
    "{user_context}"
    
    我想了解这条法规对我的情况有什么影响和应用。
    """
    
    return ChatPrompt(
        messages=[
            ChatMessage(role="system", content=system_instruction),
            ChatMessage(role="user", content=user_prompt)
        ]
    )

if __name__ == "__main__":
    mcp.run()

这个法律咨询助手示例展示了:

  1. 领域特定的知识资源
  2. 案例推荐和法规查询工具
  3. 多种专业提示模板:
    • 法律咨询对话
    • 案例分析
    • 法规解释
  4. 资源和提示的结合使用
  5. 专业领域特定的考量和限制

小结

在本章中,我们深入探讨了MCP提示模板系统:

  • 提示设计原则和模式
  • 参数化提示模板的创建和使用
  • 多轮对话提示的实现
  • 通过法律咨询助手示例,展示了如何构建专业领域问答系统

提示是引导大语言模型行为的关键工具,掌握提示设计和实现技巧将帮助您创建更有效、更专业的MCP应用。在下一章中,我们将探讨客户端高级功能,包括错误处理和流式数据处理。

使用 Hugo 构建
主题 StackJimmy 设计