### Copy Example Configuration File Source: https://hexdocs.pm/instructor_lite/local_development_guide.html Copies the example configuration file to `config/config.exs`. This file should be used to store your personal API keys and is ignored by Git. ```bash cp config/config.example.exs config/config.exs ``` -------------------------------- ### Install Dependencies and Run Tests Source: https://hexdocs.pm/instructor_lite/local_development_guide.html Installs project dependencies and runs all unit tests. Ensure you have run `mix deps.get` before running tests. ```bash mix deps.get mix test ``` -------------------------------- ### Install InstructorLite and Dependencies Source: https://hexdocs.pm/instructor_lite/openai-advanced-features.html Installs the InstructorLite library along with its dependencies, req and kino, using Mix.install. ```elixir Mix.install( [ {:instructor_lite, "~> 1.0"}, {:req, "~> 0.5"}, {:kino, "~> 0.16"} ] ) ``` -------------------------------- ### Basic Example with OpenAI Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Demonstrates a basic ask request to an OpenAI model. Ensure the :openai_key is configured in your application environment. ```elixir iex> InstructorLite.ask(%{ model: "gpt-5-mini-2025-08-07", input: [ %{role: "user", content: "Cite me the greatest opening line in the history of cyberpunk."} ] }, adapter: InstructorLite.Adapters.OpenAI, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :openai_key)] ) {:ok, "The sky above the port was the color of television, tuned to a dead channel."} ``` -------------------------------- ### Instructing with Anthropic API for Structured Output Source: https://hexdocs.pm/instructor_lite/InstructorLite.Adapters.Anthropic.html Example of using InstructorLite.instruct with the Anthropic adapter to get a structured response. Ensure your Anthropic API key is configured in your environment. ```elixir InstructorLite.instruct(%{ messages: [%{role: "user", content: "John is 25yo"}], model: "claude-sonnet-4-5", metadata: %{user_id: "3125"} }, response_model: %{name: :string, age: :integer}, adapter: InstructorLite.Adapters.Anthropic, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :anthropic_key)] ) {:ok, %{name: "John", age: 25}} ``` -------------------------------- ### Ask Response Example Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html An example of a successful raw string response from `InstructorLite.ask/2` when using the Ollama adapter. ```Elixir {:ok, "\" All secrets are best kept cool.\" - Neuromancer"} ``` -------------------------------- ### instruct/2 Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Perform instruction session from start to finish. ```APIDOC ## instruct/2 ### Description Perform instruction session from start to finish. ### Function Signature ```elixir instruct(params, opts) ``` ### Parameters #### `params` - Type: `InstructorLite.Adapter.params()` - Description: Adapter-specific map containing values eventually sent to the LLM. #### `opts` - Type: `opts()` - Description: Options passed to instructor functions. ### Return Value - The return type is not explicitly defined in the source, but it is expected to handle the entire instruction session. ### Examples ```elixir # Example usage would go here, but is not provided in the source text. ``` ``` -------------------------------- ### Instruct Response Example Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html An example of a successful structured response from `InstructorLite.instruct/2` when using the Ollama adapter. ```Elixir {:ok, %{name: "John Doe", age: 42}} ``` -------------------------------- ### Install Instructor Lite and Dependencies Source: https://hexdocs.pm/instructor_lite/batch-api.html Install the necessary Elixir packages for Instructor Lite, Req, and Multipart. ```elixir Mix.install( [ {:instructor_lite, "~> 1.0"}, {:req, "~> 0.5"}, {:multipart, "0.4.0"} ] ) ``` -------------------------------- ### Instruct Example with Llama.cpp Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Demonstrates performing an instruction session with a Llama.cpp model, specifying the response model structure. Ensure the :llamacpp_url is configured. ```elixir iex> InstructorLite.instruct(%{ prompt: "John Doe is fourty two years old" }, response_model: %{name: :string, age: :integer}, adapter: InstructorLite.Adapters.Llamacpp, adapter_context: [url: Application.fetch_env!(:instructor_lite, :llamacpp_url)] ) {:ok, %{name: "John Doe", age: 42}} ``` -------------------------------- ### Instruct Example with OpenAI Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Demonstrates performing an instruction session with an OpenAI model, specifying the response model structure. Ensure the :openai_key is configured. ```elixir iex> InstructorLite.instruct(%{ input: [ %{role: "user", content: "John Doe is fourty two years old"} ] }, response_model: %{name: :string, age: :integer}, adapter: InstructorLite.Adapters.OpenAI, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :openai_key)] ) {:ok, %{name: "John Doe", age: 42}} ``` -------------------------------- ### Instruct with Chat Completions Adapter Source: https://hexdocs.pm/instructor_lite/InstructorLite.Adapters.ChatCompletionsCompatible.html Example of using InstructorLite.instruct with the ChatCompletionsCompatible adapter to get structured output from a chat completion API. Requires messages, model, service tier, response model, adapter, and adapter context including API key and URL. ```elixir InstructorLite.instruct(%{ messages: [%{role: "user", content: "John is 25yo"}], model: "gpt-4o-mini", service_tier: "default" }, response_model: %{name: :string, age: :integer}, adapter: InstructorLite.Adapters.ChatCompletionsCompatible, adapter_context: [ api_key: Application.fetch_env!(:instructor_lite, :openai_key), url: "https://api.openai.com/v1/chat/completions" ] ) {:ok, %{name: "John", age: 25}} ``` -------------------------------- ### Basic Example with Gemini Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Demonstrates a basic ask request to a Gemini model. Ensure the :gemini_key is configured in your application environment. ```elixir iex> InstructorLite.ask(%{ contents: [ %{ role: "user", parts: [%{text: "Cite me the greatest opening line in the history of cyberpunk."}] } ] }, adapter: InstructorLite.Adapters.Gemini, adapter_context: [ api_key: Application.fetch_env!(:instructor_lite, :gemini_key) ] ) {:ok, "The sky above the port was the color of a bruise."} ``` -------------------------------- ### Instructor Configuration for Releases Source: https://hexdocs.pm/instructor_lite/migrating_from_instructor.html Example of configuring release stripping to keep documentation files when using Instructor. ```elixir # mix.exs def project do # ... releases: [ myapp: [ strip_beams: [keep: ["Docs"]] ] ] end ``` -------------------------------- ### Example Response for find_output Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html An example of a response structure that the `find_output/2` callback might process. ```Elixir {:ok, "{\"name\": \"George_Washington\"}\n\n "} ``` -------------------------------- ### Install Instructor Lite and Req Source: https://hexdocs.pm/instructor_lite/text-classification.html Installs the necessary Elixir dependencies for using Instructor Lite and Req. ```elixir Mix.install( [ {:instructor_lite, "~> 1.0"}, {:req, "~> 0.5"} ] ) ``` -------------------------------- ### Instructor Application Configuration Source: https://hexdocs.pm/instructor_lite/migrating_from_instructor.html Example of configuring Instructor's adapter and API key via application configuration. ```elixir # config.exs config :instructor, adapter: Instructor.Adapters.OpenAI, openai: [api_key: "my_secret_key"] ``` -------------------------------- ### Install Instructor Lite and Dependencies Source: https://hexdocs.pm/instructor_lite/vision.html Install the necessary Elixir dependencies for Instructor Lite, req, and Kino. ```elixir Mix.install( [ {:instructor_lite, "~> 1.0"}, {:req, "~> 0.5"}, {:kino, "~> 0.12.3"} ] ) ``` -------------------------------- ### Basic Example with Grok (Chat Completions Compatible) Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Demonstrates a basic ask request to a Grok model using a chat completions compatible endpoint. Ensure the :grok_key is configured and the URL is correct. ```elixir iex> InstructorLite.ask(%{ model: "grok-3-latest", messages: [ %{ role: "user", content: "Cite me the greatest opening line in the history of cyberpunk." } ] }, adapter: InstructorLite.Adapters.ChatCompletionsCompatible, adapter_context: [ url: "https://api.x.ai/v1/chat/completions", api_key: Application.fetch_env!(:instructor_lite, :grok_key) ] ) {:ok, "The sky above the port was the color of television, tuned to a dead channel."} ``` -------------------------------- ### Instruct with Custom Ollama Adapter Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html Example of using `InstructorLite.instruct/2` with the custom `OllamaAdapter`. This demonstrates how to configure the adapter, specify the model, and provide necessary context like the API URL. ```Elixir InstructorLite.instruct(%{ messages: [ %{role: "user", content: "Dr. John Doe is forty two"} ], }, adapter: OllamaAdapter, notes: "Trim down all people's titles", response_model: %{name: :string, age: :integer}, adapter_context: [ url: "http://localhost:11434/api/chat" ] ) ``` -------------------------------- ### ask/2 Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Performs a simple request with a non-structured response. This function is useful when you already have InstructorLite setup in the project and need to get simple text output. ```APIDOC ## ask/2 ### Description Perform a simple request with a non-structured response. This function is useful when you already have `InstructorLite` setup in the project and need to get simple text output. ### Function Signature ```elixir ask(params, opts) ``` ### Parameters #### `params` - Type: `InstructorLite.Adapter.params()` - Description: Adapter-specific map containing values eventually sent to the LLM (e.g., prompt, model name, temperature). #### `opts` - Type: `ask_opts()` - Description: A subset of all options used by the `ask/2` function. See `opts()` for a full list of available options. ### Return Value - `{:ok, String.t()}`: On success, returns the string response from the LLM. - `{:error, any()}`: On error, returns an error tuple. - `{:error, atom(), any()}`: On error with a specific atom identifier, returns an error tuple. ### Examples ```elixir # Example usage would go here, but is not provided in the source text. ``` ``` -------------------------------- ### Basic Example with Anthropic Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Demonstrates a basic ask request to an Anthropic model. Ensure the :anthropic_key is configured in your application environment. ```elixir iex> InstructorLite.ask(%{ messages: [ %{role: "user", content: "Cite me the greatest opening line in the history of cyberpunk."} ], max_tokens: 100, model: "claude-sonnet-4-20250514" }, adapter: InstructorLite.Adapters.Anthropic, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :anthropic_key)] ) {:ok, "The sky above the port was the color of television, tuned to a dead channel."} ``` -------------------------------- ### Example Extracted Product Data Source: https://hexdocs.pm/instructor_lite/vision.html This is an example of the structured data that can be extracted from the product image. ```elixir %Product{ name: "Thomas Wooden Railway Thomas The Tank Engine", price: Decimal.new("33.0"), currency: :usd, color: "blue" } ``` -------------------------------- ### Install Instructor Lite and Dependencies Source: https://hexdocs.pm/instructor_lite/text-to-dataframes.html Install the necessary Elixir dependencies for Instructor Lite, Req, Explorer, Kino, and Kino Explorer. ```elixir Mix.install( [ {:instructor_lite, "~> 1.0"}, {:req, "~> 0.5"}, {:explorer, "~> 0.7.2"}, {:kino, "~> 0.12.0"}, {:kino_explorer, "~> 0.1.13"} ] ) ``` -------------------------------- ### Instruct with Llama.cpp Adapter Source: https://hexdocs.pm/instructor_lite/InstructorLite.Adapters.Llamacpp.html Example of using the `instruct` function with the Llama.cpp adapter. Requires specifying the response model, adapter, and adapter context with the server URL. ```elixir InstructorLite.instruct(%{ prompt: "John is 25yo", temperature: 0.8 }, response_model: %{name: :string, age: :integer}, adapter: InstructorLite.Adapters.Llamacpp, adapter_context: [url: "http://localhost:8000/completion"] ) {:ok, %{name: "John", age: 25}} ``` -------------------------------- ### Ask with Custom Ollama Adapter Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html Example of using `InstructorLite.ask/2` with the custom `OllamaAdapter`. This is suitable for retrieving raw string output rather than structured data. ```Elixir InstructorLite.ask(%{ model: "deepseek-r1:8b", stream: false, think: false, messages: [ %{role: "user", content: "Cite me the greatest opening line in the history of cyberpunk. No yapping, just the line."} ], }, adapter: OllamaAdapter, adapter_context: [ url: "http://localhost:11434/api/chat" ] ) ``` -------------------------------- ### Instruct with OpenAI Adapter Source: https://hexdocs.pm/instructor_lite/InstructorLite.Adapters.OpenAI.html Example of using InstructorLite.instruct with the OpenAI adapter to generate structured output. Requires specifying the input, model, service tier, response model, adapter, and adapter context including the API key. ```elixir InstructorLite.instruct(%{ input: [%{role: "user", content: "John is 25yo"}], model: "gpt-4o-mini", service_tier: "default" }, response_model: %{name: :string, age: :integer}, adapter: InstructorLite.Adapters.OpenAI, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :openai_key)] ) {:ok, %{name: "John", age: 25}} ``` -------------------------------- ### Instruct Example with Anthropic Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Demonstrates performing an instruction session with an Anthropic model, specifying the response model structure. Ensure the :anthropic_key is configured. ```elixir iex> InstructorLite.instruct(%{ messages: [ %{role: "user", content: "John Doe is fourty two years old"} ] }, response_model: %{name: :string, age: :integer}, adapter: InstructorLite.Adapters.Anthropic, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :anthropic_key)] ) {:ok, %{name: "John Doe", age: 42}} ``` -------------------------------- ### Instruct Example with Gemini Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Demonstrates performing an instruction session with a Gemini model, specifying the response model structure and JSON schema. Ensure the :gemini_key is configured. ```elixir iex> InstructorLite.instruct(%{ contents: [ %{ role: "user", parts: [%{text: "John Doe is fourty two years old"}] } ] }, response_model: %{name: :string, age: :integer}, json_schema: %{ type: "object", required: [:age, :name], properties: %{name: %{type: "string"}, age: %{type: "integer"}} }, adapter: InstructorLite.Adapters.Gemini, adapter_context: [ api_key: Application.fetch_env!(:instructor_lite, :gemini_key) ] ) {:ok, %{name: "John Doe", age: 42}} ``` -------------------------------- ### Instruct with Gemini Adapter Source: https://hexdocs.pm/instructor_lite/index.html Use InstructorLite.instruct/2 with the Gemini adapter. This example also shows how to provide a JSON schema directly for response validation. ```elixir iex> InstructorLite.instruct(%{ contents: [ %{ role: "user", parts: [%{text: "John Doe is forty-two years old"}] } ] }, response_model: UserInfo, json_schema: %{ type: "object", required: [:age, :name], properties: %{name: %{type: "string"}, age: %{type: "integer"}}, }, adapter: InstructorLite.Adapters.Gemini, adapter_context: [ api_key: Application.fetch_env!(:instructor_lite, :gemini_key) ] ) {:ok, %UserInfo{name: "John Doe", age: 42}} ``` -------------------------------- ### Example of validating a changeset with a custom LLM rule Source: https://hexdocs.pm/instructor_lite/migrating_from_instructor.html This example shows how to use the custom `changeset` function to validate an answer against a specific LLM rule, demonstrating the detailed error message returned. ```Elixir %QuestionAnswer{question: "What is the meaning of life?"} |> QuestionAnswer.changeset(%{answer: "Sex, drugs, and rock'n roll"}) ``` -------------------------------- ### Example of validating a changeset with a custom rule Source: https://hexdocs.pm/instructor_lite/migrating_from_instructor.html This example demonstrates how to cast and validate a changeset using the custom `validate_changeset` function, showing the resulting errors. ```Elixir %QuestionAnswer{} ``` -------------------------------- ### Instructor Chat Completion Call Source: https://hexdocs.pm/instructor_lite/migrating_from_instructor.html Example of calling Instructor's `chat_completion/2` function with parameters and response model. ```elixir Instructor.chat_completion(%{ model: "gpt-3.5-turbo", response_model: SpamPrediction, messages: [ %{role: "user", content: "Classify the following text: Hello, I am a Nigerian prince and I would like to give you $1,000,000."} ] }) {:ok, %SpamPrediction{class: :spam, score: 0.999}} ``` -------------------------------- ### Instructing Gemini for Structured Output Source: https://hexdocs.pm/instructor_lite/InstructorLite.Adapters.Gemini.html Example of using InstructorLite.instruct with the Gemini adapter to generate structured JSON output. Requires specifying the response model, JSON schema, adapter, and adapter context including the model and API key. ```elixir InstructorLite.instruct( %{contents: [%{role: "user", parts: [%{text: "John is 25yo"}]}]}, response_model: %{name: :string, age: :integer}, json_schema: %{ type: "object", required: [:age, :name], properties: %{name: %{type: "string"}, age: %{type: "integer"}} }, adapter: InstructorLite.Adapters.Gemini, adapter_context: [ model: "gemini-1.5-flash-8b", api_key: Application.fetch_env!(:instructor_lite, :gemini_key) ] ) {:ok, %{name: "John", age: 25}} ``` -------------------------------- ### InstructorLite Instruct Call Source: https://hexdocs.pm/instructor_lite/migrating_from_instructor.html Example of calling InstructorLite's `instruct/2` function, passing model, response model, adapter, and adapter context (including API key) via options. ```elixir InstructorLite.instruct(%{ input: [ %{role: "user", content: "Classify the following text: Hello, I am a Nigerian prince and I would like to give you $1,000,000."} ] , model: "gpt-4o-mini" }, response_model: SpamPrediction, adapter: InstructorLite.Adapters.OpenAI, adapter_context: [api_key: "my_secret_key"] ) {:ok, %SpamPrediction{class: :spam, score: 0.999}} ``` -------------------------------- ### Construct Retry Prompt Example Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html Shows how to call the custom `retry_prompt` function with sample data to generate a new prompt for retrying a model query after validation failure. ```elixir retry_prompt = OllamaAdapterRetryPrompt.retry_prompt(prompt, nil, errors, response, []) ``` -------------------------------- ### Example Batch API Results Source: https://hexdocs.pm/instructor_lite/batch-api.html Displays the expected output after processing the batch job, showing the classification, reason, and score for each email. ```elixir [ ok: %SpamPrediction{class: :spam, reason: "Typical scam offer from prince.", score: 0.95}, ok: %SpamPrediction{class: :spam, reason: "Suspicious webcam claim", score: 0.95}, ok: %SpamPrediction{ class: :not_spam, reason: "Newsletter content is not promotional", score: 0.85 } ] ``` -------------------------------- ### Using max_retries with InstructorLite Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Demonstrates how to use the `max_retries` option when calling `InstructorLite.instruct`. This example defines an embedded schema and makes an instruction call with a retry limit of 1. ```elixir defmodule Rhymes do use Ecto.Schema use InstructorLite.Instruction @primary_key false embedded_schema do field(:word, :string) field(:rhymes, {:array, :string}) end @impl true def validate_changeset(changeset, _opts) do Ecto.Changeset.validate_length(changeset, :rhymes, is: 3) end end InstructorLite.instruct(%{ input: [ %{role: "user", content: "Take the last word from the following line and add some rhymes to it Even though you broke my heart"} ] }, response_model: Rhymes, max_retries: 1, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :openai_key)] ) {:ok, %Rhymes{word: "heart", rhymes: ["part", "start", "dart"]}} ``` -------------------------------- ### Run Ollama Model via CLI Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html Example command to pull and run a specific model (deepseek-r1:8b) using the Ollama command-line interface. This demonstrates the basic interaction with Ollama. ```bash > ollama run deepseek-r1:8b pulling manifest pulling e6a7edc1a4d7: 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████▏ 5.2 GB pulling c5ad996bda6e: 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████▏ 556 B pulling 6e4c38e1172f: 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████▏ 1.1 KB pulling ed8474dc73db: 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████▏ 179 B pulling f64cd5418e4b: 100% ▕███████████████████████████████████████████████████████████████████████████████████████████████▏ 487 B verifying sha256 digest writing manifest success ``` -------------------------------- ### Example Retry Prompt Structure Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html Illustrates the structure of a prompt after incorporating retry logic, including the original message, a new user message with validation errors, and the system prompt. ```json { messages: [ %{ role: "system", content: "You're called by an Elixir application through the InstructorLite library. Your task is to understand what the application wants you to do and respond with JSON output that matches the schema. The output will be validated by the application against an Ecto schema and potentially some custom rules. You may be asked to adjust your response if it doesn't pass validation. " }, %{role: "user", content: "Who was the first president of the united states?"}, %{"content" => "{\n \"name\": \"George_Washington\"\n}\n\n ", "role" => "assistant"}, %{ role: "user", content: "The response did not pass validation. Please try again and fix the following validation errors:\n\nname - is invalid\n" } ], stream: false, format: %{ type: "object", title: "root", required: [:name], additionalProperties: false, properties: %{name: %{type: "string"}} }, model: "deepseek-r1:8b" } ``` -------------------------------- ### Implement CoinGuess Instruction with Validation Source: https://hexdocs.pm/instructor_lite/InstructorLite.Instruction.html This example demonstrates defining an Ecto embedded schema for a coin guessing game. It includes a custom `validate_changeset/2` callback that checks if the user's guess matches the target value provided in the options. ```elixir # Let's play a guessing game! defmodule CoinGuess do use Ecto.Schema use InstructorLite.Instruction @primary_key false embedded_schema do field(:guess, Ecto.Enum, values: [:heads, :tails]) end @impl InstructorLite.Instruction def validate_changeset(cs, opts) do target = Keyword.fetch!(opts, :extra) case Ecto.Changeset.fetch_field!(cs, :guess) do ^target -> cs _ -> Ecto.Changeset.add_error(cs, :guess, "Wrong! Try again") end end end ``` -------------------------------- ### Instruct with Chat Completions Compatible Adapter (Grok) Source: https://hexdocs.pm/instructor_lite/index.html Use InstructorLite.instruct/2 with the ChatCompletionsCompatible adapter for APIs like Grok that follow the OpenAI Chat Completions format. Provide the Grok API key and URL. ```elixir iex> InstructorLite.instruct(%{ model: "grok-3-latest", messages: [ %{role: "user", content: "John Doe is forty-two years old"} ] }, response_model: UserInfo, adapter: InstructorLite.Adapters.ChatCompletionsCompatible, adapter_context: [ url: "https://api.x.ai/v1/chat/completions", api_key: Application.fetch_env!(:instructor_lite, :grok_key) ] ) {:ok, %UserInfo{name: "John Doe", age: 42}} ``` -------------------------------- ### Instructor Schema Definition Source: https://hexdocs.pm/instructor_lite/migrating_from_instructor.html Example of defining an Ecto schema with Instructor using the `@doc` attribute for field descriptions and `Instructor.Validator` for validation. ```elixir defmodule SpamPrediction do use Ecto.Schema use Instructor.Validator @doc """ ## Field Descriptions: - class: Whether or not the email is spam. - reason: A short, less than 10 word rationalization for the classification. - score: A confidence score between 0.0 and 1.0 for the classification. """ @primary_key false embedded_schema do field(:class, Ecto.Enum, values: [:spam, :not_spam]) field(:reason, :string) field(:score, :float) end @impl true def validate_changeset(changeset) do changeset |> Ecto.Changeset.validate_number(:score, greater_than_or_equal_to: 0.0, less_than_or_equal_to: 1.0 ) end end ``` -------------------------------- ### Instruct with OpenAI Adapter Source: https://hexdocs.pm/instructor_lite/index.html Use InstructorLite.instruct/2 with the default OpenAI adapter to fill an Ecto schema from unstructured text. Ensure the OpenAI API key is configured. ```elixir iex> InstructorLite.instruct(%{ input: [ %{role: "user", content: "John Doe is forty-two years old"} ] }, response_model: UserInfo, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :openai_key)] ) {:ok, %UserInfo{name: "John Doe", age: 42}} ``` -------------------------------- ### Instruct with Gemini Adapter and JSON Schema Source: https://hexdocs.pm/instructor_lite/readme.html Use `InstructorLite.instruct/2` with the Gemini adapter, providing a `json_schema` for response validation. Ensure the Gemini API key is available. ```elixir iex> InstructorLite.instruct(%{ contents: [ %{ role: "user", parts: [%{text: "John Doe is forty-two years old"}] } ] }, response_model: UserInfo, json_schema: %{ type: "object", required: [:age, :name], properties: %{name: %{type: "string"}, age: %{type: "integer"}}, }, adapter: InstructorLite.Adapters.Gemini, adapter_context: [ api_key: Application.fetch_env!(:instructor_lite, :gemini_key) ] ) {:ok, %UserInfo{name: "John Doe", age: 42}} ``` -------------------------------- ### Instruct with Image Input Source: https://hexdocs.pm/instructor_lite/openai-advanced-features.html Uses InstructorLite to instruct the model with both text and image input, expecting a Product struct as a response. ```elixir file = Kino.FS.file_path("shopify-screenshot.png") |> File.read!() base64_image = "data:image/png;base64," <> Base.encode64(file) {:ok, result} = InstructorLite.instruct(%{ model: "gpt-4o-mini", input: [ %{ role: "user", content: [ %{type: "input_text", text: "What is the product details of the following image?"}, %{type: "input_image", image_url: base64_image} ]} ] }, response_model: Product, adapter_context: [api_key: secret_key] ) result ``` -------------------------------- ### InstructorLite Schema Definition Source: https://hexdocs.pm/instructor_lite/migrating_from_instructor.html Example of defining an Ecto schema with InstructorLite using the `@notes` attribute for field descriptions and `InstructorLite.Instruction` for validation. Note the `_opts` argument in `validate_changeset`. ```elixir defmodule SpamPrediction do use Ecto.Schema use InstructorLite.Instruction @notes """ ## Field Descriptions: - class: Whether or not the email is spam. - reason: A short, less than 10 word rationalization for the classification. - score: A confidence score between 0.0 and 1.0 for the classification. """ @primary_key false embedded_schema do field(:class, Ecto.Enum, values: [:spam, :not_spam]) field(:reason, :string) field(:score, :float) end @impl InstructorLite.Instruction def validate_changeset(changeset, _opts) do changeset |> Ecto.Changeset.validate_number(:score, greater_than_or_equal_to: 0.0, less_than_or_equal_to: 1.0 ) end end ``` -------------------------------- ### Implement Ollama Adapter initial_prompt Callback Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html Enriches the parameters with system messages and sets the JSON schema format for structured output. It defaults the model to 'deepseek-r1:8b' if not provided. ```elixir defmodule OllamaAdapterInitialPrompt do def initial_prompt(params, opts) do # This prompt will be a message with a "system" role sys_message = [ %{role: "system", content: InstructorLite.Prompt.prompt(opts)} ] params # This adapter might work with different models, # so let's put a default one but now insist on it |> Map.put_new(:model, "deepseek-r1:8b") |> Map.put(:stream, false) # The user has likely provided their own prompt, so we need to be nice and not overwrite it |> Map.update(:messages, sys_message, fn msgs -> sys_message ++ msgs end) |> Map.put(:format, Keyword.fetch!(opts, :json_schema)) end end ``` -------------------------------- ### Define SpamPrediction Instruction Source: https://hexdocs.pm/instructor_lite/InstructorLite.Instruction.html This example shows how to define an Ecto embedded schema as an Instruction for spam prediction. It includes field descriptions and a custom validation for the score field. ```elixir defmodule SpamPrediction do use Ecto.Schema use InstructorLite.Instruction @notes """ Field Descriptions: - class: Whether or not the email is spam. - reason: A short, less than 10-word rationalization for the classification. - score: A confidence score between 0.0 and 1.0 for the classification. """ @primary_key false embedded_schema do field(:class, Ecto.Enum, values: [:spam, :not_spam]) field(:reason, :string) field(:score, :float) end @impl InstructorLite.Instruction def validate_changeset(changeset, _opts) do Ecto.Changeset.validate_number(changeset, :score, greater_than_or_equal_to: 0.0, less_than_or_equal_to: 1.0 ) end end ``` -------------------------------- ### prepare_prompt/2 Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Prepare prompt that can be later sent to LLM. ```APIDOC ## prepare_prompt/2 ### Description Prepare prompt that can be later sent to LLM. ### Function Signature ```elixir prepare_prompt(params, opts) ``` ### Parameters #### `params` - Type: `InstructorLite.Adapter.params()` - Description: Adapter-specific map containing values eventually sent to the LLM. #### `opts` - Type: `opts()` - Description: Options passed to instructor functions. ### Return Value - The return type is not explicitly defined in the source, but it is expected to return a prepared prompt. ### Examples ```elixir # Example usage would go here, but is not provided in the source text. ``` ``` -------------------------------- ### Instruct with Web Search Tool Source: https://hexdocs.pm/instructor_lite/openai-advanced-features.html Utilizes InstructorLite to instruct the model with a web search tool to find information about the InstructorLite Hex package. ```elixir {:ok, result} = InstructorLite.instruct(%{ model: "gpt-4o-mini", tools: [%{type: "web_search_preview"}], input: "We want to know about: InstructorLite Hex package" }, response_model: Package, adapter_context: [api_key: secret_key] ) result ``` -------------------------------- ### instruct Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Performs a full instruction session, including prompt sending, response consumption, and retries. ```APIDOC ## instruct ### Description Performs an instruction session from start to finish, gluing together prompt sending, response consumption, and adding retries on top. It supports various adapters and response models. ### Method `InstructorLite.instruct/2` ### Parameters - `params` (InstructorLite.Adapter.params()) - Parameters for the instruction, including input messages. - `opts` (keyword list) - Options, including `response_model`, `adapter`, `adapter_context`, and `json_schema`. ### Request Example ```elixir InstructorLite.instruct( %{input: [%{role: "user", content: "John Doe is fourty two years old"}]} response_model: %{name: :string, age: :integer}, adapter: InstructorLite.Adapters.OpenAI, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :openai_key)] ) ``` ### Response - `{:ok, Ecto.Schema.t()}` - The successfully parsed and structured response. - `{:error, Ecto.Changeset.t()}` - An error occurred, returning an invalid changeset. - `{:error, any()}` - Other errors. ``` -------------------------------- ### Ollama Adapter initial_prompt Compilation Info Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html Compilation information for the OllamaAdapterInitialPrompt module. ```elixir {:module, OllamaAdapterInitialPrompt, <<70, 79, 82, 49, 0, 0, 9, ...>>, {:initial_prompt, 2}} ``` -------------------------------- ### Instruct with Anthropic Adapter Source: https://hexdocs.pm/instructor_lite/index.html Use InstructorLite.instruct/2 with the Anthropic adapter to fill an Ecto schema. Specify the adapter and provide the Anthropic API key. ```elixir iex> InstructorLite.instruct(%{ messages: [ %{role: "user", content: "John Doe is forty-two years old"} ] }, response_model: UserInfo, adapter: InstructorLite.Adapters.Anthropic, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :anthropic_key)] ) {:ok, %UserInfo{name: "John Doe", age: 42}} ``` -------------------------------- ### Prepare Prompt Function Signature Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Shows the type specification for the `prepare_prompt` function in InstructorLite. This function is used to prepare prompts for LLM interaction. ```elixir @spec prepare_prompt(InstructorLite.Adapter.params(), opts()) :: InstructorLite.Adapter.params() ``` -------------------------------- ### Prepare and Submit Batch Job Source: https://hexdocs.pm/instructor_lite/batch-api.html Prepare prompts for batch processing, format them into a JSONL file, and submit to OpenAI using Req and Multipart. This includes uploading the file and creating the batch job. ```elixir opts = [ response_model: SpamPrediction, adapter: InstructorLite.Adapters.OpenAI ] prompts = [ "Hello I am a Nigerian prince and I would like to send you money", "Hello I know we never met but I got access to your webcam and have some spicy footage", "Elixir Radar Newsletter. Issue #420" ] |> Enum.map(fn text -> InstructorLite.prepare_prompt(%{ model: "gpt-4o-mini", input: [%{ role: "user", content: "Classify first paragraph of an email:\n#{text}" }] }, opts ) end) |> Enum.with_index() jsonl = prompts |> Enum.map(fn {prompt, index} -> Jason.encode!(%{custom_id: "#{index}", method: "POST", url: "/v1/responses", body: prompt}) end) |> Enum.join("\n") multipart = Multipart.new() |> Multipart.add_part(Multipart.Part.text_field("batch", "purpose")) |> Multipart.add_part( Multipart.Part.file_content_field("emails.jsonl", jsonl, :file, filename: "emails.jsonl") ) auth_headers = [{"Authorization", "Bearer #{secret_key}"}] mp_headers = [{"Content-Type", Multipart.content_type(multipart, "multipart/form-data")}] {:ok, %{body: %{"id" => file_id}}} = Req.post("https://api.openai.com/v1/files", headers: auth_headers ++ mp_headers, body: Multipart.body_binary(multipart) ) {:ok, %{body: %{"id" => batch_id}}} = Req.post("https://api.openai.com/v1/batches", json: %{input_file_id: file_id, endpoint: "/v1/responses", completion_window: "24h"}, headers: auth_headers ) :ok ``` -------------------------------- ### Adapter initial_prompt Callback Source: https://hexdocs.pm/instructor_lite/InstructorLite.Adapter.html Callback to update parameters with the model-specific prompt before the initial request. ```elixir @callback initial_prompt(params(), InstructorLite.opts()) :: params() ``` -------------------------------- ### Extract Product Details from Image Source: https://hexdocs.pm/instructor_lite/vision.html Extract structured product details (name, price, currency, color) from a product screenshot using Instructor Lite and the Anthropic adapter. The image is base64 encoded and sent as part of the prompt. ```elixir image = Kino.FS.file_path("shopify-screenshot.png") |> File.read!() base64_image = Base.encode64(image) defmodule Product do use Ecto.Schema @primary_key false embedded_schema do field(:name, :string) field(:price, :decimal) field(:currency, Ecto.Enum, values: [:usd, :gbp, :eur, :cny]) field(:color, :string) end end {:ok, result} = InstructorLite.instruct(%{ messages: [ %{role: "user", content: [ %{type: "text", text: "What is the product details of the following image?"}, %{type: "image", source: %{data: base64_image, type: "base64", media_type: "image/png"}} ]} ] }, adapter: InstructorLite.Adapters.Anthropic, response_model: Product, adapter_context: [api_key: secret_key] ) result ``` -------------------------------- ### ask Source: https://hexdocs.pm/instructor_lite/InstructorLite.html Sends a prompt to an AI model and returns the response. Supports multiple adapters like OpenAI, Anthropic, and Gemini. ```APIDOC ## ask ### Description Sends a prompt to an AI model and returns the response. Supports multiple adapters like OpenAI, Anthropic, and Gemini. ### Method `InstructorLite.ask/2` ### Parameters - `params` (map) - Parameters for the AI model request, including model name and input messages. - `opts` (keyword list) - Options for the adapter, such as the adapter module and adapter context (e.g., API key). ### Request Example ```elixir InstructorLite.ask( %{model: "gpt-5-mini-2025-08-07", input: [%{role: "user", content: "Cite me the greatest opening line in the history of cyberpunk."}]} adapter: InstructorLite.Adapters.OpenAI, adapter_context: [api_key: Application.fetch_env!(:instructor_lite, :openai_key)] ) ``` ### Response #### Success Response - `{:ok, response_body}` - The AI model's response. #### Error Response - `{:error, reason}` - An error occurred during the request. ``` -------------------------------- ### Run OpenAI Integration Tests Source: https://hexdocs.pm/instructor_lite/local_development_guide.html Executes the integration tests specifically for the OpenAI adapter. This requires your OpenAI API key to be configured in `config/config.exs`. ```bash mix test test/integrations/openai_test.exs ``` -------------------------------- ### Complete Ollama Adapter Module Source: https://hexdocs.pm/instructor_lite/custom-ollama-adapter.html A comprehensive Elixir module implementing the `InstructorLite.Adapter` behavior for Ollama. It includes callbacks for sending requests, setting initial prompts, parsing responses, finding output, and handling retries. ```Elixir defmodule OllamaAdapter do @behaviour InstructorLite.Adapter @impl InstructorLite.Adapter def send_request(params, options) do url = options |> Keyword.get(:adapter_context, []) |> Keyword.fetch!(:url) case Req.post(url, json: params, receive_timeout: 120_000) do {:ok, %{status: 200, body: body}} -> {:ok, body} {:ok, response} -> {:error, response} {:error, reason} -> {:error, reason} end end @impl InstructorLite.Adapter def initial_prompt(params, opts) do sys_message = [ %{role: "system", content: InstructorLite.Prompt.prompt(opts)} ] params |> Map.put_new(:model, "deepseek-r1:8b") |> Map.put(:stream, false) |> Map.update(:messages, sys_message, fn msgs -> sys_message ++ msgs end) |> Map.put(:format, Keyword.fetch!(opts, :json_schema)) end @impl InstructorLite.Adapter def parse_response(response, opts) do with {:ok, json} <- find_output(response, opts) do InstructorLite.JSON.decode(json) end end @impl InstructorLite.Adapter def find_output(response, _opts) do case response do %{"message" => %{"content" => output}} -> {:ok, output} other -> {:error, :unexpected_response, other} end end @impl InstructorLite.Adapter def retry_prompt(params, _resp_params, errors, response, _opts) do message = Map.fetch!(response, "message") do_better = [ message, %{role: "user", content: InstructorLite.Prompt.validation_failed(errors)} ] Map.update(params, :messages, do_better, fn msgs -> msgs ++ do_better end) end end ``` -------------------------------- ### Extract Toponyms with Reasoning Source: https://hexdocs.pm/instructor_lite/openai-advanced-features.html Demonstrates how to use lower-level InstructorLite functions to access reasoning and structured output, extracting toponyms from an adventure description. ```elixir require Logger adventure_description = """ Something strange is happening to your hometown of Willowshore! Nestled on the banks of a river winding through the legendary Specterwood in Tian Xia’s haunted land of Shenmen, the people of Willowshore are no strangers to supernatural threat, but the danger that comes to town on the first day of summer is unlike anything you’ve ever seen before. Over the four seasons to come, you and your fellow home-grown heroes must face evil spirits, sinister fiends, and frightening curses, lest the town of Willowshore succumb to the Season of Ghosts! " opts = [ response_model: %{toponyms: {:array, :string}}, adapter_context: [api_key: secret_key] ] params = InstructorLite.prepare_prompt(%{ model: "o4-mini", reasoning: %{effort: "medium", summary: "auto"}, input: [ %{role: "system", content: "Here's an adventure description, please extract all toponyms"}, %{role: "user", content: adventure_description} ] }, opts) {:ok, response} = InstructorLite.Adapters.OpenAI.send_request(params, opts) {:ok, result} = InstructorLite.consume_response(response, params, opts) for %{"summary" => summaries} <- response["output"] do for %{"type" => "summary_text", "text" => text} <- summaries do Logger.info(text) end end result ``` -------------------------------- ### Add InstructorLite Dependency Source: https://hexdocs.pm/instructor_lite/index.html Add the InstructorLite library to your project's dependencies in `mix.exs`. ```elixir def deps do [ {:instructor_lite, "~> 1.2.0"} ] end ``` -------------------------------- ### Adapter find_output Callback Source: https://hexdocs.pm/instructor_lite/InstructorLite.Adapter.html Optional callback to find text output in a response, assuming a simple plain text format. Used in InstructorLite.ask/2. ```elixir @callback find_output(response(), InstructorLite.opts()) :: {:ok, String.t()} | {:error, any()} | {:error, reason :: atom(), any()} ```