返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

别再执着于大模型提示词技巧了,一起迈向program llms新时代!

[复制链接]
链载Ai 显示全部楼层 发表于 前天 10:04 |阅读模式 打印 上一主题 下一主题

在大模型之后,提示词工程师这个岗位开始在市场上出现,我司去年就设了这个岗位,虽然不知道他们具体的工作内容有哪些方向。提示词工程,实际上就是大量的玩家在试玩大模型之后总结出的技巧。互联网上搜一波可以看到大量的诸如50个大模型提示词技巧,100个提示词技巧。这些技巧本身都很不错,但是在试用之后,你可能发现,没有什么提示词策略是可以解决所有类型的问题的。

LLMs本身对提示词是非常敏感的,这意味着,在实际实验过程中,除了要求大模型输出某个内容,还需要约束它按照某种格式,各种条件约束下输出,以确保整体的稳定性。

今天分享的这个思路,是将prompt llms变成program llms,主要来源于斯坦福大学的DSPY框架。将大模型提示词工程转变成像写pytorch代码一样结构化。这个框架的首图如下:

在DSPY中,对应了3大核心模块,Signatures、Modules、Optimizers。如果还原到提示词工程中,Signatures相当于在书写提示词,而Modules就像你使用提示词技巧,比如思维链cot、react等,而Optimizers就像一步一步的去根据模型的生成结果调优提示词。

更具象化一点:

  • Signatures是我们告诉DSPY需要做什么,而不是告诉他应该如何做。例如:输入是文档,输出是摘要;输入是上下文+问题,输出是问题回复。
  • Modules,在DSPY是一些模块化的组件,比如说:dspy.ChainOfThought、dspy.ProgramOfThought,类似于一些可调用的函数
  • Optimizers,根据某个指标对整个流程自动优化。

接下来举个具体的例子:

比如说,我们想解决“姚明的妻子的出生年龄?”这个问题。看到这个问题,大家脑子里肯定蹦出了一堆的解决方案。这是个多跳问题,几乎不可能通过单轮搜索来解决这个问题,大多数系统可以得出“姚明的妻子是谁?”,但是无法回答后续的年龄问题。多轮搜索的系统,通过生成额外的搜索,收集必要的信息,可以得出最终答案,整体上还是蛮复杂的。但是这里举个例子,如何用DSPY只需要几行代码来实现并优化这个问题。

importdspy

turbo=dspy.OpenAI(model='gpt-3.5-turbo')
colbertv2=dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')

dspy.settings.configure(lm=turbo,rm=colbertv2)

加载测试数据,多跳问题,可以使用HotPotQA测试

fromdspy.datasetsimportHotPotQA

dataset=HotPotQA(train_seed=1,train_size=20,eval_seed=2023,dev_size=50,test_size=0)

trainset=[x.with_inputs('question')forxindataset.train]
devset=[x.with_inputs('question')forxindataset.dev]

len(trainset),len(devset)
#(20,50)

设置Signatures

classGenerateAnswer(dspy.Signature):
context=dspy.InputField()
question=dspy.InputField()
answer=dspy.OutputField()


classGenerateSearchQuery(dspy.Signature):

context=dspy.InputField()
question=dspy.InputField()
query=dspy.OutputField()

构建DSPY pipeline

fromdsp.utilsimportdeduplicate

classSimplifiedBaleen(dspy.Module):
def__init__(self,passages_per_hop=3,max_hops=2):
super().__init__()

self.generate_query=[dspy.ChainOfThought(GenerateSearchQuery)for_inrange(max_hops)]#多跳,每一跳都使用一个dspy.ChainOfThought
self.retrieve=dspy.Retrieve(k=passages_per_hop)
self.generate_answer=dspy.ChainOfThought(GenerateAnswer)
self.max_hops=max_hops

defforward(self,question):
context=[]

forhopinrange(self.max_hops):
query=self.generate_query[hop](context=context,question=question).query
passages=self.retrieve(query).passages
context=deduplicate(context+passages)

pred=self.generate_answer(context=context,question=question)
returndspy.Prediction(context=context,answer=pred.answer)

测试

my_question="HowmanystoreysareinthecastlethatDavidGregoryinherited?"

uncompiled_baleen=SimplifiedBaleen()
pred=uncompiled_baleen(my_question)

print(f"Question:{my_question}")
print(f"redictedAnswer:{pred.answer}")
print(f"RetrievedContexts(truncated):{[c[:200]+'...'forcinpred.context]}")

优化

上面提到过,可以用某个打分来优化DSPY的结果,定义一个评估函数

  • 预测答案与真实答案相符。
  • 检索到的上下文包含真实答案
  • 生成的搜索查询不能太杂乱,小于100个字符
  • 生成的搜索查询尽量不要重复(跟历史的相比,不能超过0.8)。
defvalidate_context_and_answer_and_hops(example,pred,trace=None):
ifnotdspy.evaluate.answer_exact_match(example,pred):returnFalse
ifnotdspy.evaluate.answer_passage_match(example,pred):returnFalse

hops=[example.question]+[outputs.queryfor*_,outputsintraceif'query'inoutputs]

ifmax([len(h)forhinhops])>100:returnFalse
ifany(dspy.evaluate.answer_exact_match_str(hops[idx],hops[:idx],frac=0.8)foridxinrange(2,len(hops))):returnFalse

returnTrue

使用 DSPy 中的BootstrapFewShot,通过少量示例来优化流程的预测器。

fromdspy.telepromptimportBootstrapFewShot

teleprompter=BootstrapFewShot(metric=validate_context_and_answer_and_hops)
compiled_baleen=teleprompter.compile(SimplifiedBaleen(),teacher=SimplifiedBaleen(passages_per_hop=2),trainset=trainset)

评估

fromdspy.evaluate.evaluateimportEvaluate


defgold_passages_retrieved(example,pred,trace=None):
gold_titles=set(map(dspy.evaluate.normalize_text,example["gold_titles"]))
found_titles=set(
map(dspy.evaluate.normalize_text,[c.split("|")[0]forcinpred.context])
)
returngold_titles.issubset(found_titles)

evaluate_on_hotpotqa=Evaluate(devset=devset,num_threads=1,display_progress=True,display_table=5)

uncompiled_baleen_retrieval_score=evaluate_on_hotpotqa(uncompiled_baleen,metric=gold_passages_retrieved,display=False)

compiled_baleen_retrieval_score=evaluate_on_hotpotqa(compiled_baleen,metric=gold_passages_retrieved)

print(f"##RetrievalScoreforuncompiledBaleen:{uncompiled_baleen_retrieval_score}")
print(f"##RetrievalScoreforcompiledBaleen:{compiled_baleen_retrieval_score}")


#Output
##RetrievalScoreforuncompiledBaleen:36.0
##RetrievalScoreforcompiledBaleen:60.0

在 DSPy 中结合多跳设置甚至可以超越人类反馈。即使是很小的模型,在 DSPy 设置中使用时也可以与更大尺寸模型进行比较。项目框架中有很多的优秀示例,感兴趣的小伙伴可以学习一波。




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

链载AI是专业的生成式人工智能教程平台。提供Stable Diffusion、Midjourney AI绘画教程,Suno AI音乐生成指南,以及Runway、Pika等AI视频制作与动画生成实战案例。从提示词编写到参数调整,手把手助您从入门到精通。
  • 官方手机版

  • 微信公众号

  • 商务合作

  • Powered by Discuz! X3.5 | Copyright © 2025-2025. | 链载Ai
  • 桂ICP备2024021734号 | 营业执照 | |广西笔趣文化传媒有限公司|| QQ