{"id":15063572,"url":"https://github.com/martosaur/instructor_lite","last_synced_at":"2026-02-01T23:00:50.474Z","repository":{"id":255440333,"uuid":"849697864","full_name":"martosaur/instructor_lite","owner":"martosaur","description":"Structured outputs for LLMs in Elixir ","archived":false,"fork":false,"pushed_at":"2025-11-21T04:29:18.000Z","size":881,"stargazers_count":119,"open_issues_count":0,"forks_count":10,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-11-21T06:19:24.870Z","etag":null,"topics":["ai","ecto","elixir","instructor","llm"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/martosaur.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-08-30T04:35:50.000Z","updated_at":"2025-11-21T04:28:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"c3fbb033-2fde-4579-9f34-c1a4a8a7f6da","html_url":"https://github.com/martosaur/instructor_lite","commit_stats":null,"previous_names":["martosaur/instructor_lite"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/martosaur/instructor_lite","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martosaur%2Finstructor_lite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martosaur%2Finstructor_lite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martosaur%2Finstructor_lite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martosaur%2Finstructor_lite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martosaur","download_url":"https://codeload.github.com/martosaur/instructor_lite/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martosaur%2Finstructor_lite/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28993725,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T22:01:47.507Z","status":"ssl_error","status_checked_at":"2026-02-01T21:58:37.335Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","ecto","elixir","instructor","llm"],"created_at":"2024-09-25T00:04:34.849Z","updated_at":"2026-02-01T23:00:50.467Z","avatar_url":"https://github.com/martosaur.png","language":"Elixir","funding_links":[],"categories":["LangChain-Style Components","LLM Clients and APIs","Generative AI"],"sub_categories":["How to Join","LLM Tools"],"readme":"# InstructorLite\n\n[![Instructor version](https://img.shields.io/hexpm/v/instructor_lite.svg)](https://hex.pm/packages/instructor_lite)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/instructor_lite/)\n[![Hex Downloads](https://img.shields.io/hexpm/dt/instructor_lite)](https://hex.pm/packages/instructor_lite)\n[![GitHub stars](https://img.shields.io/github/stars/martosaur/instructor_lite.svg)](https://github.com/martosaur/instructor_lite/stargazers)\n[![CI](https://github.com/martosaur/instructor_lite/actions/workflows/ci.yml/badge.svg)](https://github.com/martosaur/instructor_lite/actions/workflows/ci.yml)\n\nStructured prompting for LLMs. InstructorLite is a fork, spiritual successor and almost an entire rewrite of [instructor_ex](https://github.com/thmsmlr/instructor_ex) library.\n \nInstructorLite provides basic building blocks to embed LLMs into your\napplication. It uses Ecto schemas to make sure LLM output has a predictable\nshape and can play nicely with deterministic application logic. For an example\nof what can be built with InstructorLite, check out\n[Handwave](https://github.com/martosaur/handwave)\n\n\n## Why Lite\n\nInstructorLite is designed to be:\n1. **Lean**. It does so little it makes you question if you should just write your own version!\n2. **Composable**. Almost everything it does can be overridden or extended.\n3. **Magic-free**. It doesn't hide complexity behind one line function calls, but does its best to provide you with enough information to understand what's going on.\n\nInstructorLite is tested to be compatible with the following providers:\n[OpenAI](https://openai.com/api/), [Anthropic](https://www.anthropic.com/),\n[Gemini](https://ai.google.dev/) and any Chat Completions-compatible APIs, such as [Grok](https://x.ai/).\n\n## Features\n\nInstructorLite can be boiled down to these features:\n1. It provides a very simple function for generating JSON schema from Ecto schema.\n2. It facilitates generating prompts, calling LLMs, casting and validating responses, including retrying prompts when validation fails.\n3. It holds knowledge of major LLM providers' API interfaces with adapters.\n\nAny of the features above can be used independently.\n\n## Usage\n\nDefine an instruction, which is a normal Ecto schema with an extra `use Instructor.Instruction` call.\n\n```elixir\ndefmodule UserInfo do\n  use Ecto.Schema\n  use InstructorLite.Instruction\n  \n  @primary_key false\n  embedded_schema do\n    field(:name, :string)\n    field(:age, :integer)\n  end\nend\n```\n\nNow let's use `InstructorLite.instruct/2` to fill the schema from unstructured text:\n\n\u003c!-- tabs-open --\u003e\n\n### OpenAI\n\n```elixir\niex\u003e InstructorLite.instruct(%{\n    input: [\n      %{role: \"user\", content: \"John Doe is forty-two years old\"}\n    ]\n  },\n  response_model: UserInfo,\n  adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :openai_key)]\n)\n{:ok, %UserInfo{name: \"John Doe\", age: 42}}\n```\n\n### Anthropic\n\n```elixir\niex\u003e InstructorLite.instruct(%{\n    messages: [\n      %{role: \"user\", content: \"John Doe is forty-two years old\"}\n    ]\n  },\n  response_model: UserInfo,\n  adapter: InstructorLite.Adapters.Anthropic,\n  adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :anthropic_key)]\n)\n{:ok, %UserInfo{name: \"John Doe\", age: 42}}\n```\n\n### Llamacpp\n\n```elixir\niex\u003e InstructorLite.instruct(%{\n    prompt: \"John Doe is forty-two years old\"\n  },\n  response_model: UserInfo,\n  adapter: InstructorLite.Adapters.Llamacpp,\n  adapter_context: [url: Application.fetch_env!(:instructor_lite, :llamacpp_url)]\n)\n{:ok, %UserInfo{name: \"John Doe\", age: 42}}\n```\n\n### Gemini\n\n```elixir\niex\u003e InstructorLite.instruct(%{\n    contents: [\n      %{\n        role: \"user\",\n        parts: [%{text: \"John Doe is forty-two years old\"}]\n      }\n    ]\n  },\n  response_model: UserInfo,\n  json_schema: %{\n    type: \"object\",\n    required: [:age, :name],\n    properties: %{name: %{type: \"string\"}, age: %{type: \"integer\"}},\n  },\n  adapter: InstructorLite.Adapters.Gemini,\n  adapter_context: [\n    api_key: Application.fetch_env!(:instructor_lite, :gemini_key)\n  ]\n)\n{:ok, %UserInfo{name: \"John Doe\", age: 42}}\n```\n\n### Grok\n\nGrok API is compatible with OpenAI Chat Completions endpoint, so we can use\nthe `ChatCompletionsCompatible` adapter with Grok's `url` and `model_name`\n\n```elixir\niex\u003e InstructorLite.instruct(%{\n    model: \"grok-3-latest\",\n    messages: [\n      %{role: \"user\", content: \"John Doe is forty-two years old\"}\n    ]\n  },\n  response_model: UserInfo,\n  adapter: InstructorLite.Adapters.ChatCompletionsCompatible,\n  adapter_context: [\n    url: \"https://api.x.ai/v1/chat/completions\",\n    api_key: Application.fetch_env!(:instructor_lite, :grok_key)\n  ]\n)\n{:ok, %UserInfo{name: \"John Doe\", age: 42}}\n```\n\n\u003c!-- tabs-close --\u003e\n\n## Configuration\n\nInstructorLite _does not_ access the application environment for configuration options like adapter or API key. Instead, they're passed as options when needed. Note that different adapters may require different options, so make sure to check their documentation.\n\n## Approach to development\n\nInstructorLite is hand-written by a human and all external contributions are\nvetted by a human. And said human is committed to keep it this way for\nforeseeable future. This comes with both advantages and drawbacks. The library\nmay be prone to silly human errors and poor judgement, but at the same time it\nis likely won't explode in complexity overnight or undergo a full rewrite every\ncouple of months. Tune your expectations accordingly! \n\n## Non-goals\n\nInstructorLite very explicitly doesn't pursue the following goals:\n1. Response streaming. Streaming is good UX for cases when LLM output is relayed\n   to users, but doesn't make much sense for application environment, where\n   structured outputs are usually used.\n2. Unified interface. We acknowledge that LLM providers can be very different\n   and trying to fit them under the same roof brings a ton of unnecessary\n   complexity. Instead, InstructorLite aims to make it simple for developers to\n   understand these differences and grapple with them.\n\n\n## Installation\n\nIn your mix.exs, add `:instructor_lite` to your list of dependencies:\n\n```elixir\ndef deps do\n  [\n    {:instructor_lite, \"~\u003e 1.2.0\"}\n  ]\nend\n```\n\nOptionally, include `Req` HTTP client (used by default) and Jason (for Elixir older than 1.18):\n\n```elixir\ndef deps do\n  [\n    {:req, \"~\u003e 0.5 or ~\u003e 1.0\"},\n    {:jason, \"~\u003e 1.4\"}\n  ]\nend\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartosaur%2Finstructor_lite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartosaur%2Finstructor_lite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartosaur%2Finstructor_lite/lists"}