guidance

guidance

灵活高效的语言模型编程框架

Guidance是一个创新的语言模型编程框架,通过约束生成和控制流程来优化模型输出。它支持正则表达式、上下文无关文法等约束方式,并能灵活结合条件、循环等控制结构。Guidance可显著提升特定任务的输出质量,同时降低延迟和成本。该框架兼容多种后端,包括Transformers、llama.cpp和OpenAI等,具有广泛的适用性。

Guidance语言模型AI编程代码生成多模态Github开源项目
<div align="right"><a href="https://guidance.readthedocs.org"><img src="https://readthedocs.org/projects/guidance/badge/?version=latest&style=flat" /></a></div> <div align="center"><picture> <source media="(prefers-color-scheme: dark)" srcset="docs/figures/guidance_logo_blue_dark.svg"> <img alt="guidance" src="https://yellow-cdn.veclightyear.com/835a84d5/59896147-60a0-4cee-ae1c-7a43c552873e.svg" width=300"> </picture></div> <br/>

**Guidance是一种高效的编程范式,用于引导语言模型。**通过Guidance,您可以控制输出的结构,并为您的用例获得高质量的输出——*同时与传统的提示或微调相比,降低延迟和成本。*它允许用户约束生成(例如使用正则表达式和上下文无关文法),以及无缝地交织控制(条件语句、循环、工具使用)和生成。

安装

Guidance可通过PyPI获得,要使用特定模型,请参阅加载模型

pip install guidance

功能特性

编写纯Python代码,附加语言模型功能。

from guidance import models, gen # 加载模型(可以是Transformers、LlamaCpp、VertexAI、OpenAI等) llama2 = models.LlamaCpp(path) # 向模型追加文本或生成内容 llama2 + f'你想要笑话还是诗歌?' + gen(stop='。')
<img alt="你想要笑话还是诗歌?我给你一首诗" src="https://yellow-cdn.veclightyear.com/835a84d5/e7dbd7cf-b0c7-4875-9aa3-b5791d20f579.png" width="354">

使用选择(即选项集)、正则表达式上下文无关文法以及预构建组件(如子字符串、json)来约束生成

from guidance import select # 在两个选项之间进行简单选择 llama2 + f'你想要笑话还是诗歌?' + select(['笑话', '诗歌'])
<img alt="你想要笑话还是诗歌?诗歌" src="https://yellow-cdn.veclightyear.com/835a84d5/eeb465b3-4760-4167-9eec-09d01266776e.png" width="277">

轻松调用和部署工具,自动交织控制和生成。

轻松使用工具,模型在调用工具时停止生成,调用工具,然后恢复生成。例如,这里是一个简单版本的计算器,通过四个独立的"工具"实现:

@guidance def add(lm, input1, input2): lm += f' = {int(input1) + int(input2)}' return lm @guidance def subtract(lm, input1, input2): lm += f' = {int(input1) - int(input2)}' return lm @guidance def multiply(lm, input1, input2): lm += f' = {float(input1) * float(input2)}' return lm @guidance def divide(lm, input1, input2): lm += f' = {float(input1) / float(input2)}' return lm

现在我们使用这些工具作为选项调用gen。注意生成是如何自动停止和重新启动的:

lm = llama2 + '''\ 1 + 1 = add(1, 1) = 2 2 - 3 = subtract(2, 3) = -1 ''' lm + gen(max_tokens=15, tools=[add, subtract, multiply, divide])

<img width="201" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/646e1a7d-0206-419b-8206-1d835c3a0e0a"><br>

获得高兼容性——在多个后端执行单个Guidance程序

适用于Transformers、llama.cpp、AzureAI、VertexAI、OpenAI等。用户可以编写一个guidance程序并在多个后端执行。(注意,最强大的控制功能需要端点集成,目前在Transformers和llama.cpp上效果最佳)。

gpt = models.OpenAI("gpt-3.5-turbo") with user(): lm = gpt + "法国的首都是什么?" with assistant(): lm += gen("capital") with user(): lm += "关于它的一个简短而令人惊讶的事实是什么?" with assistant(): lm += gen("fact")

<img width="645" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/f31ed7b8-1868-44d2-b14c-4842b0a40e5c"><br>

通过有状态控制 + 生成函数获得速度提升——无需中间解析器。

