GenAIScript — это новый скриптовый язык, сочетающий в себе возможности генеративного ИИ (GenAI) и скриптинга:

  1. Интегрированные LLM. GenAIScript легко интегрирует большие языковые модели, позволяя скриптам непосредственно использовать мощные возможности генеративного ИИ и упрощать сложные задачи обработки естественного языка.
  2. Упрощенный синтаксис JavaScript. GenAIScript включает стандартный синтаксис JavaScript, поэтому разработчикам не нужно изучать новый язык программирования, что облегчает начало работы.
  3. Эффективные возможности автоматизации. Различные задачи, такие как обработка данных, создание контента и выполнение API-запросов, могут быть эффективно решены с помощью скриптинга.
$`Analyze ${env.files} and report errors. Use gitmojis.`

Благодаря упрощенному синтаксису JavaScript, GenAIScript внедряет большие языковые модели (LLM) в процесс написания скриптов, позволяя разработчикам создавать автоматизированные задачи и интеллектуальные приложения более гибко и быстро.

// определение контекста
def("FILE", env.files, { endsWith: ".pdf" })
// структуризация данных
const schema = defSchema("DATA", { type: "array", items: { type: "string" } })
// назначение задачи
$`Analyze FILE and extract data to JSON.`
// сохранение результатов в файл
defFileOutput("*.pdf.txt", "Extracted data", { schema })
// инструменты
defTool("weather", "live weather", { city: "Paris" }, /* schema */
    async ({ city }) => { ... "sunny" }) /* callback */
// агенты!
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", // Отображается в пользовательском интерфейсе и чате 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 Long Term Support (LTS).

Расширения VSCode

Затем понадобится установить расширение Visual Studio Code.

  1. GenAIScript. Найдите последнюю стабильную версию расширения на Visual Studio Code Marketplace.
  1. Установите Visual Studio Code. Это легкий и мощный редактор исходного кода, который поддерживает Windows, macOS и Linux.
  2. Откройте папку с проектом в Visual Studio Code.
  3. Щелкните значок «Расширенный вид» (Expanded View) на левой панели активности.
  1. Найдите GenAIScript и нажмите на нем install. После успешной установки вы увидите значок в окне просмотра расширений.
  1. Опционально: щелкните значок шестеренки ⚙️ на странице «Расширения» (Extensions) и выберите Add to Workspace Recommendations («Добавить в рекомендации рабочего пространства»)…

Если вам необходимо установить определенную версию расширения, рекомендуется сохранить ее в репозитории genaiscript.vsix и использовать ручную установку. Это делается следующим образом:

  1. Откройте страницу последнего релиза на GitHub и загрузите genaiscript.vsix в корневой каталог проекта.
  2. Откройте проект в Visual Studio Code.
  3. Щелкните правой кнопкой мыши по файлу .vsix и выберите установку Install Extension VSIX….

Инструменты командной строки

GenAIScript — инструмент командной строки, позволяющий запускать скрипты из любого терминала.

Запуск скрипта с помощью npx :

