Askit是一个用于打字稿的语言插件,使您能够直接在您的编程环境中利用大型语言模型(例如GPT-4)的功能(例如GPT-4)的功能,不需要复杂的API。 Askit的广泛申请包括:
Askit建立在OpenAI API上,提供了一个用户友好的界面,用于将LLMS纳入您的应用程序。您不仅可以在打字稿中,而且可以在JavaScript和Python中使用Askit 。
有关将askit与JavaScript集成,请参阅相应的JavaScript部分。
如果Python是您的首选语言,您可以通过访问我们的专用askit(Pyaskit)页面了解有关如何利用Askit的更多信息。
类型引导的输出控制:在指定类型中获取响应。
基于模板的功能定义:使用提示模板定义函数。
代码生成:从统一接口生成功能。有关更多详细信息,请参见带有Askit的代码生成。
按示例编程(PBE):使用示例定义函数。请参阅以示例的方式参见编程,以获取更多详细信息。
在开始之前,请确保系统上安装了Node.js和NPM。然后,执行以下命令:
npm install ts-askit此软件包依赖于ts-patch 。要安装ts-patch ,请运行:
npx ts-patch install将以下片段添加到您的tsconfig.json :
"compilerOptions" : {
"plugins" : [{ "transform" : " ts-askit/transform " }]
}此修改允许打字稿编译器支持ask的类型参数,并在Askit中define API。
ts-patch软件包对于释放Askit的全部潜力至关重要,因为它扩展了打字稿编译器以完全集成了Askit类型系统。尽管可以在没有ts-patch情况下使用Askit,但此集成提供了更丰富的体验。
在使用askit之前,您需要将OpenAI API密钥设置为环境变量OPENAI_API_KEY :
export OPENAI_API_KEY= < your OpenAI API key > <your OpenAI API key>是一个看起来像这样的字符串: sk-<your key> 。您可以在OpenAI仪表板中找到API键。
您还可以将模型名称指定为环境变量ASKIT_MODEL :
export ASKIT_MODEL= < model name > <model name>是您要使用的模型的名称。最新的Askit经过gpt-4和gpt-3.5-turbo-16k测试。您可以在OpenAI API文档中找到可用型号的列表。
以下是一些介绍性示例:
import { ask } from 'ts-askit' ;
ask < string > ( 'Paraphrase "Hello World!"' ) . then ( ( result ) => {
console . log ( result ) ;
} ) ;在此示例中, ask是一个API函数,允许您的程序对大型语言模型(LLM)提出查询。类型参数表示LLM的预期输出类型。在这里,输出类型是string 。提示以自然语言为论点传递,描述了LLM执行的任务。 ask是异步的,返回指定输出类型的Promise 。上面的代码段应该打印出这样的内容:
Greetings, Universe!
对于带有参数的提示,您可以使用以下方式使用define API:
import { define } from 'ts-askit' ;
const paraphrase = define < string > ( 'Paraphrase {{text}}' ) ;
paraphrase ( { text : 'Hello World!' } ) . then ( ( result ) => {
console . log ( result ) ;
} ) ; define是一个API函数,允许您定义自定义功能。其类型参数指示LLM的输出类型,因此表示函数的返回值。该函数接收一个字符串模板作为参数,用作LLM的任务提示。该模板可以包括包含在双卷发括号中的参数。在上面的示例中, text是模板中的一个参数,并且可以是任何有效的JavaScript标识符。
定义功能后,可以像任何其他功能一样调用它。此函数接受对象作为参数,该参数映射到模板参数的值。在这种情况下, text映射到字符串“ Hello World!”。
Askit擅长从自然语言描述中生成代码。这是一个例子:
import { define } from 'ts-askit' ;
const sort = define < number [ ] , { numbers : number [ ] } > (
'Sort {{numbers}} in ascending order'
) ;此示例显示一个函数,该函数以升序顺序排列数字数组,并利用define API指示LLM来定义函数。尽管概念效率有效,但由于每个功能调用都需要一个新的LLM任务,因此该方法似乎在计算上很重。
要简化此过程,我们可以利用LLM生成排序函数的代码,而不是诉诸于每个分类任务的LLM。由于Askit的代码生成功能,这可以优化功能,而无需进行实施任何更改。
上述函数的代码可以通过三个步骤生成:
tsc编译代码。 Askit Analyzer扫描代码并生成一个JSONL文件,其中包含define并ask API调用的详细信息。npx askgen < jsonl file >tsc重新编译代码。这次,得益于Askit的自动更换功能, define和ask API调用分别由新生成的功能的参考和调用代替。 Askit允许您以示例(PBE)来利用编程的功能。 PBE通过使您能够通过示例而不是硬编码逻辑来定义功能来简化编程过程。下面的示例通过向您展示如何使用PBE和Askit添加两个二进制数字来说明这一点。
import { define , Example } from 'ts-askit' ;
const trainingExamples : Example [ ] = [
{ input : { x : '1' , y : '0' } , output : '1' } ,
{ input : { x : '1' , y : '1' } , output : '10' } ,
{ input : { x : '101' , y : '11' } , output : '1000' } ,
{ input : { x : '1001' , y : '110' } , output : '1111' } ,
{ input : { x : '1111' , y : '1' } , output : '10000' } ,
] ;
const testExamples = [
{ input : { x : '0' , y : '1' } , output : '1' } ,
{ input : { x : '10' , y : '0' } , output : '10' } ,
{ input : { x : '110' , y : '10' } , output : '1000' } ,
] ;
const addInBase2 = define < string , { x : string ; y : string } > (
'Add {{x}} and {{y}}' ,
trainingExamples ,
testExamples
) ;
async function doit ( ) {
console . log ( await addInBase2 ( { x : '101' , y : '11' } ) ) ;
}
doit ( ) ;在此示例中,我们定义了一个函数addInBase2 ,该函数采用两个二进制数(表示为字符串)并添加它们。 define函数通过提示和两个示例来调用:培训示例和测试示例。培训示例以一些速度学习方式在提示中反映。另一方面,测试示例用于验证生成的函数的正确性。如果您不为该功能生成代码,则不需要测试示例。
结果是一个强大的功能,允许您指示LLM使用示例执行复杂的操作,例如二进制添加。这种方法使您能够快速发展复杂的功能,并且具有较少的明确逻辑。
定义函数addInBase2后,您可以将其调用二进制数字字符串以在基本2中执行添加。与传统功能呼叫一样, Askit的ask Operation返回返回的承诺可以解决计算结果。
JavaScript开发人员可以充分利用Askit提供的类型引导输出控制的潜力。就像其兄弟姐妹打字稿一样,JavaScript合并了API方法来实现这一ask 。函数ask需要两个参数:类型和提示。
这是证明其用法的一系列示例:
const ai = require ( 'ts-askit' )
const t = require ( 'ts-askit/types' )
ai . ask ( t . number , 'What is the third prime number?' ) . then ( ( answer ) => { console . log ( answer ) } ) ;
ai . ask ( t . string , "What is the month number of 'January'?" ) . then ( ( answer ) => { console . log ( answer ) } ) ;
ai . ask ( t . array ( t . number ) , "What are the month numbers in the second quarter?" ) ;
const monthType = t . type ( {
name : t . string ,
number : t . number
} )
ai . ask ( monthType , "What is the month number of 'October'?" ) . then ( ( answer ) => { console . log ( answer ) } ) ;
ai . ask ( t . array ( monthType ) , "What are the months in the second quarter?" ) . then ( ( answer ) => { console . log ( answer ) } ) ;在上面的代码片段中,使用类型和提示调用ask功能。类型参数的目的是通知Askit有关所需输出的格式和结构。当您处理复杂的数据结构时,这变得非常方便。
使用Askit ,JavaScript开发人员可以使用易于理解的模板来定义功能。 define方法是这里的幕后英雄,因为它可以根据提供的任务模板来创建功能。创建后,这些函数可以用任何为模板中占位持有人提供值的对象调用。
这是一个如何完成的示例:
const ai = require ( 'ts-askit' )
const t = require ( 'ts-askit/types' )
let f = ai . define ( t . string , 'Translate {{text}} into {{language}}' ) ;
f ( { text : 'Hello' , language : 'French' } ) . then ( ( answer ) => { console . log ( answer ) } ) ;在上面的代码中,使用define方法来使用任务模板f转换{{text}}到{{language}}'。然后将函数f与提供text和language值的对象调用。
'ts-askit/types'模块是您可以用来指导Askit输出的类型的宝库。这是一张可以帮助您快速掌握这些类型的桌子:
| 类型 | 描述 | 类型示例 | 价值示例 |
|---|---|---|---|
NumberType | 数字类型 | t.number | 123 |
StringType | 字符串类型 | t.string | “你好世界!” |
BooleanType | 布尔类型 | t.boolean | 真的 |
LiteralType | 字面价值类型 | t.literal(123) | 123 |
ArrayType | 数组类型 | t.array(t.number) | [1,2,3] |
UnionType | 联合类型(多个可能的值) | t.union([t.literal('yes'), t.literal('no')]) | “是还是不是” |
InterfaceType | 接口/字典类型 | t.type({a: t.number, b: t.number}) | {a:1,b:2} |
CodeType | 代码类型 | t.code('python') | “ def hello_world():print('Hello,World!')” |
每种类型都有特定的属性,该属性用来理解手头的任务并正确格式化输出。
截至撰写本文时,代码生成功能在打字稿中仅可用。但是,努力正在努力将这一强大功能扩展到JavaScript领域。如果您的要求要求在此期间使用代码生成,我们建议使用TypeScript直至进一步更新。
有关我们的行为守则和提交拉的请求过程的详细信息,请参阅progruting.md。
该项目已根据MIT许可获得许可。有关更多信息,请参阅许可证文件。
@misc { okuda2023askit ,
title = { AskIt: Unified Programming Interface for Programming with Large Language Models } ,
author = { Katsumi Okuda and Saman Amarasinghe } ,
year = { 2023 } ,
eprint = { 2308.15645 } ,
archivePrefix = { arXiv } ,
primaryClass = { cs.PL }
}