0Pricing
AI Prompt Engineering · 课时

定义签名与模块

签名语法、ChainOfThought、ReAct 以及自定义 DSPy 模块。

定义签名与模块 是 CoddyKit 上的免费 AI Prompt Engineering 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Prompt Engineering 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Prompt Engineering 课程共包含 4 节课。

signature 是类型化契约

DSPy 的 signature 是一个 Python 类,用于声明推理步骤的输入和输出。您可以将它理解为 LLM 调用的类型化函数契约。

文档字符串会成为任务描述。字段注解会告诉 DSPy 要生成什么。您无需编写实际的提示词文本,DSPy 会根据这份声明推导出提示词。

定义基本 signature

最小的 signature 继承 dspy.Signature,并将字段标注为 InputField 或 OutputField。类的文档字符串提供任务指令。

import dspy

class QASignature(dspy.Signature):
    """Answer the question based on the given context."""
    context: str = dspy.InputField(desc='Relevant background text')
    question: str = dspy.InputField(desc='The question to answer')
    answer: str = dspy.OutputField(desc='A concise answer')

# Inspect what DSPy sees
print(QASignature.instructions)  # The docstring
print(list(QASignature.input_fields.keys()))   # ['context', 'question']
print(list(QASignature.output_fields.keys()))  # ['answer']

多个输出字段

signature 可以包含多个输出字段。DSPy 会提示模型在一次调用中生成所有输出。这对于提取结构化信息很有用。

import dspy

class EntityExtraction(dspy.Signature):
    """Extract named entities from the text."""
    text: str = dspy.InputField()
    people: list[str] = dspy.OutputField(desc='List of person names mentioned')
    organizations: list[str] = dspy.OutputField(desc='List of organization names')
    locations: list[str] = dspy.OutputField(desc='List of place names')

extractor = dspy.Predict(EntityExtraction)
result = extractor(text='Elon Musk founded SpaceX in Hawthorne, California.')
print(result.people, result.organizations, result.locations)

Predict 模块

dspy.Predict 是最简单的模块。它接收一个 signature,直接要求 LM 生成输出。它不会添加推理框架,只会生成与 signature 匹配的结构化提示词。

当任务很直接且不需要明确的推理步骤时,请使用 Predict。

import dspy

class Classify(dspy.Signature):
    """Classify the sentiment of the review."""
    review: str = dspy.InputField()
    sentiment: str = dspy.OutputField(desc='positive, negative, or neutral')

# Predict wraps the signature with a direct prompt
classifier = dspy.Predict(Classify)
result = classifier(review='The food was amazing and the service was excellent!')
print(result.sentiment)  # positive

ChainOfThought 模块

dspy.ChainOfThought 会为 signature 添加一个中间的 reasoning 字段。模型会先写出推理过程,然后生成最终答案。

对于多步骤问题,这种方式可以稳定提升准确率,而且您无需编写任何思维链提示词指令。

import dspy

class MathSolver(dspy.Signature):
    """Solve the math problem."""
    problem: str = dspy.InputField()
    answer: str = dspy.OutputField(desc='The numerical answer')

# ChainOfThought adds a 'reasoning' step automatically
solver = dspy.ChainOfThought(MathSolver)
result = solver(problem='If a train travels 60 mph for 2.5 hours, how far does it go?')
print(result.reasoning)  # Step-by-step reasoning
print(result.answer)     # 150 miles

ReAct 模块

dspy.ReAct 实现了推理 + 行动循环。模型会在推理步骤和工具调用之间交替进行,因此非常适合需要搜索、计算或获取数据的代理。

您只需提供工具列表(带有文档字符串的 Python 函数),DSPy 会自动处理它们之间的交替过程。

import dspy

def search_web(query: str) -> str:
    """Search the web and return relevant results."""
    # In production, call a real search API
    return f'Search results for: {query}'

def calculate(expression: str) -> str:
    """Evaluate a mathematical expression."""
    return str(eval(expression))

class ResearchQA(dspy.Signature):
    """Answer the question using web search and calculation as needed."""
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

agent = dspy.ReAct(ResearchQA, tools=[search_web, calculate])
result = agent(question='What is 15% of 847?')
print(result.answer)

将模块组合成程序

将模块组合成多步骤程序,才能发挥真正的威力。继承 dspy.Module,在 __init__ 中定义子模块,并实现 forward() 将它们串联起来。

import dspy

