PDL: декларативный язык программирования слов с подсказками

рефераты

Большие языковые модели (LLM) вызвали широкий интерес во всем мире, позволяя создавать многие ранее труднодостижимые приложения ИИ. LLM управляются с помощью выразительных текстовых запросов и возвращают текстовые ответы. Однако неструктурированный текст на входе и выходе делает приложения на базе LLM уязвимыми. Это послужило толчком к появлению систем подсказок, которые призваны регулировать взаимодействие LLM с внешним миром. Однако существующие механизмы подсказок либо требуют длительного обучения, либо лишают разработчиков контроля над точными подсказками. Для решения этой дилеммы в данной статье представлен декларативный язык подсказок (Prompting Declarative Language, PDL). PDL - это простой декларативный язык, основанный на YAML, который ставит подсказки во главу угла. PDL хорошо работает с различными платформами LLM и LLM, поддерживает написание интерактивных приложений, вызывающих LLM и инструменты, и прост в реализации, например, чат-боты, RAG или агенты, среди распространенных сценариев использования, таких как чат-боты, RAG или прокси. Мы надеемся, что PDL сделает оперативное программирование проще, надежнее и приятнее.

 

1. Введение

Большие языковые модели (БЯМ) достигли большого прогресса, продемонстрировав способность выполнять множество полезных задач. Поскольку ЛЛМ управляются с помощью подсказок естественного языка, разработка подсказок стала специальным методом повышения точности (White et al.2023). Обучение с помощью подсказок, таких как контекстное обучение (Brown et al.2020), несколько цепочек вызовов LLM (Chase et al.2022), улучшенное поколение (RAG) (Lewis et al.2020), использование инструментов (Schick et al.2023), модель процедурного вспомогательного языка (PAL) (Gao et al.2023) и агентов (Yao et al.2023) может открыть больше возможностей. Однако, несмотря на свою мощь, LLM все еще остается хрупким: иногда он галлюцинирует или даже не соблюдает ожидаемый синтаксис и типы.

Система подсказок (Liu et al.2023) позволяет разработчикам легче использовать LLM и связанные с ним шаблоны подсказок, снижая при этом их уязвимость. Некоторые фреймворки, такие как LangChain (Chase et al.2022) и AutoGen (Wu et al.2023), предоставляя специальные функции для популярных паттернов, таких как RAG или прокси. Однако такие возможности могут лишить пользователей контроля над основными подсказками и заставить их изучать множество сложных функций фреймворка. В отличие от этого, низкоуровневые фреймворки подсказок, такие как Guidance (Microsoft.2023) и LMQL (Beurer-Kellner et al.2023), которые обеспечивают больший контроль за счет синтаксиса и типов. Однако они требуют от пользователей программирования на императивных языках, таких как Python или TypeScript. Фреймворки на другом конце спектра, такие как DSPy (Khattab et al.2023) и Виейра (Li et al.2024), позволяя полностью избежать рукописных подсказок за счет автоматической генерации подсказок. К сожалению, это еще больше отнимает контроль у разработчика. Таким образом, возникает вопрос, как сделать программирование LLM более надежным и оставить разработчика за рулем, сохранив при этом простоту.

Для решения этой проблемы мы опираемся на проверенные временем идеи проектирования языков программирования. Принцип ортогональности поддерживает использование небольшого и простого набора функций, которые комбинируются для достижения мощной функциональности (van Wijngaarden et al.1977). В этом контексте ортогональность означает максимально возможное избегание особых случаев. Для фреймворков с подсказками ортогональность - это способ избежать специфических особенностей. Далее, если язык может пройти проверку типов и ролей (Hugging Face, the2023), навязанных структурно, разработчики будут меньше бороться с уязвимостью. Остается неразрешимое противоречие: с одной стороны, мы хотим, чтобы разработчики могли управлять точными подсказками, а с другой - нам нужен простой декларативный язык. По этой причине мы выбрали язык, ориентированный на данные, который намеренно стирает грань между процедурами (например, для цепочек и инструментов) и данными (для подсказок). Вдохновение пришло от старого понятия "код как данные" (McCarthy.1960), а также основополагающие работы по безслойному программированию (Cooper et al.2006).

