### Instructor Chat Completion with Response Model Source: https://github.com/thmsmlr/instructor_ex/blob/main/pages/philosophy.md Example of using Instructor to get a structured response from an LLM, specifying the desired output schema (Recipe). This demonstrates Instructor's core functionality of bridging LLMs and structured data. ```elixir Instructor.chat_completion( model: "gpt-4o-mini", response_model: Recipe, messages: [ %{ role: "user", content: "Give me a recipe for a banana smoothie" } ] ) # => {:ok, %Recipe{title: "Banana smoothie", cook_time: 15, steps: [...]} ``` -------------------------------- ### Configure Instructor Default Adapter Source: https://github.com/thmsmlr/instructor_ex/blob/main/CLAUDE.md Sets the default LLM adapter for the Instructor library. Ensure the specified adapter module exists and is correctly configured. ```elixir config :instructor, adapter: Instructor.Adapters.OpenAI # default ``` -------------------------------- ### Add Instructor Dependency Source: https://github.com/thmsmlr/instructor_ex/blob/main/README.md Add the Instructor library to your project's dependencies in `mix.exs`. ```elixir def deps do [ {:instructor, "~> 0.1.0"} ] end ``` -------------------------------- ### Configure Instructor LLMCPP Adapter Source: https://github.com/thmsmlr/instructor_ex/blob/main/CLAUDE.md Provides specific configuration for the LLMCPP adapter, including the chat template and API URL. This allows customization for specific LLMCPP deployments. ```elixir config :instructor, :llamacpp, chat_template: :mistral_instruct, api_url: "http://localhost:8080/completion" ``` -------------------------------- ### API Key Authentication Configuration for Azure OpenAI Source: https://github.com/thmsmlr/instructor_ex/blob/main/pages/llm-providers/azure-openai.md Configures Instructor to use API key authentication for Azure OpenAI. Ensure the API key is set as an environment variable. ```elixir config: [ instructor: [ adapter: Instructor.Adapters.OpenAI, openai: [ auth_mode: :api_key_header, api_key: System.get_env("LB_AZURE_OPENAI_API_KEY"), # e.g. "c3829729deadbeef382938acdfee2987" api_url: azure_openai_endpoint, api_path:azure_openai_api_path ] ] ] ``` -------------------------------- ### LLM Responding with Text Source: https://github.com/thmsmlr/instructor_ex/blob/main/pages/philosophy.md Demonstrates a basic interaction where an LLM generates a text response to a prompt. This highlights the challenge of parsing unstructured text output from LLMs in Software 1.0. ```text llm("Recipe for a banana smoothie") -> """ A banana smoothie is a delicious and nutritious treat that's quite easy to make. Here's a simple recipe for you: Ingredients: 2 ripe bananas 1 cup milk (you can use almond, soy, or cow's milk) 1/2 cup Greek yogurt (optional, for extra creaminess) 1-2 tablespoons honey or maple syrup (adjust according to taste) A pinch of cinnamon (optional) Ice cubes (optional, for a colder smoothie) Instructions: Peel the bananas and place them in a blender. Add the milk, Greek yogurt (if using), honey/maple syrup, and cinnamon. Add a few ice cubes if you prefer a colder smoothie. Blend until smooth and creamy. If the smoothie is too thick, you can add a little more milk to reach your desired consistency. Taste and adjust the sweetness if necessary. Pour into glasses and serve immediately. Enjoy your banana smoothie! """ ``` -------------------------------- ### Instructor Interaction Flow Source: https://github.com/thmsmlr/instructor_ex/blob/main/pages/philosophy.md Illustrates the basic interaction flow between user, instructor, and code. This pattern can be applied in various contexts where Ecto is utilized. ```text user -> instructor -> code code -> instructor -> code code -> instructor -> user ``` -------------------------------- ### Call Instructor for Chat Completion Source: https://github.com/thmsmlr/instructor_ex/blob/main/README.md Use `Instructor.chat_completion/1` to send a prompt to an LLM and receive structured output matching the `response_model`. Supports `max_retries` for automatic validation error correction. ```elixir is_spam? = fn text -> Instructor.chat_completion( model: "gpt-4o-mini", response_model: SpamPrediction, max_retries: 3, messages: [ %{ role: "user", content: """ Your purpose is to classify customer support emails as either spam or not. This is for a clothing retail business. They sell all types of clothing. Classify the following email: #{text} " } ] ) end is_spam?.("Hello I am a Nigerian prince and I would like to send you money") # => {:ok, %SpamPrediction{class: :spam, reason: "Nigerian prince email scam", score: 0.98}} ``` -------------------------------- ### Azure OpenAI Endpoint and Deployment Configuration Source: https://github.com/thmsmlr/instructor_ex/blob/main/pages/llm-providers/azure-openai.md Defines the necessary variables for connecting to Azure OpenAI, including the endpoint, deployment name, and API path. ```elixir azure_openai_endpoint = "https://contoso.openai.azure.com" azure_openai_deployment_name = "contosodeployment123" azure_openai_api_path = "/openai/deployments/#{azure_openai_deployment_name}/chat/completions?api-version=2024-02-01" ``` -------------------------------- ### Define Ecto Schema with LLM Documentation Source: https://github.com/thmsmlr/instructor_ex/blob/main/CLAUDE.md Defines an Ecto schema with integrated LLM documentation and validation. Use `@llm_doc` for LLM instructions and `validate_changeset/1` for custom validation logic. ```elixir defmodule YourSchema do use Ecto.Schema use Instructor.Validator @llm_doc """ Description for the LLM explaining this schema """ embedded_schema do field(:field_name, :type) end @impl true def validate_changeset(changeset) do # Custom validation logic end end ``` -------------------------------- ### Configure Release to Preserve Documentation Source: https://github.com/thmsmlr/instructor_ex/blob/main/CLAUDE.md Configures Elixir releases to preserve documentation artifacts, specifically within a directory named 'Docs'. This is useful for generating or including documentation in production builds. ```elixir releases: myapp: strip_beams: [keep: ["Docs"]] ``` -------------------------------- ### Ecto Schema Definition Source: https://github.com/thmsmlr/instructor_ex/blob/main/pages/philosophy.md Defines an Ecto embedded schema for a recipe, including fields for title, cook time, steps, and ingredients. This schema serves as the target structure for LLM output. ```elixir defmodule Recipe do use Ecto.Schema @doc """ Our AI generated delicious recipe. """ @primary_key false embedded_schema do field :title, :string field :cook_time, :integer field :steps, {:array, :string} embeds_many :ingredients, Ingredients, primary_key: false do field :name, :string field :quantity, :decimal field :unit, :string end end end ``` -------------------------------- ### Microsoft Entra ID Authentication Configuration for Azure OpenAI Source: https://github.com/thmsmlr/instructor_ex/blob/main/pages/llm-providers/azure-openai.md Configures Instructor to use Microsoft Entra ID (Bearer token) authentication for Azure OpenAI. It utilizes a dynamic function to fetch the latest access token. ```elixir config: [ instructor: [ adapter: Instructor.Adapters.OpenAI, openai: [ auth_mode: :bearer, api_key: AzureServicePrincipalTokenRefresher.get_token_func!( System.get_env("LB_AZURE_ENTRA_TENANT_ID"), # e.g. "contoso.onmicrosoft.com" System.get_env("LB_AZURE_OPENAI_CLIENT_ID"), # e.g. "deadbeef-0000-4f13-afa9-c8a1e4087f97" System.get_env("LB_AZURE_OPENAI_CLIENT_SECRET"), # e.g. "mEf8Q~.e2e8URInwinsermNe8wDewsedRitsen.."}, "https://cognitiveservices.azure.com/.default" ), api_url: azure_openai_endpoint, api_path: azure_openai_api_path ] ] ] ``` -------------------------------- ### Azure Service Principal Token Refresher GenServer Source: https://github.com/thmsmlr/instructor_ex/blob/main/pages/llm-providers/azure-openai.md A GenServer to manage and refresh Microsoft Entra ID access tokens for Azure OpenAI. It continuously fetches the latest token using service principal credentials. ```elixir defmodule AzureServicePrincipalTokenRefresher do use GenServer @derive {Inspect, only: [:tenant_id, :client_id, :scope, :error], except: [:client_secret, :access_token]} @enforce_keys [:tenant_id, :client_id, :client_secret, :scope] defstruct [:tenant_id, :client_id, :client_secret, :scope, :access_token, :error] def get_token_func!(tenant_id, client_id, client_secret, scope) do {:ok, pid} = __MODULE__.start_link(tenant_id, client_id, client_secret, scope) fn -> case __MODULE__.get_access_token(pid) do {:ok, access_token} -> access_token {:error, error} -> raise "Could not fetch Microsoft Entra ID token: #{inspect(error)}" end end end def start_link(tenant_id, client_id, client_secret, scope) do GenServer.start_link(__MODULE__, %__MODULE__{ tenant_id: tenant_id, client_id: client_id, client_secret: client_secret, scope: scope }) end def get_access_token(pid) do GenServer.call(pid, :get_access_token) end @impl GenServer def init(%__MODULE__{} = state) do {:ok, state, {:continue, :fetch_token}} end @impl GenServer def handle_call(:get_access_token, _from, %__MODULE__{} = state) do case state do %__MODULE__{access_token: access_token, error: nil} -> {:reply, {:ok, access_token}, state} %__MODULE__{access_token: nil, error: error} -> {:reply, {:error, error}, state} end end @impl GenServer def handle_continue(:fetch_token, %__MODULE__{} = state) do {:noreply, fetch_token(state)} end @impl GenServer def handle_info(:refresh_token, %__MODULE__{} = state) do {:noreply, fetch_token(state)} end defp fetch_token(%__MODULE__{} = state) do %__MODULE__{ tenant_id: tenant_id, client_id: client_id, client_secret: client_secret, scope: scope } = state case Req.post( url: "https://login.microsoftonline.com/#{tenant_id}/oauth2/v2.0/token", form: [ grant_type: "client_credentials", scope: scope, client_id: client_id, client_secret: client_secret ] ) do {:ok, %Req.Response{ status: 200, body: %{ "access_token" => access_token, "expires_in" => expires_in } }} -> fetch_new_token_timeout = to_timeout(%Duration{second: expires_in - 60}) Process.send_after(self(), :refresh_token, fetch_new_token_timeout) %__MODULE__{state | access_token: access_token, error: nil} {:ok, response} -> %__MODULE__{state | access_token: nil, error: response} {:error, error} -> %__MODULE__{state | access_token: nil, error: error} end end end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.