与链式调用相比,Guidance程序相当于单次LLM调用。更重要的是,所有非生成文本的追加都会被批处理,因此当您有固定结构时,Guidance程序比让LLM生成中间文本更快

令牌修复

用户处理文本(或字节)而不是令牌,因此不必担心令牌边界问题,如"提示以空白结尾"。

使用f-strings的丰富模板。

llama2 + f'''\ 你想要笑话还是诗歌?{select(['笑话', '诗歌'])}好的,这是一句话:"{gen(stop='"')}" '''

<img width="358" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/486ca968-89b1-4c02-b914-3b9714fe5890"><br>

抽象聊天接口,为任何聊天模型使用正确的特殊令牌。

# 将我们的选择捕获在名为'answer'下 lm = llama2 + f"你想要笑话还是诗歌?{select(['笑话', '诗歌'], name='answer')}。\n" # 根据模型之前的选择做出选择 if lm["answer"] == "笑话": lm += f"这是一个关于猫的一句话笑话:" + gen('output', stop='\n') else: lm += f"这是一首关于狗的一句话诗:" + gen('output', stop='\n')

<img width="393" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/66d47ce7-1d5a-4dbd-b676-66b9c1094184"><br>

易于编写的可重用组件。

import guidance @guidance def one_line_thing(lm, thing, topic): lm += f'这是一个关于{topic}的一句话{thing}:' + gen(stop='\n') return lm # 返回我们更新后的模型 # 选择笑话或诗歌 lm = llama2 + f"你想要笑话还是诗歌?{select(['笑话', '诗歌'], name='thing')}。\n" # 调用我们的guidance函数 lm += one_line_thing(lm['thing'], '猫')

<img width="386" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/60071680-8bbb-4fa5-a298-613d4fd55fa7"><br>

预构建组件库

常见语法元素开箱即用,下面是substring的示例,其他(如json)请查看文档

from guidance import substring # 定义一组可能的陈述 text = 'guidance很棒。guidance非常好。guidance是自切片面包以来最好的东西。' # 强制模型做出精确引用 llama2 + f'这是关于guidance库的一个真实陈述:"{substring(text)}"'

<img width="589" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/9a7178ad-ed73-4e6b-b418-f9d2a3a76b88"><br>

流式支持,也集成了Jupyter笔记本。

lm = llama2 + '这是一首关于猫和狗的可爱五行诗:\n' for i in range(5): lm += f"第 {i+1} 行:" + gen(temperature=0.8, suffix="\n")
<img src="https://yellow-cdn.veclightyear.com/835a84d5/2d317f3a-56c1-4314-8ec4-6dbf409fc7d1.gif" width="337">

对于不支持guidance的丰富IPython/Jupyter/HTML可视化的环境(如控制台应用程序),可以通过在任何guidance.models对象的构造函数中设置echo=False来禁止所有可视化和控制台输出:

llama2 = models.LlamaCpp(path, echo=False)

多模态支持。

from guidance import image gemini = models.VertexAI("gemini-pro-vision") with user(): lm = gemini + "这是什么的图片?" + image("longs_peak.jpg") with assistant(): lm += gen("回答")
<img width="673" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/6450d05d-52e9-4ef5-b280-8b57e733d46d">

示例笔记本

我们正在更新我们的示例笔记本。以下是已更新的内容:

更多内容即将推出

基本生成

lm对象是不可变的,所以你通过创建新的副本来改变它。默认情况下,当你向lm追加内容时,它会创建一个副本,例如:

from guidance import models, gen, select llama2 = models.LlamaCpp(model) # llama2没有被修改,`lm`是`llama2`的副本,其状态中追加了'This is a prompt' lm = llama2 + 'This is a prompt'

<img width="124" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/c1e96b2b-8f4a-44ee-a8f4-a694a8d7784b"><br>

你可以向模型对象追加_生成_调用,例如

lm = llama2 + 'This is a prompt' + gen(max_tokens=10)

<img width="267" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/d2e5ed34-ba9d-4bdd-872d-2b76f8e3cf85"><br>

你也可以在生成调用之间穿插纯文本或控制流:

# 注意我们如何设置停止标记 lm = llama2 + '我喜欢和我的' + gen(stop=' ') + '玩' + gen(stop=['\n', '。', '!'])

<img width="279" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/2d47fd65-1982-4dd8-9ba9-a01e62fba455"><br>