В этой статье представлен язык объявлений Prompt Declaration Language (PDL), ортогональный и типизированный язык, ориентированный на данные. В отличие от других языков подсказок, встроенных в императивные языки, PDL основан на YAML (Ben-Kiki et al.2004).YAML - это формат сериализации данных, который является одновременно человекочитаемым (благодаря простому синтаксису для неструктурированных строк) и структурированным (совместимым с JSON).Переменные в PDL также содержат значения JSON и опционально используют JSON Schema (Pezoa et al.2016В настоящее время PDL реализуется интерпретатором, выполняющим динамическую проверку типов. Одним из преимуществ представления программ в виде данных является простота преобразования программ (Mernik et al.2005), например, для оптимизации. Рендеринг программ в формате представления данных может даже облегчить генерацию PDL-программ с помощью большой языковой модели, подобно PAL (Gao et al.2023).

Программы PDL состоят из блоков (объектов YAML), каждый из которых добавляет данные в контекст подсказки. Такой подход идеально подходит для использования с технологиями подсказок, такими как чат-боты или агенты: выполнение программы неявно строит диалог или траекторию без явной конвейеризации. Этот контекст затем становится входом для следующего вызова LLM.PDL поддерживает собственные LLM, а также LLM, размещаемые различными поставщиками, включая, но не ограничиваясь, модель Granite с открытым исходным кодом на IBM Watsonx1 и Replicate2 (Abdelaziz et al.2024; Granite Team, IBM.2024PDL предоставляет циклы и условные структуры управления, а также введение функций и файлов для модульности.PDL использует Jinja2 (Ronacher.2008) выражений для шаблонизации не только подсказок, но и целых программ.

В этой статье представлен обзор PDL на вводном примере (Раздел 2), затем следует подробное описание языка (Раздел 3). В нем описаны инструменты для запуска и редактирования программ PDL (Раздел 4), а также приводятся тематические исследования, демонстрирующие дальнейшее применение PDL (Раздел 5). Наконец, в статье обсуждаются сопутствующие работы (Раздел 6), и вРаздел 7PDL имеет открытый исходный код и может быть найдена в https://github.com/IBM/prompt-declaration-language Получить. В целом PDL - это простой, но мощный новый язык программирования LLM prompt.

 

2. Обзор

В этом разделе представлен обзор функциональности PDL на примере чатбота. Программа PDL выполняет ряд следующих действий комок (земли)Данные, генерируемые каждым блоком, попадают в фоновый контекст. Существуют различные типы блоков, которые могут генерировать данные разными способами: вызов модели, чтение данных из stdin или файлов, создание различных JSON-данных напрямую и выполнение кода. Кроме того, существует множество управляющих блоков (if-then-else, for и repeat), которые позволяют пользователям PDL выражать богатые конвейеры данных и приложения искусственного интеллекта.

искать 1На рисунке (a) показан код PDL для простого чатбота. Блок read: в строках 1-4 печатает сообщение с просьбой ввести запрос и считывает его из stdin. Рис. 1(b) Показана трассировка выполнения той же программы. Например, пользователь может спросить: "Что такое языковой салат?". . Чтобы избежать повторений, в пункте "attribute: [context]" в фоновый контекст помещается ответ пользователя, но не результат (то, что выводится в stdout).

Блок repeat:until: в строках 5-16 содержит вложенный блок text:, который, в свою очередь, содержит последовательность из двух вложенных блоков. Блоки text: преобразуют результаты своих вложенных блоков в строки и конкатенируют их. Блок model: в строках 7-9 вызывает большую языковую модель (LLM), которая использует текущий накопленный контекст в качестве подсказки. В первой итерации цикла контекст состоит всего из двух строк: "Каков ваш запрос?" и "Что такое языковой салат?". Параметр модели 'stop: [\n\n]' заставляет LLM прекратить генерацию лексем после того, как будут сгенерированы два последовательных перевода строки. интерпретатор LLM печатает вывод LLM зеленым цветом; рис. 1(b) показывает, что в этом примере LLM сгенерировал сообщение "A language salad is [...]". Блок read: в строках 10-15 выводит сообщение, используя синтаксис многострочных строк YAML (начиная с вертикальной черты (|)). Этот пример показывает, как PDL ставит подсказку на первое место, делая ее легко читаемой и предоставляя разработчику точный контроль. Трассировка интерпретатора справа показывает, что пользователь набрал "Say it as a poem!", который определяется как переменная question слева в строке 10 и добавляется к контексту в строке 12. Предложение until: в строке 16 указывает, что выражение Jinja2 '${question == "quit"}’ PDL использует синтаксис '${...}' синтаксис для вставки шаблонов Jinja2 вместо '{{...}}' вместо '{{...}}', поскольку последний несовместим со специальными символами YAML (фигурными скобками).

Во второй итерации цикла контекст содержит эффекты первой итерации цикла. Таким образом, второе выполнение блока model: видит результат первого выполнения и может перефразировать его в стихотворение "В мире, где много языков [...]", как показано здесь 1(b). В конце концов, во время выполнения второго блока read: в этом примере пользователь набирает "quit", что приводит к завершению цикла. Теперь, когда мы увидели некоторые общие блоки PDL (read:, repeat:, text: и model:) в действии, мы можем перейти ко второму блоку read:. 3 Раздел, в котором описываются остальные блоки и особенности языка.

PDL:声明式提示词编程语言

(a) Код

- read:
contribute: [context]
message: |
您的查询是什么?
- repeat:
text:
- model: watsonx/ibm/granite-13b-chat-v2
parameters:
stop: ["\n\n"]
- def: question
read:
contribute: [context]
message: |
输入查询或说“quit”退出。
until: ${question == "quit"}

(b) Отслеживание переводчика

您的查询是什么?
什么是语言沙拉?
语言沙拉是一个术语,用于描述在单一对话或文本中混合不同语言和方言。它可以被看作是[…]
输入查询或说“quit”退出。
用诗的形式表达!
在语言众多的世界中,
语言沙拉诞生,喜悦中成长。
词语交织,和谐中流动,
五彩缤纷的语言,活力绽放。
输入查询或说“quit”退出。
quit

Рисунок 1. Простой чатбот в PDL

 

3. Язык

PDL:声明式提示词编程语言

Рисунок 2. Краткая справка по PDL

PDL - это язык, встроенный в YAML, что делает каждую PDL-программу действительным YAML-документом, соответствующим архитектуре PDL. Рисунок 2 является краткой справкой по PDL и объясняется в этом разделе с помощью правил синтаксиса. Программа - это блок или список блоков, где блок может быть выражением или структурированным блоком, как показано в следующих правилах синтаксиса:

pdl ::= блок | [блок, . . . ,блок]блок ::= выражение | структурированный_блок

Все правила синтаксиса в этом разделе используют синтаксис YAML в стиле потока (например, [блок, ...,блок]). ...,block]). Тот же самый код PDL может быть преобразован в синтаксис блочного стиля YAML, например:

  • блок
    ...
  • блок