npx genaiscript run my-script some/path/*.pdf

CLI будет автоматически установлен и кэширован. Вы также можете добавить devDependency в свой проект. Установка genaiscript для зависимостей разработки:

npm install -D genaiscript

GenAIScript запустит сервер node в терминале по умолчанию. Если терминал по умолчанию не настроен или не поддерживает Node.js, может потребоваться обновить его в настройках пользователя/рабочего пространства.

  1. Откройте палитру команд (Ctrl+Shift+P) и найдите Terminal: Select Default Profile.
  2. Выберите профиль терминала, например Git Bash.

После этой настройки вы сможете легко выполнять разработку в Visual Studio Code или командной строке GenAIScript.

Запуск модели

Запустите модель с помощью GitHub Models или GitHub Copilot.

script({ ..., model: "github:gpt-4o" })

Поддерживает локальный запуск моделей с открытым исходным кодом, таких как OllamaLocalAI:

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», схема преобразуется в типы TypeScript перед вставкой подсказок LLM. Так, приведенный выше тип CITY_SCHEMA будет иметь следующий вид:

// Список городов с информацией о населении и высоте над уровнем моря.
type CITY_SCHEMA = Array<{
    // Название города.
    name: string,
    // Население города.
    population: number,
    // URL-адрес страницы города в Википедии.
    url: string,
}>

Определив схему, вы указываете LLM генерировать данные в соответствии с ней. Вы можете генерировать соответствующие JSON-данные CITY_SCHEMA следующими способами:

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-файлов и т. д.), а также обработку и парсинг файлов :DOCXPDF.

def("PDF", env.files, { endsWith: ".pdf" })
const { pages } = await parsers.PDF(env.files[0])

Функция def автоматически проведет парсинг PDF-файл и извлечет из него текст, а функция parsers.PDF прочитает PDF-файл и попытается преобразовать его в текстовый формат, подходящий для LLM.

Обработка табличных данных

GenAIScript может извлекать и обрабатывать данные из CSVXLSX и других табличных файлов:

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 в качестве инструментов и привязывает их к агентам в качестве промптов.

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 предоставляет руководство по генерации сообщений о коммитах. Он генерирует сообщения о коммитах на основе staged-изменений в репозитории Git и предлагает пользователю закоммитить эти изменения или повторно сгенерировать сообщение о коммите.

Сначала определяем функцию script, задаем заголовок и описание скрипта, а также указываем используемую модель:

script({
    title: "git commit message",
    description: "Generate a commit message for all staged changes",
    model: "openai:gpt-4o",
})

Далее с помощью git diff проверяем наличие staged-изменения в Git-репозитории. Если staged-изменений не будет, GenAI сообщит о необходимости перевода изменений в статус staged: 

// Проверка наличия staged-изменений; если их нет, перевод изменений в статус staged
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-текст) крайне важен для того, чтобы сделать изображения доступными для всех, включая людей со слабым зрением. Он представляет собой текстовое описание изображения, позволяющее программам чтения с экрана передавать содержимое пользователям, которые не могут видеть изображение. Однако написание alt-текста может отнимать много времени, особенно если речь идет о большом количестве изображений. И тут на выручку приходит искусственный интеллект. Используя языковую модель, такую как GPT-4 от OpenAI, вы можете автоматически генерировать alt-текст изображения, экономя время и силы.

В следующем примере показано, как создать инструмент генерации альтернативного текста для изображений в файлах Markdown. Скрипт состоит в основном из кода Typescript и запускается в CLI GenAIScript. Разберем код пошагово.

Сначала определим функцию 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", //  Укажите свой путь к папке с активами
        },
    },
})

Далее объявляем скрипт и используем модель GPT-4 от OpenAI. Задаем такие параметры, как путь к файлу, потребность в повторной генерации всех описаний и путь к активам.

Далее извлекаем переменные среды:

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)

Мы заменяем плейсхолдеры в исходном содержимом сгенерированным альтернативным текстом и сохраняем обновленный файл.

Запускать этот скрипт нужно через CLI GenAIScript. Если вы еще не установили CLI GenAIScript, ознакомьтесь с руководством по установке. После установки можете запустить скрипт с помощью следующей команды:

npx genaiscript run iat

По умолчанию скрипт импортирует сообщение системы безопасности, чтобы предотвратить генерацию вредоносного текстового содержимого:

// сообщение системы безопасности для предотвращения генерации вредоносного текста
system: ["system.safety_harmful_content"],

С помощью этого скрипта вы можете автоматически генерировать альтернативный текст для изображений в файлах Markdown, значительно повышая эффективность своей работы и обеспечивая доступность контента.

Вместо заключения

На официальном сайте можно найти полное руководство по использованию GenAIScript и большое количество примеров:

Для получения дополнительной информации посетите следующие ресурсы:

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Xiuer Old: Microsoft launches a new generative AI script: GenAIScript!

Предыдущая статьяC++: подробное руководство по is_open()
Следующая статьяРендеринг больших табличных данных в браузере