约束生成

选择(基础)

select将生成限制在一组选项中:

lm = llama2 + '我喜欢的颜色是' + select(['红色', '蓝色', '绿色'])

<img width="137" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/f0b97629-78a9-439d-90b2-06af31fdc40e"><br>

正则表达式

gen有可选参数regexstop_regex,它们允许通过正则表达式控制生成(和停止)。

用正则表达式约束生成

无约束:

lm = llama2 + '问题:小明有十个球。他给了他弟弟三个。\n' lm += '小明还剩多少个球?\n' lm += '答案:' + gen(stop='\n')

<img width="405" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/55fb66ea-a717-417a-8a70-14c46eba4c66"><br>

用正则表达式约束:

lm = llama2 + '问题:小明有十个球。他给了他弟弟三个。\n' lm += '小明还剩多少个球?\n' lm += '答案:' + gen(regex='\d+')

<img width="404" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/b45a5a79-55e0-4c15-884a-fba830c0a153"><br>

使用正则表达式作为停止标准

无约束:

lm = llama2 + '19, 18,' + gen(max_tokens=50)

<img width="359" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/5dd13454-cc42-4e27-a52c-19a31237891c"><br>

使用传统停止文本,当模型生成数字7时停止:

lm = llama2 + '19, 18,' + gen(max_tokens=50, stop='7')

<img width="73" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/fc96d7c3-381d-4766-8bee-c930669f518a"><br>

当模型生成不被其他数字包围的字符7时停止:

lm = llama2 + '19, 18,' + gen(max_tokens=50, stop_regex='[^\d]7[^\d]')

<img width="293" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/a657e566-b1a4-447a-82a5-b88977b5fedf"><br>

上下文无关文法

我们提供了多种操作符,使定义CFG变得容易,这些CFG可以用来约束生成。 例如,我们可以使用select操作符(它接受CFG作为选项)、zero_or_moreone_or_more来定义数学表达式的语法:

import guidance from guidance import one_or_more, select, zero_or_more # stateless=True表示此函数不依赖于LLM生成 @guidance(stateless=True) def number(lm): n = one_or_more(select(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])) # 允许负数或正数 return lm + select(['-' + n, n]) @guidance(stateless=True) def operator(lm): return lm + select(['+' , '*', '**', '/', '-']) @guidance(stateless=True) def expression(lm): # 可以是 # 1. 一个数字(终结符) # 2. 两个表达式加上一个运算符和可选的空格 # 3. 一个带括号的表达式 return lm + select([ number(), expression() + zero_or_more(' ') + operator() + zero_or_more(' ') + expression(), '(' + expression() + ')' ])

@guidance(stateless=True)装饰器使得函数(如expression)作为无状态语法存在,直到我们调用lm + expression()lm += expression()时才会"执行"。例如,这里是一个_无约束_生成的例子:

# 无约束 lm = llama2 + '问题:小明有一百零六个球。然后他丢失了三十六个。\n' lm += '等效的算术表达式:' + gen(stop='\n') + '\n'

<img width="462" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/54af1909-cad4-4fb1-8987-dfdfc02f8f42"><br>

注意模型写出了正确的等式但(错误地)解答了它。如果我们想约束模型只写出有效表达式(而不尝试解答),我们可以直接将我们的语法附加到它上面:

grammar = expression() lm = llama2 + '问题:小明有一百零六个球。然后他丢失了三十六个。\n' lm += '等效的算术表达式:' + grammar + '\n'

<img width="460" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/dbda0ff8-8edd-4384-b63d-fc98792e0689"><br>

语法很容易组合。例如,假设我们想要一个语法,生成一个数学表达式或一个表达式后跟一个解答再跟另一个表达式。创建这个语法很简单:

from guidance import regex grammar = select([expression(), expression() + regex(' = \d+; ') + expression()])

我们可以根据它生成:

llama2 + '这是一个二加二的数学表达式:' + grammar

<img width="346" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/283e6973-0b8d-4153-a82b-9f5db1460da9"><br>

llama2 + '2 + 2 = 4; 3+3\n' + grammar

<img width="109" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/d584a93c-bf24-43d5-8f8d-501e7eb88422"><br>

即使你不喜欢以递归语法的方式思考,这种形式也可以轻松地限制生成。例如,假设我们有以下的一次性提示:

@guidance(stateless=True) def ner_instruction(lm, input): lm += f'''\ 请用PER、ORG、LOC或无标记来标记输入中的每个单词 --- 输入: John worked at Apple. 输出: John: PER worked: at: Apple: ORG .: --- 输入: {input} 输出: ''' return lm input = 'Julia never went to Morocco in her life!!' llama2 + ner_instruction(input) + gen(stop='---')

<img width="465" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/8ecf5ad4-68b8-4e7a-b107-b1a5613e4c68"><br>

注意模型没有正确拼写"Morocco"这个词。有时模型也可能产生不存在的标记。我们可以通过添加更多的少样本例子来改进,但我们也可以限制生成过程来得到我们想要的确切格式:

import re @guidance(stateless=True) def constrained_ner(lm, input): # 分词 words = [x for x in re.split('([^a-zA-Z0-9])', input) if x and not re.match('\s', x)] ret = '' for x in words: ret += x + ': ' + select(['PER', 'ORG', 'LOC', '']) + '\n' return lm + ret llama2 + ner_instruction(input) + constrained_ner(input)
<img width="462" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/72545093-ef16-479a-b666-bd97c54a5dc7">

虽然constrained_ner(input)一个限制模型生成的语法,但它感觉就像你在用+=selects编写普通的命令式Python代码。

捕获生成内容

通过使用capture函数,无状态函数生成的字符串可以被保存到lm对象中。capture接受两个参数:无状态函数和用于存储捕获变量的名称。

from guidance import capture, one_or_more ans = lm + "要闭合开放的括号序列[[ 对应的闭合括号是 " + capture(one_or_more("]"), "brackets") ans["brackets"]
<img alt="]]]" src="https://yellow-cdn.veclightyear.com/835a84d5/36a0cd09-a2c0-47f5-a91a-679947f93bde.png" width="500">

有状态控制 + 生成

不可变对象中的状态

每当你执行lm + grammarlm + genlm + select等操作时,你都会返回一个带有额外状态的新lm对象。例如:

lm = llama2 + '这是一个提示' + gen(name='test', max_tokens=10) lm += select(['这个', '那个'], name='test2') lm['test'], lm['test2']

<img width="296" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/f0f9d180-6209-40df-9401-40da35d46e1a"><br>

有状态的{guidance}函数

guidance装饰器默认为@guidance(stateless=False),这意味着带有此装饰器的函数依赖于lm状态来执行(可以是先前的状态或函数内生成的状态)。例如:

@guidance(stateless=False) def test(lm): lm += '我应该说"Scott"吗?\n' + select(['是', '否'], name='answer') + '\n' if lm['answer'] == '是': lm += 'Scott' else: lm += '不是Scott' return lm llama2 + test()

<img width="159" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/5a55496b-aea0-46e9-8de6-b63655027653"><br>

示例:ReAct

有状态控制的一大优势是你不需要编写任何中间解析器,即使后续操作依赖于模型生成的内容,添加后续"提示"也很容易。 例如,假设我们要实现这里中ReAct提示的第一个例子,并且假设有效的行为只有"搜索"或"完成"。我们可以这样写:

@guidance def react_prompt_example(lm, question, max_rounds=10): lm += f'问题: {question}\n' i = 1 while True: lm += f'思考 {i}: ' + gen(suffix='\n') lm += f'行动 {i}: ' + select(['搜索', '完成'], name='act') lm += '[' + gen(name='arg', suffix=']') + '\n' if lm['act'] == '完成' or i == max_rounds: break else: lm += f'观察 {i}: ' + search(lm['arg']) + '\n' i += 1 return lm

注意我们不需要为行动和参数编写解析器并希望模型生成有效内容:我们强制执行它。还要注意,只有当模型选择以"完成"行动时(或者当我们达到最大轮数时),循环才会停止。

示例:更改聊天会话的中间步骤

我们还可以隐藏或更改模型生成的部分内容。例如,下面我们让一个聊天模型(注意我们使用特殊的role块)命名一些专家来回答问题,但如果提到了"Ferriss",我们总是从列表中删除他:

from guidance import user, system, assistant lm = llama2 query = '我如何提高生产力?' with system(): lm += '你是一个有帮助且简洁的助手。' with user(): lm += f'我想要回答以下问题:\n{query}\n' lm += '列出3位能很好回答这个问题的世界级专家(过去或现在)。' with assistant(): temp_lm = lm for i in range(1, 4): # 这个正则表达式只允许看起来像名字的字符串(每个单词都大写) # list_append将结果添加到列表中 temp_lm += f'{i}. ' + gen(regex='([A-Z][a-z]*\s*)+', suffix='\n', name='experts', list_append=True) experts = [x for x in temp_lm['experts'] if 'Ferriss' not in x] # 注意,即使模型在上面生成了'Ferriss', # 它也不会被添加到`lm`中,只会添加到`temp_lm`中 lm += '、'.join(experts) with user(): lm += '请像这些专家合作撰写匿名回答一样回答这个问题。' with assistant(): lm += gen(max_tokens=100)

<img width="688" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/d274f8b8-52e7-41a5-9635-b34f70ed50e0"><br>

控制和生成的自动交错:工具使用

工具使用是有状态控制的常见情况。为了使其易于实现,gen调用将tools作为可选参数,其中每个工具由以下两部分定义:(1)触发其调用并捕获参数(如果有)的语法,以及(2)实际的工具调用。然后,随着生成的展开,每当模型生成的内容与工具调用的语法匹配时,它会(1)停止生成,(2)调用工具(工具可以向LM会话添加任何内容),然后(3)继续生成。

例如,这里我们如何利用上面的expression语法来实现一个计算器工具:

from guidance import capture, Tool @guidance(stateless=True) def calculator_call(lm): # capture只是"命名"表达式,以保存在LM状态中 return lm + '计算器(' + capture(expression(), 'tool_args') + ')' @guidance def calculator(lm): expression = lm['tool_args'] # 出于安全考虑,你通常不想直接运行eval # 这里我们保证只有数学表达式 lm += f' = {eval(expression)}' return lm calculator_tool = Tool(calculator_call(), calculator) lm = llama2 + '这里有五个表达式:\n计算器(3 *3) = 33\n计算器(2 + 1 * 3) = 5\n' lm += gen(max_tokens=30, tools=[calculator_tool], stop='\n\n')

<img width="201" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/2d9b840a-4fad-4dab-b3e7-20887539b447"><br>

Gsm8k示例

注意计算器在生成过程中是无缝调用的。这里是一个更现实的例子,展示模型解决gsm8k问题:

@guidance def math_with_calc(lm, question): # 两个示例 lm += '''\ 问题:John开始有2个球。然后他将球的数量增加到原来的5倍。之后他失去了一半。然后他给了他弟弟3个。他还剩下多少个? 推理过程: 1. 他将球的数量增加到5倍。所以他有calculator(2 * 5) = 10个球。 2. 他失去了一半。所以他有calculator(10 / 2) = 5个球。 3. 他给了他弟弟3个。所以他有calculator(5 - 3) = 2个球。 答案:2 问题:Jill每天得到7美元的零用钱。她每天用1美元买公交车票,然后把一半的钱捐出去。她每天还剩多少钱? 推理过程: 1. 她每天得到7美元。 2. 她花1美元买公交车票。所以她有calculator(7 - 1) = 6美元。 3. 她捐出一半。所以剩下calculator(6 / 2) = 3美元。 答案:3 ''' lm += f'问题:{question}\n' lm += '推理过程:\n' + gen(max_tokens=200, tools=[calculator_tool], stop='答案') # 只允许数字或逗号 lm += '答案:' + gen(regex='[-\d,]+') return lm question = '''Janet的鸭子每天下16个蛋。她每天早上吃三个当早餐,每天用四个给朋友烤松饼。她每天在农贸市场以每个新鲜鸭蛋2美元的价格出售剩下的蛋。她每天在农贸市场能赚多少美元?''' llama2 + math_with_calc(question)

@guidance函数的自动调用语法

你也可以用任何带有@guidance装饰器的函数初始化一个Tool,默认的调用语法就像Python调用一样。这里有一个在同一个gen调用中使用多个这样的工具的例子:

@guidance def say_scott(lm, n): lm += '\n' for _ in range(int(n)): lm += 'Scott\n' return lm @guidance def say_marco(lm, n): lm += '\n' for _ in range(int(n)): lm += 'marco\n' return lm tools = [Tool(callable=say_scott), Tool(callable=say_marco)] llama2 + '''\ 我将多次调用say_scott和say_marco: say_scott(1) Scott ''' + gen(max_tokens=20, tools=tools)