Каждый блок содержит тело блока с ключевым словом, указывающим на тип блока (например, модель или чтение). Существует 15 типов тел блоков (необязательные поля отмечены вопросительными знаками):

PDL:声明式提示词编程语言 блок_тела ::=

model:expression,input:?pdl,parameters:?  
expression  
| read:file,message:?  
string,message:?  
bool  
| text:pdl  
| lastOf:pdl  
| array:pdl  
| object:pdl  
| data:json  
| include:file  
| function:args,return:pdl  
| call:𝑓,args:args  
| if:expression,then:pdl,else:?pdl  
| for:args,repeat:𝑝𝑑𝑙,join:?  
join  
| repeat:pdl,num_iterations:n,join:?  
join  
| repeat:pdl,until:expression,join:?  
join  
| code:pdl,lang:string

Мы уже познакомились с блоками model: и read: в предыдущем разделе. блоки model: вызывают большую языковую модель. Подсказки берутся из текущего контекста, если не указано необязательное поле input:. Необязательное поле parameters: используется для настройки поведения модели при выводе. Блок read: считывает ввод из файла или из стандартного ввода, если имя файла не указано. Необязательное поле message: используется для вывода сообщения пользователю, а необязательное поле multiline: определяет, следует ли останавливаться на переводах строк.

Пять типов блоков для создания данных включают: text:, lastOf:, array:, object: и data:. Рисунок 2 Они показаны в простом примере. Список блоков без ключевого слова показан как lastOf:. Разница между блоком object: и блоком data: заключается в том, что интерпретатор PDL игнорирует ключевое слово PDL в блоке data: и рассматривает его как обычное поле JSON.

Для модульности PDL поддерживает блоки include: и функции. Блоки include: открывают программы PDL по указанному относительному пути и добавляют их вывод в место, где он появляется. Синтаксис аргументов функций следующий:

args::={x:exp ression,... ,x:expres sion}

Каждое выражение x:expressi сопоставляет имена параметров со спецификациями типов (в определении функции:) или значениями (в вызове функции:). Ключевое слово return: предоставляет тело функции, которое может содержать вложенные блоки; рис. 2 Показан пример простого выражения в Jinja2. Необязательное ключевое слово pdl_context: сбрасывает контекст во время вызова, например, на пустой контекст [].

Существует три типа управляющих блоков: if:, for: и различные формы repeat:. Они могут содержать вложенные блоки или простые выражения; если они содержат список блоков, список по умолчанию ведет себя как lastOf:. Если вам не нужно поведение lastOf:, распространенным подходом является инкапсуляция тела цикла в блок text: или объединение результатов итераций цикла с помощью ключевого слова join::

join::=as:? (text∣array∣lastOf),with:? строка

Перечисленные выше 15 блоков могут использоваться в сочетании с нулем или более необязательных ключевых слов, которые применяются к любому блоку:

структурированный _block::=