class RetrieveAndAnswer(dspy.Module):
    def __init__(self):
        super().__init__()
        self.retrieve = dspy.Retrieve(k=3)  # Retrieves top-3 passages
        self.generate = dspy.ChainOfThought('context, question -> answer')

    def forward(self, question):
        passages = self.retrieve(question).passages
        context = '\n'.join(passages)
        return self.generate(context=context, question=question)

# This is a complete RAG pipeline in ~10 lines
rag = RetrieveAndAnswer()
result = rag(question='What are the main causes of climate change?')
print(result.answer)

内联 signature 简写

对于简单情况,DSPy 接受内联字符串 signature:'input1, input2 -> output1, output2'。无需定义完整的类,就可以快速制作原型,非常方便。

import dspy

# Full class signature
class Translate(dspy.Signature):
    """Translate text to French."""
    text: str = dspy.InputField()
    translation: str = dspy.OutputField()

# Equivalent inline shorthand
translator_v1 = dspy.Predict(Translate)
translator_v2 = dspy.Predict('text -> translation')  # Less metadata

# Both work the same way
result = translator_v1(text='Hello world')
print(result.translation)

字段描述很重要

InputField 和 OutputField 中的 desc 参数会被包含在生成的提示词中。优秀的描述可以精确地引导模型。

您可以将 desc 理解为字段级文档,它会与字段名称一起出现在提示词中。

import dspy

class Summarize(dspy.Signature):
    """Summarize the article for a busy executive."""
    article: str = dspy.InputField(
        desc='The full article text to summarize'
    )
    summary: str = dspy.OutputField(
        desc='3-5 bullet points highlighting key decisions and numbers'
    )
    confidence: float = dspy.OutputField(
        desc='Your confidence in the summary accuracy from 0.0 to 1.0'
    )

summarizer = dspy.Predict(Summarize)
# DSPy constructs a prompt using all the desc values automatically

保存和加载程序

优化完成后,您可以保存编译后的程序,这样就不必每次都重新运行优化。DSPy 会将优化后的状态序列化为 JSON 文件。

import dspy

class QA(dspy.Signature):
    """Answer questions accurately."""
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

program = dspy.ChainOfThought(QA)

# After optimization, save the compiled state
program.save('optimized_qa.json')

# Load it later without re-running optimization
loaded_program = dspy.ChainOfThought(QA)
loaded_program.load('optimized_qa.json')

result = loaded_program(question='What is the speed of light?')
print(result.answer)

用于输出约束的断言

DSPy 的断言让您可以声明输出约束。如果模型违反约束,DSPy 会自动结合纠正性反馈重试,无需手动编写重试逻辑。

import dspy

class ShortAnswer(dspy.Signature):
    """Answer in at most 10 words."""
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()

class ConstrainedQA(dspy.Module):
    def __init__(self):
        super().__init__()
        self.predict = dspy.Predict(ShortAnswer)

    def forward(self, question):
        result = self.predict(question=question)
        # Assert: answer must be at most 10 words
        dspy.Assert(
            len(result.answer.split()) <= 10,
            'The answer must be 10 words or fewer.'
        )
        return result

知识检查:ChainOfThought

使用相同的 signature 时,dspy.ChainOfThought 相比 dspy.Predict 增加了什么?

回顾:signature 和模块

DSPy 的 signature 是描述 LLM 步骤应执行什么操作的类型化类声明,包括输入、输出和文档字符串指令。Predict、ChainOfThought 和 ReAct 等模块围绕 signature 实现不同的推理策略。您可以在 dspy.Module 子类中组合多个模块,构建多步骤流水线。字段的 desc 值会在自动生成的提示词中引导模型,而断言则通过自动重试来强制执行输出约束。

常见问题解答

「定义签名与模块」课时是免费的吗?

是的 — 「定义签名与模块」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Prompt Engineering 课程的其余内容,请升级到 CoddyKit PRO。 AI Prompt Engineering 课程共包含 4 节课。

「定义签名与模块」这节课中我会学到什么?

签名语法、ChainOfThought、ReAct 以及自定义 DSPy 模块。 你通过在浏览器中直接运行的动手代码来练习 AI Prompt Engineering,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 AI Prompt Engineering 需要有经验吗?

无需任何先前经验。CoddyKit 上的 AI Prompt Engineering 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「定义签名与模块」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 AI Prompt Engineering 课中编写并运行代码吗?

能。每节 AI Prompt Engineering 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. DSPy 框架简介
  2. 定义签名与模块
  3. 编译与优化提示词
  4. 评估 DSPy 流程
← 返回 AI Prompt Engineering