文本,而非词元

大多数语言模型使用的标准贪婪分词方法会引入各种微妙而强大的偏见,这可能会对你的提示产生各种意想不到的后果。 例如,看下面这个给gpt-2(标准贪婪分词)的提示:

hf_gen(prompt, max_tokens=10)

from transformers import pipeline pipe = pipeline("text-generation", model="gpt2") def hf_gen(prompt, max_tokens=100): return pipe(prompt, do_sample=False, max_length=max_tokens, return_full_text=False)[0]['generated_text'] prompt = 'http:' hf_gen(prompt, max_tokens=10)

注意LLM生成的输出并没有用明显的下一个字符(两个正斜杠)来完成URL。相反,它在中间加了一个空格,创建了一个无效的URL字符串。为什么?因为字符串://是一个独立的词元,所以一旦模型看到单独的冒号,它就假设下一个字符不可能是//;否则,分词器就不会使用:,而是会使用://。这就是为什么有警告说不要在提示词的末尾加空格,但问题远比这更普遍:任何可能跨越多个词元的边界都会造成问题,例如,注意部分词如何导致错误的补全:

prompt = 'John is a' hf_gen(prompt, max_tokens=5)
prompt = 'John is a fo' hf_gen(prompt, max_tokens=5)

虽然对普通提示来说已经够problematic了,但对于我们在这个readme中写的那种提示,这些问题将是灾难性的,因为在这种提示中,提示和生成是多次交错进行的(因此有多个出问题的机会)。这就是为什么{guidance}实现了词元修复,这个功能可以自动处理提示边界,让用户只需考虑文本而不是词元。例如:

from guidance import models gpt = models.Transformers('gpt2') prompt = 'http:' gpt + prompt + gen(max_tokens=10)
prompt = 'John is a fo' gpt + prompt + gen(max_tokens=2)

快速

集成的有状态控制更快

我们在与transformersllamacpp的集成中完全控制解码循环,允许我们添加控制和额外提示而不需要任何额外成本。 相反,如果我们调用服务器,我们需要付出额外的成本来进行额外的请求,如果服务器有缓存,这可能还好,但如果服务器没有细粒度的缓存,这很快就变得不切实际。例如,再次注意上面gsm8k示例和计算器的输出:

每次我们调用calculator,我们都必须停止生成,将结果附加到提示中,然后恢复生成。为了避免第一次调用后速度变慢,服务器需要保持KV缓存到'3 for breakfast. So she has calculator(16 - 3)',然后从那一点开始继续生成。即使有缓存的服务器通常也没有办法保证在每次停止和开始时都保留状态,因此用户在每次中断时都会付出显著的开销。将所有内容都视为新提示的正常方法会导致每次调用calculator时都会大大减慢速度。

Guidance加速

除了上述好处外,由于我们可以批处理执行展开时用户添加的任何额外文本(而不是生成它),{guidance}调用通常比传统方式运行等效提示更快。看下面的例子,我们使用llama.cpp执行的GGUF压缩llama2 7B生成一个json:

@guidance def character_maker(lm, id, description, valid_weapons): lm += f"""\ 以下是RPG游戏中的角色简介,采用JSON格式。 ```json {{ "id": "{id}", "description": "{description}", "name": "{gen('name', stop='"')}", "age": {gen('age', regex='[0-9]+', stop=',')}, "armor": "{select(options=['皮甲', '锁子甲', '板甲'], name='armor')}", "weapon": "{select(options=valid_weapons, name='weapon')}", "class": "{gen('class', stop='"')}", "mantra": "{gen('mantra', stop='"')}", "strength": {gen('strength', regex='[0-9]+', stop=',')}, "items": ["{gen('item', list_append=True, stop='"')}", "{gen('item', list_append=True, stop='"')}", "{gen('item', list_append=True, stop='"')}"] }}```""" return lm a = time.time() lm = llama2 + character_maker(1, '一个敏捷的战士', ['斧头', '剑', '弓']) time.time() - a

所有非绿色部分实际上并非由模型生成,因此被批处理(速度更快)。这个提示在A100 GPU上大约需要1.2秒。现在,如果我们让模型生成所有内容(如下面大致等效的提示所示),大约需要2.6秒(不仅速度更慢,我们对生成的控制也更少)。