{ block_body,
description:?
string,
def:?
x,
defs:?
defs,
role:?
string,
contribute:?
contribute,
parser:?parser,
spec:?
type }

description: специальный комментарий. def: присваивает результат блока переменной; рис. 1 Пример уже есть в строке 10 PDL. В отличие от этого, defs: создает несколько определений переменных, каждая со своим именем x, и присваивает им значения через вложенную процедуру PDL:

defs::={x:pdl ,...,x:pdl}

role: присваивает определенную роль, такую как "пользователь", "помощник" или "система", данным, сгенерированным блоком. Вызовы PDL к модели чата следуют обычной практике современных API чата, передавая в качестве подсказок пары последовательностей {content:str, role:str}, а не обычный текст. Затем API модели применяет специфичный для модели шаблон чата и сплющивает последовательность, вставляя соответствующие управляющие теги, тем самым обеспечивая PDL-программе некоторую независимость от модели. Если в блоке явно не указана роль:, то блок модели по умолчанию принимает значение "помощник", а другие блоки - "пользователь". Роли встроенных блоков соответствуют ролям внешних блоков. В будущих исследованиях мы также планируем реализовать механизмы безопасности на основе прав доступа с использованием ролей.

Ключевое слово contribute: может быть использовано для указания (возможно, пустого) подмножества для двух направлений 'result' или 'context'. По умолчанию каждый модуль вносит вклад в свой результат и в фоновый контекст, используемый для последующих вызовов Large Language Model (LLM). Рисунок 1 В строке 2 показан пример ограничения вклада модуля только фоновым контекстом для упрощения вывода.

Ключевое слово parser: позволяет модулю, который обычно генерирует только плоские строки (например, вызов LLM), генерировать структурированные данные. Поддерживаются такие парсеры, как json, yaml, regex и jsonl. Ключевое слово spec: задает тип. Типы для PDL являются подмножеством JSON Schema (Pezoa et al. 2016), рис. 2 Краткая демонстрация общего синтаксиса сокращений показана на рисунке. Например, тип '{questions: [str], answers: [str]}' - это объект, содержащий два поля для вопросов и ответов, оба из которых содержат массивы строк. Первое 5 В этом разделе будет показано, как парсер: и спецификация: работают вместе. В будущей работе эти ключевые слова также будут использоваться для декодирования ограничений (Scholak et al. 2021).

Атомарный блок - это выражение:

выражение ::= bool | число | строка | ${𝑗𝑖𝑛𝑗𝑎_𝑒𝑥𝑝𝑟𝑒 𝑠𝑠𝑖𝑜𝑛} | string_expression

Выражения могут быть базовыми значениями, выражениями Jinja2 (Ronacher. 2008) или строки, содержащие выражения Jinja. Jinja2 - это удобный способ задания шаблонов для подсказок, где часть подсказки жестко закодирована, а другая часть заполняется выражениями. Однако PDL еще больше расширяет возможности использования Jinja2, позволяя разработчикам шаблонировать не только отдельные подсказки, но и целые цепочки вызовов моделей и других модулей. Хотя мы рекомендуем читателям обратиться к документации Jinja2 за полным списком возможных выражений, на рис. 2 В PDL используются только выражения Jinja2, исключая утверждения Jinja2, такие как {% if .. %} возможно {% for .. %}потому что они уже пересекаются с функциями PDL if: и for:.

Наконец, что не менее важно, в PDL есть модуль code:, который позволяет выполнять код на заданном языке программирования (на данный момент поддерживается только Python). В следующем разделе описываются инструменты PDL, включая интерпретатор, который предоставляет функцию "песочницы" для снижения риска выполнения произвольного кода. Для получения дополнительной информации см. ссылку на учебник в репозитории PDL на GitHub.

 

4. Инструменты

PDL предоставляет инструменты, облегчающие написание, выполнение и понимание программ PDL.

Во-первых, PDL переводчик представляет собой механизм выполнения с интерфейсом командной строки, как и следует ожидать от скриптового языка. Интерпретатор поддерживает потоковый режим, в котором вывод LLM постепенно отображается по мере его генерации, что обеспечивает более интерактивное общение. Интерпретатор также поддерживает функцию "песочницы", которая позволяет запускать его в контейнере и рекомендуется при выполнении генерируемых LLM действий или кода.

PDL Поддержка IDE VSCode был улучшен, чтобы облегчить написание кода PDL благодаря подсветке синтаксиса, автозавершению, всплывающим подсказкам для ключевых слов PDL и проверке ошибок. Эти возможности частично определяются метарежимом PDL - схемой JSON, определяющей действительный PDL.

