提示词模板-Prompt_Templates.py

# ===================================
# 学习目标
# ===================================
# 通过本模块,你将学习:

# 1. 为什么需要提示词模板
# 字符串拼接的问题
# 模板的优势

# 2.PromptTemplate
# 基本用法
# 变量替换
# 格式化方法

# 3.ChatPromptTemplate
# 聊天消息模板
# 多角色支持
# 对话历史管理

# 4.高级特性
# 部分变量
# 模板组合
# 可复用模板库

# 5.LCEL 链式调用
# 模板与模型的组合
# 管道运算符

from regex import D, P

from init_model import get_chat_model


chat_model = get_chat_model()

# 使用模板
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate


# 1. 为什么需要提示词模板?
# 🔴 问题:字符串拼接的缺点
# ❌ 不推荐的做法
def demo1():
    user_name = "张三"
    topic = "Python"
    prompt = f"你好 {user_name},我来帮你学习 {topic}"
    # 问题:
    #     ❌ 难以维护和修改
    #     ❌ 容易出现格式错误
    #     ❌ 不能复用
    #     ❌ 难以测试
    #     ❌ 混合了逻辑和数据


def demo2():
    template = PromptTemplate.from_template("你好 {user_name},我来帮你学习 {topic}")
    prompt = template.format(user_name="张三", topic="Python")
    # ✅ 可复用 - 一个模板,多次使用
    # ✅ 可维护 - 模板和数据分离
    # ✅ 类型安全 - 自动验证变量
    # ✅ 可测试 - 更容易编写测试
    # ✅ 可组合 - 可以组合多个模板


# 2. PromptTemplate - 简单文本模板
# PromptTemplate 用于创建简单的文本提示词,适合单一提示的场景。


# 方法 1:from_template(最简单,推荐)
def demo3():
    template = PromptTemplate.from_template("你的模板文本 {变量名}")
    # 方法 2:完整定义
    template = PromptTemplate(
        input_variables=["变量1", "变量2"], template="你的模板文本 {变量1} 和 {变量2}"
    )


##创建模板的三种方法
# 方法 1:from_template(推荐)
def demo4_1():
    template = PromptTemplate.from_template("将以下文本翻译成{language}:\n{text}")
    # 自动识别变量
    print(template.input_variables)  # ['language', 'text']


def demo4_2():
    template = PromptTemplate(
        input_variables=["product", "feature"],
        template="为{product}写一句广告语,重点突出{feature}特点。",
    )


# 方法 部分变量预填充
def demo4_3():
    template = PromptTemplate.from_template("你是一个{role},请{task}")
    # 预填充 role
    partial_template = template.partial(role="Python 导师")
    # 填充 task
    prompt = partial_template.format(task="解释一下什么是大模型?")
    print(prompt)  # 你是一个Python 导师,解释一下什么是大模型?


# 使用模板方法
# 方式 1:format() - 返回字符串
def demo5_1():
    temp = PromptTemplate.from_template("你好{name}")
    # 返回格式化后的字符串
    prompt_str = temp.format(name="张三")
    print(prompt_str)  # 你好张三
    # 直接传递给模型
    response = chat_model.invoke(prompt_str)
    print(response.content)  # 你好张三,我来帮你学习 Python


# 方式 2:invoke() - 返回 PromptValue
def demo5_2():
    temp = PromptTemplate.from_template("你好{name}")
    # 返回 PromptValue 对象
    prompt_value = temp.invoke({"name": "张三"})
    # 获取文本
    print(prompt_value.text)  # "你好 张三"


# ===================================
# 模版实战案例
# ===================================


# 示例 1:翻译模板
def demo6():
    translator = PromptTemplate.from_template(
        "将以下{source_lang}文本翻译成{target_lang}:\n{text}"
    )

    promat = translator.format(
        source_lang="英文", target_lang="中文", text="Hello, how are you?"
    )