@guidance def character_maker2(lm, id, description): lm += f"""\ 以下是RPG游戏中JSON格式的角色简介。包含'id'、'description'、'name'、'age'、'armor'、'weapon'、'class'、'mantra'、'strength'和'items(仅3件物品的名称)'字段 请将description设置为'{description}' ```json""" + gen(stop='```') return lm a = time.time() lm = llama2 + character_maker2(1, '一个敏捷的战士') time.time() - a

<img width="586" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/9c55500d-4c90-4f42-9343-43aa2a25efa4"><br>

加载模型

llama.cpp

安装Python绑定:

CMAKE_ARGS="-DGGML_CUDA=on" pip install llama-cpp-python

加载模型:

from guidance import models lm = models.LlamaCpp(path_to_model, n_gpu_layers=-1)

Transformers

安装transformers:

from guidance import models lm = models.Transformers(model_name_or_path)

Vertex AI

没有明确guidance集成的远程端点以"乐观"方式运行。这意味着所有可强制的文本都作为提示(或聊天上下文)提供给模型,然后模型以流式模式运行,没有硬性约束(因为远程API不支持)。如果模型违反约束,则停止模型流,并可选择在该点重试。这意味着所有API支持的控制按预期工作,而API不支持的更复杂控制/解析在模型与程序保持一致时也能工作。

palm2 = models.VertexAI("text-bison@001") with instruction(): lm = palm2 + "请说一个关于西雅图的有趣事实?" lm + gen("fact", max_tokens=100)

<img width="635" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/693ae08f-68f7-4368-bd25-19afc9bfc0a5"><br>

OpenAI

OpenAI端点没有直接支持guidance语法,但通过乐观运行,我们仍然可以以匹配模型类型的方式控制它们:

传统补全模型:

curie = models.OpenAI("text-curie-001") curie + "最小的猫是" + gen(stop="。")

<img width="263" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/116a906c-ea77-4a13-a83a-682029d5e5c8"><br>

指令微调模型:

gpt_instruct = models.OpenAI("gpt-3.5-turbo-instruct") with instruction(): lm = gpt_instruct + "最小的猫是哪些?" lm += gen(stop="。")

<img width="574" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/56a53ce1-89f5-4e9d-bdb8-86fb3eebf309"><br>

聊天模型:

gpt = models.OpenAI("gpt-3.5-turbo") with system(): lm = gpt + "你是一位猫咪专家。" with user(): lm += "最小的猫是哪些?" with assistant(): lm += gen("answer", stop="。")

<img width="367" alt="image" src="https://github.com/guidance-ai/guidance/assets/3740613/46102f0f-37dc-4bb1-99b7-e5895bdee772"><br>

编辑推荐精选

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

AI办公办公工具AI工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图热门
讯飞星火

讯飞星火

深度推理能力全新升级,全面对标OpenAI o1

科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。

热门AI开发模型训练AI工具讯飞星火大模型智能问答内容创作多语种支持智慧生活
Spark-TTS

Spark-TTS

一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型

Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。

Trae

Trae

字节跳动发布的AI编程神器IDE

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
咔片PPT

咔片PPT

AI助力,做PPT更简单!

咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

热门AI辅助写作AI工具讯飞绘文内容运营AI创作个性化文章多平台分发AI助手
材料星

材料星

专业的AI公文写作平台,公文写作神器

AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。

openai-agents-python

openai-agents-python

OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。

openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。

Hunyuan3D-2

Hunyuan3D-2

高分辨率纹理 3D 资产生成

Hunyuan3D-2 是腾讯开发的用于 3D 资产生成的强大工具,支持从文本描述、单张图片或多视角图片生成 3D 模型,具备快速形状生成能力,可生成带纹理的高质量 3D 模型,适用于多个领域,为 3D 创作提供了高效解决方案。

3FS

3FS

一个具备存储、管理和客户端操作等多种功能的分布式文件系统相关项目。

3FS 是一个功能强大的分布式文件系统项目,涵盖了存储引擎、元数据管理、客户端工具等多个模块。它支持多种文件操作,如创建文件和目录、设置布局等,同时具备高效的事件循环、节点选择和协程池管理等特性。适用于需要大规模数据存储和管理的场景,能够提高系统的性能和可靠性,是分布式存储领域的优质解决方案。

下拉加载更多