%%pdl единица магии В сочетании с Jupyter Notebooks разработчики могут писать блоки кода непосредственно в PDL. Таким образом, платформа размещенных блокнотов может быть использована как простая игровая площадка для интерактивного изучения подсказок. При использовании нескольких единиц кода PDL в одном блокноте последующие единицы могут использовать переменные, определенные в предыдущих единицах. Кроме того, фоновый контекст последующего блока переносится из предыдущего; если это нежелательно, разработчики могут использовать функцию %%pdl --reset-context чтобы переопределить это поведение.

PDL Визуализатор документов в реальном времени Конкретный след выполнения программы PDL отображается в виде цветных вложенных ячеек, похожих на типичный график, который можно найти в диссертации или в блоге о советах LLM. Пользователь может выбрать один из боксов, чтобы отобразить соответствующий код PDL, подобно ячейке электронной таблицы, в которой отображаются данные, но пользователь может выбрать их, чтобы изучить формулу, которая сгенерировала эти данные. Такое представление в реальном времени позволяет пользователю быстро понять конкретные данные, а затем перейти к пониманию кода, сгенерировавшего эти данные.

Наконец, в PDL есть SDK(Software Development Kit), небольшая библиотека Python для вызова PDL из Python. Это полезно для расширения больших приложений Python, чтобы использовать процедуры, основанные на подсказках, такие как агенты. Как описано в разделе 3 Как говорилось в разделе , файлы PDL могут содержать Python в виде блоков кода. При разработке больших приложений с использованием PDL мы обнаружили, что полезно свести этот код к нескольким строкам, определив функцию в отдельном файле Python и затем вызвав ее из PDL. Хорошей практикой является передача данных между PDL и Python в виде объектов JSON. Как вариант, можно использовать функцию PDL spec: ключевое слово, и TypedDict или Pydantic на стороне Python для проверки типов, как показано в следующем разделе. 3 Показано.

PDL:声明式提示词编程语言 (a) коды PDL

1text:
2- lang: python
3 code: |
4 import rag_mbpp
5 PDL_SESSION.mbpp = rag_mbpp.initialize()
6 result = ""
7- defs:
8 test_query: >-
9 编写一个 Python 函数,从字符串中删除给定字符的第一个和最后一个出现。
12 retrieved:
13 lang: python
14 spec: [{query: str, answer: str}]
15 code: |
16 import rag_mbpp
17 result = rag_mbpp.retrieve(
18 PDL_SESSION.mbpp, "${test_query}", 5
19 )
20 text: >
21 给定文本在 "Q:" 之后,生成一个 Python 函数在 "A:" 之后。
24 这里有一些示例,请完成最后一个:
25- for:
26 few_shot_sample: ${retrieved}
27 repeat: |
28 Q: ${few_shot_sample.query}
29 A: ‘‘‘${few_shot_sample.answer}‘‘‘
30- |-
31 Q: ${test_query}
32 A:
33- model: watsonx/ibm/granite-3-8b-instruct
34 parameters:
35 stop: ["Q:", "A:"]

(b) Код на языке Python

1from typing import TypedDict
2import datasets
3from sklearn.feature_extraction.text \
4 import TfidfVectorizer
5
6def initialize():
7 train_in = datasets.load_dataset(
8 "mbpp", "sanitized", split="train"
9 )
10 corpus = [row["prompt"] for row in train_in]
11 tfidf = TfidfVectorizer().fit(corpus)
12 def embed(text):
13 sparse_result = tfidf.transform(
14 raw_documents=[text]
15 )
16 return sparse_result.toarray().flatten()
17 train_em = train_in.map(
18 lambda row: {"em": embed(row["prompt"])}
19 )
20 vec_db = train_em.add_faiss_index("em")
21 return vec_db, embed
22
23QA = TypedDict("QA", {"query":str,"answer":str})
24def retrieve(mbpp, query, n: int) -> list[QA]:
25 vec_db, embed = mbpp
26 key = embed(query)
27 nearest = vec_db.get_nearest_examples(
28 "em", key, n
29 )
30 queries = nearest.examples["prompt"]
31 answers = nearest.examples["code"]
32 return [
33 {"query": q, "answer": a}
34 for q, a in zip(queries, answers)
35 ]

Рисунок 3. RAG Пример в PDL

5. тематические исследования

Мы находимся в первом 2 В этом разделе был рассмотрен простой пример чатбота PDL. В этом разделе мы покажем несколько более сложных случаев использования PDL: RAGs, прокси и генерация PDL из PDLs.

5.1 Создание улучшений при извлечении

