imp README

The project's README from github.com/deepfates/imp. As one markdown file: README.md.

Imp

Declarative, self-improving language-model programs for Elixir.

An imp studies a hand of cards through a lens while a smaller imp springs from its tail.

Imp is a full port of DSPy to the BEAM. You describe what each language-model step takes and returns, choose how it thinks, and let an optimizer improve it against examples of what good looks like. You get signatures, modules, optimizers, agent loops and retrieval, running with the reliability and concurrency of OTP.

DSPy makes each call to a model a declared, typed function that you can measure and improve. On the BEAM, an agent is a process: it keeps its own state, receives messages, and runs under a supervisor alongside the rest of your application. With both, you can build anything from one typed call to many long-running agents, and improve each part by measuring it.

Declare a task

lm = Imp.req_llm("openai:gpt-5.4-mini", api_key: System.fetch_env!("OPENAI_API_KEY"))

triage =
  "issue -> kind: enum[bug,feature,question], summary"
  |> Imp.signature("Triage a GitHub issue.")
  |> Imp.predict(lm: lm)

{:ok, prediction} =
  Imp.call(triage, %{issue: "App crashes on startup since 0.4 with ** (KeyError) key :lm not found"})

{Imp.get(prediction, :kind), Imp.get(prediction, :summary)}
#=> {"bug", "App crashes on startup since version 0.4 with a KeyError for `:lm` not found."}

You never write a prompt or a parser. Imp builds the prompt from the signature, checks the reply against it, and gives you typed fields: kind is always one of the three values, or the call returns an error. To make the same task reason first, use Imp.chain_of_thought/2; to give it tools, use Imp.react/3. The signature stays the same.

Measure it and improve it

Give Imp labeled examples and a metric, and it scores the program and optimizes it. You need three lists of issues you have already labeled: trainset, which the optimizer learns from; valset, which it uses to choose between the programs it tries; and testset, which you score on before and after. strong_lm is a more capable model that GEPA uses to read failures and write new instructions.

# Each set is a list of labeled issues like this one:
example =
  Imp.example(%{issue: "Please add a dark mode to the dashboard", kind: "feature"})
  |> Imp.with_inputs([:issue])

metric = Imp.exact_match(:kind)

Imp.evaluate(triage, testset, metric).score

optimizer = Imp.Optimizer.GEPA.new(metric, reflection_lm: strong_lm, max_metric_calls: 300)
improved = Imp.optimize!(triage, optimizer, trainset, valset)

Imp.evaluate(improved, testset, metric).score

GEPA runs the program, reads where it failed, and rewrites its instructions. Other optimizers choose worked examples (LabeledFewShot, BootstrapFewShot), search over combinations of instructions and examples (MIPROv2), learn rules and examples from the program's own better and worse attempts (SIMBA), or train the model's weights (fine-tuning, GRPO). The result is a new program whose instructions and examples you can read, save as JSON, and review as a diff.

Build agents

A tool is an Elixir function. Imp.react/3 builds an agent that calls tools until it can answer. This one reads web pages with Req. Imp depends on Req; if your own code calls it, as this tool does, add {:req, "~> 0.6"} to your dependencies:

fetch =
  Imp.tool(:fetch, "Read a web page as text.", fn %{"url" => url} -> Req.get!(url).body end,
    schema: %{"type" => "object", "properties" => %{"url" => %{"type" => "string"}}, "required" => ["url"]}
  )

researcher = Imp.react("question -> answer", [fetch], lm: lm)

question =
  "What version does https://raw.githubusercontent.com/elixir-lang/elixir/v1.18.0/VERSION say? " <>
    "Reply with just the version."

{:ok, prediction} = Imp.call(researcher, %{question: question})
Imp.get(prediction, :answer)
#=> "1.18.0"

Run agents as processes

Imp.call/2 runs a program in your process. Imp.start_run/3 runs it as its own supervised process instead, so you can watch it, stop it, and decide which tool calls it may make:

{:ok, run} =
  Imp.start_run(researcher, %{question: question},
    authorize: fn call ->
      url = call.arguments["url"] || ""

      if String.starts_with?(url, "https://raw.githubusercontent.com/"),
        do: :allow,
        else: {:deny, :untrusted_host}
    end
  )