# 示例 2:代码生成模板】、
def demo7():
    code_template = PromptTemplate.from_template(
        "用{language}编写一个{functionality}的函数。\n"
        "要求:\n"
        "1. {requirement1}\n"
        "2. {requirement2}"
    )
    prompt = code_template.format(
        language="Python",
        functionality="计算斐波那契数列",
        requirement1="使用递归实现",
        requirement2="添加类型注解",
    )


# 3. ChatPromptTemplate - 聊天消息模板
# ChatPromptTemplate 用于创建聊天格式的消息,支持多种角色(system、user、assistant)。

# 为什么需要 ChatPromptTemplate?

# PromptTemplate vs ChatPromptTemplate:
# 特性    PromptTemplate    ChatPromptTemplate
# 输出格式    纯文本字符串    消息列表
# 角色支持    ❌ 无    ✅ system/user/assistant
# 对话历史    ❌ 不支持    ✅ 支持
# 适用场景    简单提示    聊天、对话、多轮交互

# 消息类型
# 角色字符串    含义    用途
# "system"    系统消息    设定 AI 的行为、角色、规则
# "user" / "human"    用户消息    用户的输入/问题
# "assistant" / "ai"    AI 消息    AI 的回复(用于对话历史)


# 创建方法
# 方法 1:元组格式(最简单,推荐)
def demo8_1():
    chat_template = ChatPromptTemplate.from_messages(
        [("system", "你是一个专业的翻译。"), ("user", "{input}")]
    )
    messages = chat_template.format_messages(
        role="Python 导师", question="什么是装饰器?"
    )


# 方法 2:字符串简写
# 单独的字符串会被解释为 user 消息
def demo8_2():
    template = ChatPromptTemplate.from_messages(
        [("system", "你是助手"), "{user_input}"]  # 相当于 ("user", "{user_input}")
    )

    messages = template.format_messages(user_input="你好")


# 方法 3:使用 MessagePromptTemplate(高级)
from langchain_core.prompts import (
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)


def demo8_3():
    system_template = SystemMessagePromptTemplate.from_template("你是一个{role}")
    human_template = HumanMessagePromptTemplate.from_template("{question}")
    template = ChatPromptTemplate.from_messages([system_template, human_template])
    messages = template.format_messages(role="Python 导师", question="什么是装饰器?")


## 4. 模板的使用场景
# 方式 1:format_messages() - 返回消息列表
def demo9_1():
    template = ChatPromptTemplate.from_messages(
        [("system", "你是{role}"), ("user", "{input}")]
    )
    message = template.format_messages(role="Python 导师", input="什么是装饰器?")
    # 直接传递给模型
    response = chat_model.invoke(message)
    print(
        response.content
    )  # 装饰器是 Python 中一种特殊的函数,用于修改其他函数的行为。


# 方式 2:invoke() - 返回 ChatPromptValue
def demo9_2():
    template = ChatPromptTemplate.from_messages(
        [("system", "你是{role}"), ("user", "{input}")]
    )
    # 返回 ChatPromptValue 对象
    prompt_value = template.invoke({"role": "助手", "input": "你好"})
    messages = prompt_value.to_messages()
    print(messages)


# ===================================
# 实用案例
# ===================================


# 示例 1:简单聊天
def demo_chat():
    template = ChatPromptTemplate.from_messages(
        [("system", "你是一个友好的{role},擅长{skill}"), ("user", "{question}")]
    )
    messages = template.format_messages(
        role="编程导师", skill="用简单语言解释复杂概念", question="什么是递归?"
    )
    response = chat_model.invoke(messages)


# 示例 2:多轮对话
def demo_chat_multi():
    template = ChatPromptTemplate.from_messages(
        [
            ("system", "你是一个专业的{role},擅长{skill}"),
            ("user", "{question}"),
            ("assistant", "{answer}"),
        ]
    )
    messages = template.format_messages(
        role="Python 专家",
        question1="什么是列表?",
        answer1="列表是 Python 的有序可变集合。",
        question2="它和元组有什么区别?",  # 基于上下文
    )


