〇门槛 快速上手
一分钟速成提示工程!
直接 pip install
安装 🌟
从 PyPI 安装:
pip install promplate[openai]
你也可以用任何你喜欢的源(比如以清华源为例):
pip install promplate[openai] -i https://pypi.tuna.tsinghua.edu.cn/simple
我们只是用 OpenAI
来做演示。实际上,你可以使用任何你想要的LLM。
让LLM生成文本!OpenAI 启动!
首先,打开一个python REPL 💻 (或者ipython
或者jupyter
都可以。任何你喜欢的python终端都可以)
下面的所有代码都可以直接运行,只要你是一行行复制粘贴过去的,都可以正常得出结果。
>>> from promplate.llm.openai import ChatComplete # 这个类只是对OpenAI的官方SDK的封装而已 >>> complete = ChatComplete(api_key="...")
在
api_key
填你的 API Key 就行
然后像这样调用:
>>> complete("你好", model="gpt-4o-mini") '你好!有什么可以帮助你的吗?'
你可能懒得每次调用 complete
的时候都要填写 model
参数,那你可以把参数绑定到 complete
上面:
>>> complete = ChatComplete(api_key="...").bind(model="gpt-4o-mini")
然后只需用一个字符串来调用它:
>>> complete("你是谁") '我是一位聊天机器人,可以回答你的问题和进行对话。有什么可以帮助你的吗?'
😭😭 如果你没有 API Key
我有个教育目的的免费代理站,你不用 API Key 也能免费使用。像这样填写base_url
字段即可:
>>> from promplate.llm.openai import ChatComplete >>> complete = ChatComplete(base_url="https://promplate.dev", api_key="").bind(model="gpt-4o-mini") >>> complete("随便说点什么") '今天的天气真是美好,阳光明媚,让人心情也变得愉快起来。希望每个人都能在这样的日子里感受到幸福和快乐。无论遇到什么困难和挑战,都要坚持积极向前,相信明天会更好。愿大家都拥有一个美好的一天!'
如果你想使用 instruct 模型 🤔
只需简单地将ChatComplete
替换为 TextComplete
:
>>> from promplate.llm.openai import TextComplete >>> complete = TextComplete(api_key="...").bind(model="gpt-3.5-turbo-instruct") >>> complete("我是") '人也像你\n缘起在那个年代,'
Complete
实例时,你可以传递参数,比如 temperature,也可以在初始化时修改参数:
>>> complete("1 + 1 = ", temperature=0, max_tokens=1) '2'
想迭代流式响应也很简单 👀
只需使用ChatGenerate
,然后用 for 循环去迭代它:
>>> from promplate.llm.openai import ChatGenerate >>> generate = ChatGenerate(api_key="...").bind(model="gpt-4o-mini") >>> for i in generate("为什么 1 + 1 = 2"): ... print(i, end="", flush=True) # 这会逐渐打印生成的token ... 1 + 1 = 2 是数学中的基本原理,这个等式符合加法运算规则。当我们将一个物体与另一个相同的物体放在一起时,我们就会有两个物体。所以,1个物体加上另一个物体等于2个物体。这是数学中的基本概念之一。
模板!如何使用 Promplate 的模板表示动态的 prompt
在你的提示中必然有一些动态的内容,比如用户输入的问题,从数据库中检索到的数据,网上搜索的结果等。
在 promplate 中,只需使用 {{ }}
就可以插入动态数据。
>>> import time >>> from promplate import Template >>> greet = Template("结合当前时间向我请安。现在是 {{ time.asctime() }}") >>> greet.render(locals()) '结合当前时间向我请安。现在是 Sat Feb 24 19:57:36 2024'
借助刚刚创建的 complete
对象来执行它:
>>> complete(_) # _ 在 REPL 中就是上一个表达式的值 '您好!现在是2024年2月24日周六晚上7点58分50秒,祝您身体健康,心情愉快!有什么可以帮助您的吗?祝您一切顺利!'
可以看到,它根据我们的当前时间给出了合适的问候语。
实际上,你可以在 {{ }}
里面使用任何python表达式。
问题有点复杂?分解成子问题逐个解决!
有时候需要组合多个 prompt 来完成任务:
- 如果任务比较复杂,可能很难在一个 prompt 中描述清楚
- 将大任务分解成小任务分别执行有可能可以减少 token 消耗量
- 如果你要让模型输出结构化的数据(通过XML或者JSON),往往先生成正常结果再
- 将任务分解成部分来完成是符合人类直觉的
- 将大任务分解成子任务可能会增强可解释性,debug 时更容易定位错误
- …
在 prompate
中,我们使用 Node
来表示一个单一的”任务”。你可以用一个字符串来初始化一个”任务”:
>>> from promplate import Node >>> greet = Node("{{ time.asctime() }} 是上午还是下午?请用英文回答。", locals()) >>> greet.render() # 你已经在这个 Node 初始化时传递了上下文 'Sat Feb 24 19:59:41 2024 是上午还是下午?请用英文回答。'
一个 Node
就是一个加了许多实用功能的 Template
:
像魔法一样,你可以直接将两个节点相加,表示先后连接的顺序:
>>> translate = Node('将 """{{ __result__ }}""" 翻译成 {{ target_language }}') >>> chain = greet + translate # 这表示了"用中文打招呼"的流程
然后像这样调用:
>>> chain.invoke({"target_language": "zh_CN"}, complete) >>> _.result '早上好!'
一些细节
注意 .run()
的返回类型是 ChainContext
,这是一个 dict
的子类,但是比 dict
多了一些东西:
__result__
键在.run()
时被自动分配为上一个Node
的输出,你可以在模板中用{{ __result__ }}
访问它;- 在模板外部,你可以使用
ChainContext
的.result
来获取最后的输出。
以下三个表达式应该返回相同的字符串:
>>> template = Template("...") >>> complete(template.render())
>>> Node("...").invoke()["__result__"]
>>> Node("...").invoke().result
这部分可能有点难理解。但这些都是为了这个框架的灵活性。其实,等你的工程逐渐变大了,你会发现这种封装就是最佳实践。
Agent = LLM + Tools! 给 Chain
注册回调!
有些事情LLM做不了,更适合用代码来完成。例如:
- LLM只会返回字符串,但我们有时需要将其解析为结构化的数据格式,如
dict
或list
Chain
默认只保留最新的__result__
,而可能也需要保留下来中间的Node
的输出- 后一个
Node
可能不能直接使用前一个Node
的结果,而是需要进行一些处理 - …
在 promplate
中,你可以在 LLM 运行前后分别注册一个或多个回调,作为”预处理”和”后处理”
除了手动实现 Callback
接口,你可以直接用装饰器语法来注册回调:
>>> @greet.end_process ... @translate.end_process ... def log_greet_result(context): ... print(context.result) ... >>> chain.invoke({"target_language": "zh_CN"}, complete) It is in the afternoon. 现在是下午。 ChainContext({'target_language': 'zh_CN', '__result__': '现在是下午。'})
上面这是一个将第一个 Node
的结果 print 出来的回调。事实上,你可以在回调中随意读取和写入 context
恭喜你 🎉 你已经学会了使用 promplate
进行提示工程的基本范式。感谢你的阅读!还有很多没有提到的特性在这个速成教程中没有提到。你可以前往其它页面了解更多 🤗
有任何问题,都欢迎在 GitHub Discussions 提问!