大家好。
最近微软宣布推出全新的生成式 AI 脚本:GenAIScript
!
GenAIScript
是一种结合了生成式人工智能(Generative AI,简称 GenAI)和脚本编写能力的新型脚本语言:
集成 LLMs: GenAIScript
无缝集成了大型语言模型,使得脚本能够直接调用强大的生成式 AI 能力,简化复杂的自然语言处理任务。简化 JavaScript 语法:结合标准的 JavaScript 语法,使开发者无需学习新的编程语言,降低了上手难度。 高效的自动化能力:通过脚本自动化各种任务,如数据处理、内容生成和执行 API 请求等,能够高效完成。
$`Analyze ${env.files} and report errors. Use gitmojis.`
通过简化的 JavaScript 语法,它将大型语言模型(LLMs)引入到脚本编写过程中,使开发者能够更加灵活快捷地创建自动化任务和智能应用。
// define the context
def("FILE", env.files, { endsWith: ".pdf" })
// structure the data
const schema = defSchema("DATA", { type: "array", items: { type: "string" } })
// assign the task
$`Analyze FILE and extract data to JSON.`
// save results to file
defFileOutput("*.pdf.txt", "Extracted data", { schema })
// tools
defTool("weather", "live weather", { city: "Paris" }, /* schema */
async ({ city }) => { ... "sunny" }) /* callback */
// agents!
defAgent("git", "answer git questions", "You are a git expert.", { tools: ["git"] })
...
支持 JavaScript 和 TypeScript
GenAIScript
支持使用 JavaScript
和 TypeScript
来构建 prompts
,使得开发过程更加灵活和方便。脚本文件以 .genai.mjs
或 .genai.mts
扩展名命名,分别表示 JavaScript 或 TypeScript 文件,并设计用于通过 LLM 构建提示。
** .genai.mjs
**:模块化 JavaScript 语法,支持导入其他模块。** .genai.js
**:非模块化 JavaScript 文件,通过eval
执行,不支持模块导入。** .genai.mts
**:模块化 TypeScript 文件,支持导入其他 TypeScript 模块,包括动态导入。** system.*.genai.mjs
**:系统提示模板,默认情况下未列出。
GenAIScript
将自动检测工作区中任何匹配 *.genai.mjs
、*.genai.js
或 *.genai.mts
的文件。虽然脚本文件可以放置在工作区的任何位置,但扩展会默认将它们放置在 genaisrc
文件夹中。
以下是一个名为 shorten.genai.mjs
的示例文件,演示了如何创建一个缩短文本的提示脚本:
script({
title: "Shorten", // 在UI和 Copilot聊天中显示
description: "A prompt that shrinks the size of text without losing meaning", // 也显示但灰色显示
})
const file = def("FILE", env.files) // 定义文件变量
// 将文本附加到提示中
$`Shorten ${file}. Limit changes to minimum.`
安装与配置
GenAIScript
需要 Node.js
才能运行。我们推荐安装 Node.js 的长期支持版 (LTS
)。
VSCode 扩展
然后安装 Visual Studio Code
扩展
在 Visual Studio Code Marketplace 中搜索 GenAIScript
,安装最新的稳定版本扩展。安装 Visual Studio Code。这是一个轻量且强大的源代码编辑器,支持 Windows、macOS 和 Linux。 在 Visual Studio Code 中打开你的项目文件夹。 点击左侧活动栏中的扩展视图图标 搜索 GenAIScript
并点击安装
。安装成功后,你将看到扩展视图中的图标(可选)点击扩展页面上的 ⚙️ 齿轮图标,并选择 添加到工作区推荐
。
如果你需要安装特定版本的扩展,建议将 genaiscript.vsix
存储在你的仓库中并使用手动安装。步骤如下:
打开 GitHub 最新发布页面,下载 genaiscript.vsix
到你的项目根目录。在 Visual Studio Code 中打开你的项目。 右键点击 .vsix
文件,选择Install Extension VSIX…
进行安装。
命令行工具
GenAIScript
命令行工具允许你从任何终端运行脚本。
使用 npx
运行脚本
npx genaiscript run my-script some/path/*.pdf
npx
将自动安装并缓存CLI。你也可以将它作为 devDependency
添加到你的项目中:
安装 genaiscript
为开发依赖
npm install -D genaiscript
GenAIScript
会在默认的终端中启动一个 node 服务器。如果默认终端未配置或不支持 Node.js
,你可能需要在用户/工作区设置中更新它。
打开命令面板 Ctrl+Shift+P
,搜索Terminal: Select Default Profile
。选择一个终端配置文件,比如 Git Bash
。
这样配置好之后,你便可以方便地在 Visual Studio Code
或命令行中进行 GenAIScript
的开发工作了。
运行模型
通过 GitHub Models
或 GitHub Copilot
运行模型:
script({ ..., model: "github:gpt-4o" })
支持 Ollama
、LocalAI
等开源模型在本地运行:
script({ ..., model: "ollama:phi3" })
数据架构
在 GenAIScript
中,我们可以强制 LLM 生成符合特定架构的数据。这种方法效果相当不错,并且 GenAIScript
还会提供自动验证功能。GenAIScript
支持的架构比完整的 JSON 架构规范要简单,建议使用简单的架构以避免混淆 LLM,然后再将其导入到你的应用特定的数据格式中。
你可以使用 defSchema
来定义提示输出的 JSON/YAML 架构。例如,下面定义了一个城市列表的架构:
const schema = defSchema("CITY_SCHEMA", {
type: "array",
description: "A list of cities with population and elevation information.",
items: {
type: "object",
description: "A city with population and elevation information.",
properties: {
name: { type: "string", description: "The name of the city." },
population: { type: "number", description: "The population of the city." },
url: { type: "string", description: "The URL of the city's Wikipedia page." }
},
required: ["name", "population", "url"]
}
})
$`Generate data using JSON compliant with ${schema}.`
根据 TypeChat 的 “All You Need Is Types” 方法,架构会在插入 LLM 提示前转换成 TypeScript 类型。例如,上面的 CITY_SCHEMA
类型如下:
// A list of cities with population and elevation information.
type CITY_SCHEMA = Array<{
// The name of the city.
name: string,
// The population of the city.
population: number,
// The URL of the city's Wikipedia page.
url: string,
}>
一旦定义了架构,你可以告诉 LLM 根据这个架构生成数据。你可以通过以下方式生成符合 CITY_SCHEMA
的 JSON 数据:
const schema = defSchema("CITY_SCHEMA", {
type: "array",
description: "A list of cities with population and elevation information.",
items: {
type: "object",
description: "A city with population and elevation information.",
properties: {
name: { type: "string", description: "The name of the city." },
population: { type: "number", description: "The population of the city." },
url: { type: "string", description: "The URL of the city's Wikipedia page." }
},
required: ["name", "population", "url"]
}
})
$`Generate data using JSON compliant with ${schema}.`
生成的数据示例:
[
{
"name": "New York",
"population": 8398748,
"url": "https://en.wikipedia.org/wiki/New_York_City"
},
{
"name": "Los Angeles",
"population": 3990456,
"url": "https://en.wikipedia.org/wiki/Los_Angeles"
},
{
"name": "Chicago",
"population": 2705994,
"url": "https://en.wikipedia.org/wiki/Chicago"
}
]
当生成的 JSON/YAML 内容带有架构标识符时,GenAIScript
会自动验证其是否符合定义的架构。你可以在脚本运行时使用 parsers.validateJSON
来验证 JSON 数据:
const validation = parsers.validateJSON(schema, json)
特性和功能
文本文件处理
GenAIScript
支持从 PDF
、DOCX
等文件中提取文本内容,比如处理和解析 PDF
文件:
def("PDF", env.files, { endsWith: ".pdf" })
const { pages } = await parsers.PDF(env.files[0])
def 函数将自动解析 PDF 文件并从中提取文本,parsers.PDF 函数会读取 PDF 文件并尝试将其干净地转换为适合 LLM 的文本格式。
表格数据处理
可以从 CSV
、XLSX
等表格文件中提取数据并进行处理。
def("DATA", env.files, { endsWith: ".csv", sliceHead: 100 })
const rows = await parsers.CSV(env.files[0])
defData("ROWS", rows, { sliceHead: 100 })
文件操作
GenAIScript
提供了对工作区文件系统以及在用户界面中选定文件的访问权限。
env.files
变量包含了通过用户界面或命令行选中的文件数组,你可以直接在 def
函数中传递并添加额外过滤条件。
def("PDFS", env.files, { endsWith: ".pdf" })
使用 defFileOutput
指定允许输出的文件路径及其用途描述。
defFileOutput("src/*.md", "Product documentation in markdown format")
使用 glob
模式在工作区中查找文件:
const mds = await workspace.findFiles("**/*.md")
def("DOCS", mds)
使用 grep
方法在工作区中搜索含有特定模式的文件内容:
const { files } = await workspace.grep("example", "**/*.md")
def("FILE", files)
读取 JSON 文件内容:
const data = await workspace.readJSON("data.json")
将文本内容写入文件:
await workspace.writeText("output.txt", "Hello, world!")
LLM 工具
你可以注册 JavaScript 函数作为工具来使用。
defTool(
"weather",
"query a weather web api",
{ location: "string" },
async (args) =>
await fetch(`https://weather.api.api/?location=${args.location}`)
)
注册 JavaScript 函数作为工具并结合 prompt
成为代理。
defAgent(
"git",
"Query a repository using Git to accomplish tasks.",
`Your are a helpful LLM agent that can use the git tools to query the current repository.
Answer the question in QUERY.
- The current repository is the same as github repository.`,
{ model, system: ["system.github_info"], tools: ["git"] }
)
then use it as a tool
script({ tools: "agent" })
$`Do a statistical analysis of the last commits`
内置 RAG
支持矢量搜索功能。
const { files } = await retrieval.vectorSearch("cats", "**/*.md")
运行代码
LLM 可以在沙箱环境下运行代码。
script({ tools: ["python_code_interpreter"] })
也可以在 Docker 容器中运行代码。
const c = await host.container({ image: "python:alpine" })
const res = await c.exec("python --version")
还可以运行 Prompty
文件。
---
name: poem
---
Write me a poem
应用示例
示例1:生成 Git 提交信息
gcm
脚本提供了生成提交信息的引导流程。它会根据 Git 仓库中的暂存变更生成一个提交信息,并引导用户提交这些变更或重新生成提交信息。
首先,我们定义 script
函数,设置脚本的标题和描述,并指定要使用的模型:
script({
title: "git commit message",
description: "Generate a commit message for all staged changes",
model: "openai:gpt-4o",
})
接下来,使用 git diff
检查你 Git 仓库中的暂存变更。如果没有暂存任何变更,GenAI
会通知你将所有变更暂存:
// 检查暂存的变更,如果没有则暂存所有变更
const diff = await git.diff({
staged: true,
askStageOnEmpty: true,
})
if (!diff) cancel("no staged changes")
console.log(diff.stdout) // 输出变更内容供你查看
此部分是关键。我们进入一个循环,根据 diff 生成提交信息。如果你对生成的信息不满意,可以选择编辑、接受或重新生成:
let choice
let message
do {
// 生成一个符合规范的 Git 提交信息
const res = await runPrompt((_) => {
_.def("GIT_DIFF", diff, { maxTokens: 20000, language: "diff" })
_.$`Generate a git conventional commit message for the changes in GIT_DIFF.
- do NOT add quotes
- maximum 50 characters
- use emojis`
})
message = res.text
} while (choice !== "commit")
如果你选择提交,GenAI
会用你的信息运行 git commit
命令,如果你愿意,还可以立即将变更推送到仓库:
if (choice === "commit" && message) {
console.log(
(await host.exec("git", ["commit", "-m", message, "-n"])).stdout
)
if (await host.confirm("Push changes?", { default: true }))
console.log((await host.exec("git push")).stdout)
}
使用以下命令在终端运行脚本:
npx genaiscript run gcm
这就是完整的 gcm
脚本实现,通过运行上述命令,可以自动化生成 Git 提交信息并进行提交。
示例2:图片替代文本生成器
图片的替代文本(alt text)对于使图片对包括视障人士在内的所有人可接触是至关重要的。它为图片提供了一种文字描述,使屏幕阅读器能够将内容传达给看不到图片的用户。然而,为图片编写替代文本可能非常耗时,尤其是当你要处理大量图片时。这时,AI 可以大显身手。使用类似于 OpenAI 的 GPT-4 的语言模型,你可以自动生成图片替代文本,从而节省时间和精力。
这个示例展示了如何构建一个工具来为 Markdown 文件中的图片生成替代文本。脚本主要由 Typescript 代码组成,并在 GenAIScript CLI 中运行。让我们来逐步解析这些代码。
首先,我们定义 script
函数,设置脚本的标题和描述,并指定要使用的模型:
script({
title: "Image Alt Textify",
description: "Generate alt text for images in markdown files",
parameters: {
docs: {
type: "string",
description: "path to search for markdown files",
default: "**.{md,mdx}",
},
force: {
type: "boolean",
description: "regenerate all descriptions",
default: false,
},
assets: {
type: "string",
description: "image assets path",
default: "./assets/images", // 修改为你的资产文件夹路径
},
},
})
在这里,我们声明了脚本,并使用 OpenAI 的 GPT-4 模型。我们还设置了文件路径、是否重新生成所有描述,以及资产路径等参数。
接下来,提取环境变量:
const { docs, force, assets } = env.vars
然后,我们定义一个正则表达式来查找 Markdown 中的图片:
const rx = force
? /!\[[^\]]*\]\(([^)]+.(png|jpg))\)/g // 匹配包含或不包含替代文本的图片
: /!\[\s*\]\(([^)]+.(png|jpg))\)/g // 匹配没有替代文本的图片
const { files } = await workspace.grep(rx, {
path: docs,
glob: "*.mdx",
readText: true,
})
我们使用 workspace.grep
来查找指定文档中符合正则表达式模式的所有内容。
对于找到的每个图片 URL,我们使用一个内联提示来生成替代文本:
for (const file of files) {
const { filename, content } = file
const matches = content.matchAll(rx)
for (const match of matches) {
const url = match[1]
const resolvedUrl = resolveUrl(filename, url)
const { text } = await runPrompt(
(_) => {
_.defImages(resolvedUrl)
_.$`
You are an expert in assistive technology.
You will analyze the image
and generate a description alt text for the image.
- Do not include alt text in the description.
- Keep it short but descriptive.
- Do not generate the [ character.`
},
{
system: ["system.safety_harmful_content"],
model: "openai:gpt-4o",
}
)
imgs[url] = text
}
}
最后,我们将替代文本更新到 Markdown 内容中:
const newContent = content.replace(
rx,
(m, url) => `![${imgs[url] ?? ""}](${url})`
)
if (newContent !== content) await workspace.writeText(filename, newContent)
我们使用生成的替代文本替换原始内容中的占位符,并保存更新后的文件。
你需要通过 GenAIScript CLI 来运行这个脚本。如果你还没有安装 GenAIScript CLI,请查看安装指南。安装后,可以通过以下命令运行脚本:
npx genaiscript run iat
脚本默认导入了一个安全系统消息,以防止生成有害文本内容:
// safety system message to prevent generating harmful text
system: ["system.safety_harmful_content"],
通过这个脚本,你可以自动化生成 Markdown 文件中图片的替代文本,大大提高工作效率并确保内容的可访问性。
最后
官方还提供了完整的使用指南、大量的案例:
了解更多内容可以访问:
官网:https://microsoft.github.io/genaiscript/ Github:https://github.com/microsoft/genaiscript/