{:ok, prediction} = Task.await(run.task, :infinity)

for event <- Imp.Run.events(run), do: event.kind
#=> [:run_started, :tools_sent, :model_request, :model_response, :tool_call,
#    :tool_result, :model_request, :model_response, :run_finished]

Imp also includes:

The optimizers work on agents too. GEPA reflects on whole agent runs and rewrites the instructions that steer them. Optimize Anything rewrites any text or JSON you can score, such as an agent's tool descriptions.

Install

{:imp, "~> 0.8"}

Imp needs Elixir 1.19 or later and a C and C++ compiler, for the native code in two dependencies (jaxon and erlexec). The first compile needs network access, because erlexec's build fetches rebar3 plugins. It reaches models through ReqLLM, so any provider ReqLLM supports works.

Imp 0.8 is experimental. Its API may still change, and its optimizers need large-scale benchmarking. Bug reports and pull requests are welcome.

Learn

Imp is MIT licensed.

imp (deepfates/imp)

Searching Database…

254 ·GitHub
Что это?Imp — полный порт DSPy на BEAM: фреймворк на Elixir для создания и автоматического улучшения программ поверх языковых моделей. Вы описываете входы и выходы шага как типизированную сигнатуру, а оптимизатор подгоняет её промпты или примеры по размеченным данным.
Это библиотека или фреймворк для создания приложений?Это фреймворк/библиотека на Elixir, которую вы добавляете в своё BEAM-приложение: вы определяете сигнатуры и модули, Imp формирует и разбирает промпты, а агенты работают как наблюдаемые OTP-процессы рядом с остальным вашим кодом.
Как добавить Imp в Elixir-проект?Добавьте Imp как зависимость в mix.exs и скачайте его через mix deps.get; первой компиляции нужен доступ к сети, потому что одна из нативных зависимостей (erlexec) при сборке скачивает плагины rebar3.
Что нужно установить, чтобы это запустить?Нужен Elixir 1.19 или новее плюс компиляторы C и C++, поскольку две зависимости (jaxon и erlexec) компилируют нативный код. Доступ к моделям идёт через ReqLLM, так что также понадобится API-ключ того провайдера LLM из поддерживаемых ReqLLM, которым вы хотите пользоваться.
Насколько это стабильно, можно ли уже строить на этом?Не полностью — в README Imp 0.8 помечен как экспериментальный, предупреждают, что его API может ещё измениться, и что его оптимизаторам по-прежнему нужно масштабное бенчмарк-тестирование.
Нужно ли уже знать DSPy, чтобы этим пользоваться?Не обязательно — в документации есть гайд «Getting started», который строит программу с нуля, и гайд «Coming from DSPy», сопоставляющий имена DSPy с именами Imp для тех, кто уже знаком с этой Python-библиотекой.
Какие оптимизаторы входят в Imp?В него входят GEPA, который разбирает неудачи с помощью более сильной модели и переписывает инструкции; LabeledFewShot и BootstrapFewShot, подбирающие готовые примеры; MIPROv2, перебирающий комбинации инструкций и примеров; SIMBA, обучающийся на собственных удачных и неудачных попытках программы; а также fine-tuning/GRPO, обучающие веса модели.
Как работают инструменты агента?Инструмент — это просто функция на Elixir; Imp.react/3 строит агента, который вызывает эти инструменты, пока не сможет дать ответ, а Imp.startrun/3 запускает этого агента как отдельный наблюдаемый OTP-процесс: за ним можно следить, его можно остановить или ограничить.
Может ли Imp использовать существующие MCP-серверы?Да — Imp может импортировать инструменты любого одобренного вами MCP-сервера и использовать их как нативные функции, а также может выставлять любую программу Imp как агента для ACP-клиентов вроде Zed.
Что происходит с вызовом инструмента, если запуск прерван на середине?Imp никогда не повторяет молча вызов инструмента, который мог уже сработать, — вместо этого он сообщается как неизвестный, а запросы к модели обрываются по заданному вами дедлайну.
Creator
deepfates
Size
46.7 MB
Stars
254
Age
3mo
Commits · 90 Days