提示词模版 - main.py

"""
LangChain 1.0 基础教程 - 提示词模板 (Prompt Templates)
========================================================

本文件演示如何使用 LangChain 的提示词模板系统
涵盖以下核心概念:
1. PromptTemplate - 简单文本模板
2. ChatPromptTemplate - 聊天消息模板
3. 模板变量和格式化
4. 消息模板的组合
5. 实际应用场景

作者:LangChain 学习者
日期:2026年3月9日
"""

from openai import chat

from init_model import get_chat_model
from langchain_core.prompts import (
    PromptTemplate,
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
    AIMessagePromptTemplate,
)

# 初始化聊天模型 代码见init_model.py
chat_model = get_chat_model()


# ============================================================================
# 示例 1:为什么需要提示词模板?
# ============================================================================
def example_1():
    """
    示例1:对比字符串拼接 vs 模板

    问题:字符串拼接容易出错、难维护、不可复用
    解决:使用提示词模板
    """
    print("\n" + "=" * 70)
    print("示例 1:为什么需要提示词模板?")
    print("=" * 70)

    # ❌ 不推荐:使用字符串拼接
    print("\n【方式 1:字符串拼接(不推荐)】")
    print("-" * 70)

    topic = "Python"
    difficulty = "初学者"

    # 难以维护,容易出错
    prompt_str = f"你是一个{difficulty}级别的编程导师。请用简单易懂的语言解释{topic}。"
    print(f"提示词:{prompt_str}")
    response = chat_model.invoke(prompt_str)
    print(f"AI 回复:{response.content[:100]}...\n")

    # ✅ 推荐:使用 PromptTemplate
    template = PromptTemplate.from_template(
        "你是一个{difficulty}级别的编程导师。请用简单易懂的语言解释{topic}。"
    )

    print(f"模板:{template.template}")
    print(f"变量:{template.input_variables}")

    prompt = template.format(difficulty=difficulty, topic=topic)
    response = chat_model.invoke(prompt)
    print(f"AI 回复:{response.content[:100]}...\n")

    print("💡 优势:")
    print("  1. 可复用 - 同一个模板可以用于不同的输入")
    print("  2. 可维护 - 模板和数据分离,易于修改")
    print("  3. 类型安全 - 自动验证变量")
    print("  4. 可测试 - 更容易编写测试用例")


# 示例 2:PromptTemplate 基础用法


def example_2():
    """
    示例2:PromptTemplate 的基本用法

    PromptTemplate 用于简单的文本模板
    适合单一提示词的场景
    """
    print("\n" + "=" * 70)
    print("示例 2:PromptTemplate 基础用法")
    print("=" * 70)

    # 方法 1:使用 from_template(最简单)
    print("\n【方法 1:from_template(推荐)】")
    template1 = PromptTemplate.from_template("将以下文本翻译成{language}:\n{text}")
    prompt1 = template1.format(language="法语", text="Hello, how are you?")
    print(f"提示词 1:{prompt1}")
    response1 = chat_model.invoke(prompt1)
    print(f"AI 回复 1:{response1.content[:100]}...\n")

    # 方法 2:显式指定变量(更严格)
    print("【方法 2:显式指定变量】")
    template2 = PromptTemplate(
        input_variables=["product", "feature"],
        template="为{product}写一句广告语,重点突出{feature}特点。",
    )
    prompt2 = template2.format(product="智能音箱", feature="语音识别")
    print(f"提示词 2:{prompt2}")
    response2 = chat_model.invoke(prompt2)
    print(f"AI 回复:{response2.content}\n")

    # 方法 3:使用 invoke(直接生成消息)
    print("【方法 3:使用 invoke(更方便)】")
    template3 = PromptTemplate.from_template(
        "写一首关于{theme}的{style}风格的诗,不超过4行。"
    )
    # invoke 直接返回格式化后的值
    prompt_value = template3.invoke({"theme": "春天", "style": "现代"})


def example_3():
    """
    示例3:ChatPromptTemplate 的基本用法

    ChatPromptTemplate 用于构建聊天消息
    支持 system、user、assistant 多种角色
    """
    # 方法 1:使用元组格式(最简单,推荐)
    print("\n【方法 1:元组格式】")
    chat_template = ChatPromptTemplate.format_messages(
        [
            ("system", "你是一个{role},擅长{expertise}。"),
            ("user", "请解释{topic}。"),
        ]
    )

    # 格式化模板
    messages = chat_template.format_messages(
        role="Python 导师",
        expertise="用简单的方式解释复杂概念",
        task="解释什么是列表推导式",
    )
    response = chat_model.invoke(messages)

    # 方法 2:使用字符串简写(最简洁)
    simple_template = ChatPromptTemplate.from_messages(
        [("system", "你是一个友好的助手"), ("user", "{question}")]
    )

    messages = simple_template.format_messages(question="什么是机器学习?")
    response = chat_model.invoke(messages)


