协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
dspy【开发与工程】DSPy is a Python framework from Stanford NLP that replaces hand-written prompts with code: you declare LLM tasks as typed signatures, compose them into modules, and let optimizers (BootstrapFewShot, MIPROv2, GEPA) tune the prompts and few-shot examples against your metric. Use when the user asks about DSPy, signatures, ChainOfThought, ReAct, teleprom…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
DSPy lets you describe what an LLM step takes in and returns (a signature), pick how it should run (Predict, ChainOfThought, ReAct), compose steps in a dspy.Module, and then optimize the whole program with a metric and a few examples. Models are called through LiteLLM-style identifiers such as openai/gpt-4o-mini or gemini/gemini-2.5-flash, so the same code moves between providers. This skill covers the current 3.x API; code written for 2.x (dspy.Assert, dspy.Suggest, dspy.OpenAI(...), dspy.settings.configure) needs porting.
pip install -U dspy
export OPENAI_API_KEY=... # or the key of whichever provider you use
import dspy
dspy.configure(lm=dspy.LM("openai/gpt-4o-mini")) # global default
Use with dspy.context(lm=other_lm): to override the model for one call.
A signature is either a string ("question -> answer") or a class with typed fields. Use Literal[...] or other Python types to constrain outputs. Predictors: dspy.Predict, dspy.ChainOfThought (adds a reasoning output field), dspy.ReAct (tool-using agent), dspy.ProgramOfThought.
Subclass dspy.Module, call super().__init__(), create predictors in __init__, and write the logic in forward. For retrieval, dspy.retrievers.Embeddings(embedder=..., corpus=[...], k=3) is a local in-process retriever (needs numpy); dspy.Retrieve only works after you configure a retrieval model such as dspy.ColBERTv2 via dspy.configure(rm=...).
dspy.Example(...).with_inputs("question") objects (inputs marked, other fields are labels).(example, prediction, trace=None) -> bool | float.dspy.Evaluate(devset=devset, metric=metric, num_threads=8)(program).BootstrapFewShot (small data, a few dozen examples), MIPROv2 (instructions and demos, auto="light"|"medium"|"heavy"), GEPA (reflective prompt evolution; its metric may return feedback text), BootstrapFinetune for weights.optimized.save("program.json") and later program.load("program.json") on a freshly constructed module.dspy.Assert and dspy.Suggest were removed in 3.x. Use dspy.Refine(module=..., N=3, reward_fn=fn, threshold=1.0) (retry with feedback until the reward passes) or dspy.BestOfN (sample N, keep the best) instead; reward_fn(inputs_dict, prediction) returns a float.
User request: "Classify product reviews as positive, negative or neutral with a confidence score."
from typing import Literal
import dspy
dspy.configure(lm=dspy.LM("openai/gpt-4o-mini"))
class ReviewSentiment(dspy.Signature):
"""Classify the sentiment of a customer review."""
review: str = dspy.InputField()
sentiment: Literal["positive", "negative", "neutral"] = dspy.OutputField()
confidence: float = dspy.OutputField(desc="0.0 to 1.0")
classify = dspy.ChainOfThought(ReviewSentiment)
out = classify(review="It works but the manual is confusing")
print(out.reasoning, out.sentiment, out.confidence)
Result: a Prediction whose sentiment is one of the three literals (for example neutral), confidence is a float, and reasoning holds the model's step-by-step text. Prompt formatting is handled by DSPy.
User request: "Build a QA module over our docs and tune it on 30 labeled questions."
import dspy
from dspy.teleprompt import MIPROv2
dspy.configure(lm=dspy.LM("openai/gpt-4o-mini"))
corpus = open("docs/faq.txt").read().split("\n\n")
search = dspy.retrievers.Embeddings(
embedder=dspy.Embedder("openai/text-embedding-3-small"), corpus=corpus, k=3)
class DocsQA(dspy.Module):
def __init__(self):
super().__init__()
self.answer = dspy.ChainOfThought("context, question -> answer")
def forward(self, question):
return self.answer(context=search(question).passages, question=question)
def metric(example, pred, trace=None):
return example.answer.lower() in pred.answer.lower()
trainset = [dspy.Example(question=q, answer=a).with_inputs("question") for q, a in labeled[:20]]
devset = [dspy.Example(question=q, answer=a).with_inputs("question") for q, a in labeled[20:]]
evaluate = dspy.Evaluate(devset=devset, metric=metric, num_threads=8)
print("baseline", evaluate(DocsQA()).score)
tuned = MIPROv2(metric=metric, auto="light").compile(DocsQA(), trainset=trainset)
print("tuned", evaluate(tuned).score)
tuned.save("docs_qa.json")
Result: two scores (percent on the dev set) so you can see whether optimization helped, and a docs_qa.json holding the tuned instructions and demos.
auto="light", set num_threads carefully against rate limits, and expect a real API bill on large trainsets.OPENAI_API_KEY, or pass api_key=os.environ[...] to dspy.LM.cache=False to dspy.LM when benchmarking or sampling several times.dspy version in production: the API moved noticeably between 2.x and 3.x.