Генерация с расширенным поиском или RAGкоторая работает, сначала извлекая релевантный контекст, а затем добавляя его в подсказки модели для генерации ответов (Lewis et al. 2020). Рис. 3(a) Показана программа PDL, использующая RAG для получения небольшого количества примеров для задачи генерации кода. Код: строки 2-6 используют Python для инициализации векторной базы данных обучающих фрагментов для набора данных MBPP, состоящего из "в основном базовых программ на Python" (Austin et al., 2008). 2021). Он использует граф 3Функция Python, определенная в (b), и специальная переменная PDL_SESSION, которая позволяет передавать состояние в последующие блоки кода. Рисунок 3В строках 8-11 из (a) переменная test_query инициализируется запросом на естественном языке, который сгенерировал код на Python. В строках 12-19 переменная retrieved инициализируется пятью наиболее похожими примерами из обучающих данных.

Строки 20-24 добавляют в контекст инструкции, строки 25-29 добавляют в контекст несколько примеров, а строки 30-32 добавляют в контекст тестовые запросы. Цикл for: в строке 25 - это обычный способ генерации данных с помощью PDL, в данном случае для контекстного обучения. Наконец, строки 33-35 вызывают модель Granite 3 (Granite Team, IBM 2024), используя кумулятивный контекст, который заставляет его генерировать Python-функции для проверки запросов. Хотя это простой пример, мы также используем PDL с Codellm-Devkit (Krishna et al. 2024) используется в сочетании с инструментом, который статически анализирует исходный код различных языков программирования, чтобы извлечь другой релевантный контекст, когда LLM запрашивает задания по кодированию.

PDL:声明式提示词编程语言 (a) Код

1text:
2- read: react_few_shot_samples.txt
3- |
4
5 Hudson River 的发现者是什么时候出生的?
6- repeat:
7 text:
8 - def: thought
9 model: watsonx/ibm/granite-34b-code-instruct
10 parameters:
11 stop: ["Act:"]
12 include_stop_sequence: true
13 - def: action
14 model: watsonx/ibm/granite-34b-code-instruct
15 parameters:
16 stop: ["\n"]
17 parser: json
18 spec: {name: str, arguments: {topic: str}}
19 - def: observation
20 if: ${ action.name == "Search" }
21 then:
22 text:
23 - "Obs: "
24 - lang: python
25 code: |
26 import wikipedia
27 query = "${ action.arguments.topic }"
28 result = wikipedia.summary(query)
29 until: ${ action.name != "Search" }

(b) Отслеживание переводчика