# ============================================================================
# 示例 4:多轮对话模板
# ============================================================================
def example_4():
    """
    示例4:构建多轮对话的模板

    包含系统提示、对话历史和当前问题
    """
    print("\n" + "=" * 70)
    print("示例 4:多轮对话模板")
    print("=" * 70)

    # 创建包含对话历史的模板
    template = ChatPromptTemplate.from_messages(
        [
            ("system", "你是一个专业的编程导师,擅长解释复杂概念。"),
            ("user", "{question}"),
            ("assistant", "{answer1}"),
            ("user", "{question2}"),
        ]
    )
    print("模板结构:")
    print("  1. System: 设定角色和指令")
    print("  2. User: 第一个问题")
    print("  3. Assistant: 第一个回答")
    print("  4. User: 第二个问题(基于上下文)\n")
    # 填充模板
    prompt = template.format_messages(
        role="Python 专家",
        instruction="回答要简洁、准确",
        question="什么是列表?",
        answer1="列表是 Python 中的有序可变集合,用方括号 [] 表示。",
        question2="它和元组有什么区别?",  # 基于上下文的问题
    )
    response = chat_model.invoke(prompt)


# ============================================================================
# 示例 5:使用 MessagePromptTemplate(高级)
# ============================================================================
def example_5():
    """
    示例5:使用 MessagePromptTemplate 类

    提供更细粒度的控制
    """
    print("\n" + "=" * 70)
    print("示例 5:MessagePromptTemplate 类(高级用法)")
    print("=" * 70)

    # 分别创建不同类型的消息模板
    system_template = SystemMessagePromptTemplate.from_template(
        "你是一个{profession},你的特长是{specialty}。"
    )
    human_template = HumanMessagePromptTemplate.from_template("请解释{topic}。")
    ai_template = AIMessagePromptTemplate.from_template("我会用{language}来解释。")

    # 组合成 ChatPromptTemplate
    chat_template = ChatPromptTemplate.from_messages([system_template, human_template])

    # 使用模板
    messages = chat_template.format_messages(
        profession="数据科学家",
        specialty="用数据讲故事",
        topic="数据可视化",
        question="如何选择合适的图表类型?",
    )
    response = chat_model.invoke(messages)
    print(f"AI 回复:{response.content[:200]}...\n")


# ============================================================================
# 示例 6:部分变量(Partial Variables)
# ============================================================================
def example_6():
    """
    示例6:部分变量 - 预填充某些变量

    适用场景:
    - 某些变量固定不变
    - 需要创建模板变体
    """
    print("\n" + "=" * 70)
    print("示例 6:部分变量(Partial Variables)")
    print("=" * 70)
    # 创建原始模板

    # 创建原始模板
    original_template = ChatPromptTemplate.from_messages(
        [("system", "你是一个{role},你的目标用户是{audience}。"), ("user", "请{task}")]
    )
    # 部分填充:固定 role 和 audience
    partially_filled = original_template.partial(role="科技博客作者", audience="程序员")
    messages1 = partially_filled.format_messages(
        task="写一篇关于 Python 装饰器的文章开头"
    )
    response1 = chat_model.invoke(messages1)
    print(f"文章 1:{response1.content[:150]}...\n")

    # 复用模板,不同的 task
    messages2 = partially_filled.format_messages(task="写一篇关于异步编程的文章开头")

    response2 = model.invoke(messages2)
    print(f"文章 2:{response2.content[:150]}...\n")


def example_7():
    """
    示例9:模板 + 模型的链式调用

    LangChain Expression Language (LCEL)
    """
    print("\n" + "=" * 70)
    print("示例 9:LCEL 链式调用(预览)")
    print("=" * 70)

    # 创建模板
    template = ChatPromptTemplate.from_messages(
        [("system", "你是一个{role}"), ("user", "{input}")]
    )
    # 使用 | 运算符创建链
    chain = template | chat_model
    print("链的组成:")
    print("  模板 | 模型")
    print("  (Template) | (LLM)\n")

    # 直接调用链
    response = chain.invoke({"role": "幽默的程序员", "input": "解释什么是bug"})

    print(f"AI 回复:{response.content}\n")

    print("💡 链式调用的优势:")
    print("  1. 代码更简洁")
    print("  2. 组件可复用")
    print("  3. 易于调试和监控")
    print("  (详细内容将在后续模块学习)")


def main():
    example_1()
    input("\n按 Enter 继续...")

    example_2()
    input("\n按 Enter 继续...")

    example_3()
    input("\n按 Enter 继续...")

    example_4()
    input("\n按 Enter 继续...")

    example_5()
    input("\n按 Enter 继续...")

    example_6()
    input("\n按 Enter 继续...")


if __name__ == "__main__":
    main()
添加新评论