# 示例 3:结构化指令
def demo_chat1():

    structured_template = ChatPromptTemplate.from_messages(
        [
            (
                "system",
                "你是一个{domain}专家。\n"
                "回答风格:{style}\n"
                "回答长度:{length}字以内",
            ),
            ("user", "{question}"),
        ]
    )
    messages = structured_template.format_messages(
        domain="机器学习",
        style="技术性强、简洁",
        length="100",
        question="什么是梯度下降?",
    )


# 4. 高级特性

# 4.1 部分变量(Partial Variables)
# 预填充某些固定不变的变量,创建模板的变体

# 使用场景:
# 某些变量在所有调用中都相同
# 需要为不同用户/场景创建定制模板


# 语法:
def demo_partial():
    # 创建一个初始模板
    template = ChatPromptTemplate.from_messages(
        [("system", "你是{role},目标用户是{audience}"), ("user", "{task}")]
    )

    # 预填充模版部分数据
    customer_support_template = template.partial(role="客服专员", audience="普通用户")
    # 现在只需要提供 task
    messages = customer_support_template.format_messages(task="解释退款政策")
    response = chat_model.invoke(messages)


# 实用示例:
def demo_chat2():
    # 创建一个初始模板
    # 基础翻译模板
    translator = ChatPromptTemplate.from_messages(
        [("system", "你是专业翻译,精通{source}和{target}"), ("user", "翻译:{text}")]
    )

    # 创建英译中的专用模板
    en_to_zh = translator.partial(source="英语", target="中文")
    # 创建中译英的专用模板
    zh_to_en = translator.partial(source="中文", target="英语")

    # 英译中
    messages = en_to_zh.format_messages(text="Hello, how are you?")
    response = chat_model.invoke(messages)
    print(response.content)
    # 中译英
    messages = zh_to_en.format_messages(text="你好,我很好")
    response = chat_model.invoke(messages)
    print(response.content)


# 模板组合
# 将多个模板片段组合成复杂的提示词。
# 方法 1:字符串组合
def demo_chat3():
    # 定义可复用的部分
    # 定义可复用的部分
    role_part = "你是一个{domain}专家。"
    style_part = "回答风格:{style}。"
    constraint_part = "限制:{constraint}。"

    # 组合
    full_system = role_part + style_part + constraint_part
    template = ChatPromptTemplate.from_messages(
        [("system", full_system), ("user", "{question}")]
    )


# 方法 2:使用 + 运算符
def demo_chat4():
    template1 = ChatPromptTemplate.from_messages([("system", "你是助手")])
    template2 = ChatPromptTemplate.from_messages([("user", "{input}")])
    # 组合(LangChain 1.0 支持)
    combined = template1 + template2
    # 格式化
    messages = combined.format_messages(input="你好")
    response = chat_model.invoke(messages)
    print(response.content)


# 4.3 可复用模板库
# 在实际项目中,建议创建模板库。

# 示例:模板库
# templates.py


# from langchain_core.prompts import ChatPromptTemplate

# class PromptTemplates:
#     """可复用的提示词模板库"""

#     TRANSLATOR = ChatPromptTemplate.from_messages(
#         [("system", "你是专业翻译,精通{source}和{target}"), ("user", "翻译:{text}")]
#     )
#     CODE_REVIEWER = ChatPromptTemplate.from_messages(
#         [
#             ("system", "你是{language}代码审查专家,重点关注{focus}"),
#             ("user", "审查代码:\n```{language}\n{code}\n```"),
#         ]
#     )
#     SUMMARIZER = ChatPromptTemplate.from_messages(
#         [
#             ("system", "你是内容摘要专家"),
#             ("user", "将以下内容总结为{num}个要点:\n{content}"),
#         ]
#     )

#     TUTOR = ChatPromptTemplate.from_messages(
#         [("system", "你是{subject}导师,学生水平:{level}"), ("user", "{question}")]
#     )

# 使用
# from templates import PromptLibrary

# messages = PromptLibrary.TRANSLATOR.format_messages(
#     source_lang="英语",
#     target_lang="中文",
#     text="Hello World"
# )


# 5. LCEL 链式调用(预览)
# LCEL = LangChain Expression Language,LangChain 的表达式语言。

# 什么是链(Chain)?
# 链是将多个组件连接在一起的方式,形成处理流程。
# 输入 → 模板 → 模型 → 输出