科罗拉多造山运动东部区域的海拔范围是多少?
Tho: 我需要搜索科罗拉多造山运动,找出东部区域的范围。
Act: {”name”: ”Search”, ”arguments”: {”topic”: ”科罗拉多造山运动”}}
Obs: 科罗拉多造山运动是一个事件 […]
[…]
Hudson River 的发现者是什么时候出生的?
Tho: 我需要搜索 Hudson River 的发现者,找出他是什么时候出生的。
Act: {”name”: ”Search”, ”arguments”: {”topic”: ”Hudson River 的发现者”}}
Obs: Hudson River 是一条 315 英里长的 […]
Tho: Hudson River 的发现者是 Henry Hudson。我需要搜索 Henry Hudson,找出他是什么时候出生的。
Act: {”name”: ”Search”, ”arguments”: {”topic”: ”Henry Hudson”}}
Obs: Henry Hudson (约 1565 年 – 消失 […]
Tho: Henry Hudson 于 1565 年出生。Act: {”name”: ”Finish”, ”arguments”: {”topic”: ”1565”}}

Рисунок 4. ReAct действовать от имени кого-л., занимая ответственную должность

5.2.ReAct Agent

Моделирование на основе большого языка действовать от имени кого-л., занимая ответственную должность Позволяет выбирать и настраивать большие языковые модели движениев матрица в которых эти действия выполняются, а результаты действий передаются обратно в большую языковую модель в виде прислушаться. Существуют различные модели таких агентов, например, ReAct (Yao et al. 2023) и ReWOO (Xu et al. 2023). Действия основаны на большой языковой модели Вызов инструмента (Schick et al. 2023), в то время как агенты объединяют несколько вызовов инструментов в динамическую последовательность загрузки большой языковой модели. Цель состоит в том, чтобы сделать приложения на основе ИИ менее предписывающими и более ориентированными на достижение целей. Кроме того, агент может использовать наблюдения в качестве обратной связи для восстановления, когда действия идут не так, как нужно.

искать 4 В основе ReAct лежит цикл "думать-действовать-наблюдать", который представлен в коде в виде определений переменных think (строка 8), act (строка 13) и observe (строка 19). Мышление - это естественный язык генерации моделей, например, на рис. 4'Мне нужно найти первооткрывателя реки Гудзон, чтобы узнать, когда он родился' в следе интерпретатора в (b). Действие - это JSON, сгенерированный моделью для соответствия инструментам модели Granite, использующим обучающие данные (Abdelaziz et al. 2024). Строки 17 и 18 в левой части гарантируют, что вывод большой языковой модели будет разобран как JSON и соответствует схеме {name, arguments}, а трассировка интерпретатора в правой части показывает, что модель действительно генерирует такие объекты. Это позволяет использовать Jinja2 для доступа к полям объекта, например ${ action.arguments.topic } в строке 27. Наблюдения генерируются окружением, в данном случае кодом на Python, который вызывает Википедию. Как показано в строке 27, в строке 1 4 Как уже говорилось в разделе , для случаев, связанных с запуском кода, сгенерированного (частично) на основе большой языковой модели, мы рекомендуем использовать возможности "песочницы" PDL.

искать 4Трассировка интерпретатора в (b) показывает, что это выполнение содержит две итерации цикла агента. Хотя это простой пример, мы также реализовали агент редактирования кода с использованием PDL, который был использован в таблице лидеров SWE-bench Lite как часть commit4 (Jimenez et al. 2024). Представление решило первый случай 23,7%, используя только модель с открытым исходным кодом, что выше любого предыдущего результата с использованием модели с открытым исходным кодом и сопоставимо с результатами пограничной модели.

5.3.Генерация PDL из PDL с помощью Большой языковой модели

В предыдущих разделах было показано, как человеческие разработчики могут использовать PDL для кодирования различных моделей подсказок. В этом разделе мы рассмотрим большие языковые модели и покажем, как их можно использовать для генерации PDL. Такая генерация мета-PDL полезна, когда большие языковые модели должны создавать планы решения задач, например, как часть рабочего процесса агента. Традиционно такие планы представляют собой только текст, JSON или код на языке Python. С PDL эти планы могут представлять собой комбинацию полностью исполняемых моделей и вызовов кода. В этом разделе рассматривается использование метагенерации PDL на наборе данных GSMHard5 .

GSMHard - это более сложная версия GSM8k, содержащая школьные математические задачи, требующие простых арифметических или символических рассуждений. GSMHard содержит входные данные - формулировку математической задачи, и выходные данные - код на языке Python, который решает задачу. Мы реализовали PAL (Gao et al. 2023), но вместо генерации кода Python большая языковая модель должна генерировать PDL. Текстовая цепочка мышления представлена в виде текстовых блоков PDL, а арифметика выполняется с помощью блоков кода PDL.

искать 6 Показана программа PDL, которая генерирует PDL-код и выполняет его в одной и той же программе. В переменной demos хранится небольшое количество примеров, призванных научить модель генерировать PDL-код. В строке 32 блок вызова модели использует эти примеры и задачу со свободными переменными в качестве входных данных. Результатом является программа PDL для решения проблемы. Строка 38 извлекает программу PDL и выполняет ее в Python. Программа применяется к набору данных GSMHard, где проблема заполняет входную задачу.

Этот эксперимент показал, что 10% для набора данных GSMHard на самом деле был ошибочным, поскольку истинное положение дел не соответствовало заданным вопросам. Рис. 6 Показаны примеры таких несоответствий. Использование PDL помогло выявить это, так как сгенерированный код PDL был доступен для чтения человеком, поэтому мы смогли легко проверить точки данных, которые не совпадали с истиной, и обнаружили, что в некоторых случаях истина была неверной. Мы использовали большую языковую модель, чтобы покрыть весь набор данных, и систематически выбирали примеры, которые казались непоследовательными. Затем мы вручную проверили результаты, чтобы удалить ложные срабатывания, и выявили точки данных из 10% с этой проблемой.

PDL:声明式提示词编程语言

 

1 定义:
2 示例:
3 数据:
4 文本:
5 |
6 ...
7
8 问题: Roger 有 5 个网球。
9 他又购买了 2 罐网球。
10 每罐有 3 个网球。
11 现在他总共有多少个网球?
12
13 答案:
14 ```
15 文本:
16 - "Roger 起初有\n"
17 - 定义: tennis_balls
18 数据: 5
19 - "\n个网球。\n"
20 - "2 罐,每罐有 3 个网球,总共是\n"
21 - 语言: python
22 定义: bought_balls
23 代码: result = 2 * 3
24 - "\n个网球。\n"
25 - "结果是:\n"
26 - 语言: python
27 定义: RESULT
28 代码: result = ${ tennis_balls } + ${ bought_balls }
29 ```
30 原始: true
31 文本:
32 - 模型: watsonx/meta-llama/llama-3-70b-instruct
33 定义: PDL
34 输入:
35 文本:
36 - ${ demos.text }
37 - "问题: ${ question }"
38 - 语言: python
39 代码: |
40 from pdl.pdl import exec_str
41 s = """${ PDL }"""
42 pdl = s.split("```")[1]
43 result = exec_str(pdl)
44 定义: RESULT

Рисунок 5.

James 决定每周跑 1793815 次冲刺
每次冲刺 60 米。
他每周总共跑多少米?
def solution():
sprints_per_day = 1793815
days_per_week = 3
meters_per_sprint = 60
total_sprints = sprints_per_day * days_per_week
total_meters = total_sprints * meters_per_sprint
result = total_meters
return result

Рисунок 6. Точки данных пробной проблемы GSMHard

 

6. сопутствующая работа

По данным недавнего исследования Рамки для кия Определяется как слой, который управляет, упрощает и облегчает взаимодействие между LLM и пользователями, инструментами или другими моделями (Liu et al.2023). В исследовании подчеркивается, что основным недостатком системы подсказок является крутая кривая обучения.

Вероятно, самым популярным фреймворком подсказок на сегодняшний день является LangChain (Chase et al.2022), богатый функционал которого делает его одновременно мощным и сложным. Основная мотивация MiniChain как раз и заключается в том, чтобы избежать этой сложности (Rush.2023), который предлагает меньшее количество простых функций, которые можно комбинировать для создания продвинутых приложений. Однако и LangChain, и MiniChain - это фреймворки на базе Python, что делает их более недекларативными, поскольку разработчикам приходится писать императивный код. PDL имеет схожую с MiniChain мотивацию, но делает еще один шаг вперед, используя в качестве основы не Python, а YAML.

Как и в случае с другими системами подсказок, цель PDL - сделать LLM более надежным.Guidance (Microsoft.2023) - это фреймворк на основе Python, который обеспечивает более структурированный дизайн, но является более примитивным, чем LangChain. Аналогично, LMQL (Beurer-Kellner et al.2023PDL в некоторой степени вдохновляется LMQL в его переплетении подсказок и программирования, но, в отличие от LMQL, он меньше опирается на императивный код Python. Crouse et al. используют конечные автоматы состояния для формального определения внутреннего потока различных интеллектуальных циклов (Crouse et al.2024); хотя это и увлекательное занятие, оно не представляет собой сложного языка подсказок.

Одно из преимуществ языков, специфичных для конкретной области, заключается в том, что они могут реализовывать преобразования программ, например, для оптимизации (Mernik et al.2005).DSPy cueing framework (Khattab et al.2023) имеет девиз "Программирование, а не подсказки": он генерирует подсказки автоматически, поэтому разработчикам не нужно писать их вручную. Аналогично, Виейра (Li et al.2024) расширяет Prolog для использования LLM в качестве вероятностного отношения и автоматически генерирует подсказки.DSPy и Vieira - очень продвинутые фреймворки, но, в отличие от PDL, они оба ослабляют контроль разработчика над конкретными подсказками.Lale (Baudart et al.2021) - это язык, который позволяет пользователям инкрементально регулировать компромиссы между автоматизацией и контролем в конвейере ИИ, но он не фокусируется на подсказках LLM. dspy, Vieira и Lale оптимизируют прогностическую производительность, а другая оптимизация нацелена на вычислительную производительность. sglang (Zheng et al.2023) достигается за счет более эффективного использования префиксного кэша, что приводит к большему количеству обращений к кэшу KV (Kwon et al.2023). В дальнейшей работе будет исследовано, может ли декларативная природа PDL обеспечить аналогичную оптимизацию вычислительной производительности.

В последнее время появилось несколько схем подсказок на основе моделирования большого языка (LLM), в которых основное внимание уделяется агентам LLM.AutoGen (Wu et al.2023) - это мультиагентный фреймворк, в котором весь контент состоит из агентов и диалогов. Другие мультиагентные фреймворки включают CrewAI (Moura.2023) и GPTSwarm (Zhuge et al.2024). PDL, хотя и поддерживает прокси, придерживается более сбалансированной позиции, рассматривая прокси как одну из нескольких техник подсказки.

 

7. Заключение

PDL - это декларативный язык, ориентированный на данные: программы состоят из блоков YAML, каждый из которых представляет собой либо литеральные, либо генеративные данные. Модель мышления заключается в выполнении блока путем добавления его данных к фоновому контексту, который используется в качестве подсказки при последующих обращениях к более широкой модели языка. В диссертации представлен язык с примерами программ и экскурсом в синтаксис и инструментарий. Декларативная природа языка также позволяет легко реализовать автоматическую оптимизацию для повышения скорости, точности и безопасности, которая будет постепенно реализована в будущей работе. PDL уже готов к использованию и находится с открытым исходным кодом по следующему URL:https://github.com/IBM/prompt-declaration-language.

© заявление об авторских правах

Похожие статьи

Нет комментариев

Вы должны войти в систему, чтобы участвовать в комментариях!
Войти сейчас
нет
Нет комментариев...