# 使用管道运算符 |


def demo_chat5():
    # 创建组件
    template = ChatPromptTemplate.from_messages(
        [("system", "你是{role}"), ("user", "{input}")]
    )
    # 使用 | 创建链
    chain = template | chat_model
    response = chain.invoke(
        {
            "role": "客服专员",
            "input": "解释退款政策",
        }
    )
    print(response.content)


# 链的优势
# 优势    说明
# 简洁    一行代码完成多步操作
# 可读    清晰展示数据流向
# 可组合    可以轻松添加/删除组件
# 可复用    链本身可以作为组件
# 详细内容将在后续模块学习。

# 常见问题 (FAQ)

# Q1: PromptTemplate 和 ChatPromptTemplate 有什么区别?
# A:
# 特性    PromptTemplate    ChatPromptTemplate
# 输出    字符串    消息列表
# 角色    无    system/user/assistant
# 适用场景    简单提示    聊天、对话

# 建议:
# 简单场景 → PromptTemplate
# 聊天场景 → ChatPromptTemplate(推荐)


# Q2: 什么时候使用部分变量?
# A: 当某些变量在多次调用中保持不变时:
# 场景:为不同部门创建专用模板\
# def demo_chat6():

#     base_template = ChatPromptTemplate.from_messages(
#         [("system", "你是{department}的{role}"), ("user", "{task}")]
#     )
#     # IT 部门
#     it_template = base_template.partial(department="IT", role="开发工程师")
#     # 销售部门
#     sales_template = base_template.partial(department="销售部门", role="销售顾问")


# Q3: 如何在模板中使用换行和特殊字符?


# A: 使用三引号字符串:
def demo_chat7():
    template = PromptTemplate.from_template(
        """
            你是一个{role}。

            请完成以下任务:
            1. {task1}
            2. {task2}

            注意事项:
            - {note1}
            - {note2}
        """
    )

    # Q4: 模板变量可以是什么类型?
    # A: 通常是字符串,但也可以是其他可转换为字符串的类型:


def demo_chat8():
    template = PromptTemplate.from_template("生成{count}个关于{topic}的想法")
    # count 是整数
    prompt = template.format(count=5, topic="创新")


# Q5: 如何处理可选变量?
# A: 使用部分变量或默认值:
def demo_chat9():
    # 方法 1:部分变量
    template = PromptTemplate.from_template("{greeting} {name},{message}")
    template_with_default = template.partial(greeting="你好")

    # 方法 2:在应用层处理
    def create_prompt(name, message, greeting="你好"):
        return template.format(greeting=greeting, name=name, message=message)


# 最佳实践
# 1. 模板命名规范
# ✅ 好的命名
# translator_template = ...
# code_review_template = ...
# customer_support_template = ...

# # ❌ 不好的命名
# template1 = ...
# t = ...
# my_template = ...

# 2.组织模版

# templates/
# ├── __init__.py
# ├── common.py        # 通用模板
# ├── translation.py   # 翻译相关
# └── coding.py        # 编程相关


def demo_chat9_2():
    # common.py
    FRIENDLY_ASSISTANT = ChatPromptTemplate.from_messages(
        [("system", "你是一个友好的助手"), ("user", "{input}")]
    )


# 3. 文档化模板
class Templates:
    """项目模板库"""

    TRANSLATOR = ChatPromptTemplate.from_messages(
        [("system", "你是专业翻译"), ("user", "翻译:{text}")]
    )
    """
    翻译模板

    变量:
        - text: 要翻译的文本

    示例:
        messages = TRANSLATOR.format_messages(text="Hello")
    """


# 4. 测试模板
# def test_translator_template():
#     """测试翻译模板"""
#     template = PromptLibrary.TRANSLATOR

#     # 测试变量识别
#     assert "text" in template.input_variables

#     # 测试格式化
#     messages = template.format_messages(text="Hello")
#     assert len(messages) == 2
#     assert messages[0].type == "system"
#     assert messages[1].type == "user"


def main():
    demo9_2()


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