Packages
nous
0.12.12
0.17.0
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.17
0.12.16
0.12.15
0.12.14
0.12.13
0.12.12
0.12.11
0.12.9
0.12.7
0.12.6
0.12.5
0.12.3
0.12.2
0.12.0
0.11.3
0.11.0
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.5.0
AI agent framework for Elixir with multi-provider LLM support
Current section
Files
Jump to
Current section
Files
lib/nous/memory/embedding/openai.ex
defmodule Nous.Memory.Embedding.OpenAI do
@moduledoc """
OpenAI embedding provider.
Uses text-embedding-3-small by default. Configurable model and base_url.
## Options
* `:api_key` - OpenAI API key (required, or set OPENAI_API_KEY env var)
* `:model` - Model name (default: "text-embedding-3-small")
* `:base_url` - API base URL (default: "https://api.openai.com/v1")
"""
@behaviour Nous.Memory.Embedding
@default_model "text-embedding-3-small"
@default_base_url "https://api.openai.com/v1"
@default_dimension 1536
@impl true
def embed(text, opts \\ []) do
api_key = opts[:api_key] || System.get_env("OPENAI_API_KEY")
model = opts[:model] || @default_model
base_url = opts[:base_url] || @default_base_url
unless api_key do
{:error, "OpenAI API key required. Set :api_key option or OPENAI_API_KEY env var."}
else
url = "#{base_url}/embeddings"
body = %{
input: text,
model: model
}
headers = [
{"authorization", "Bearer #{api_key}"},
{"content-type", "application/json"}
]
case Req.post(url, json: body, headers: headers) do
{:ok, %Req.Response{status: 200, body: %{"data" => [%{"embedding" => embedding} | _]}}} ->
{:ok, embedding}
{:ok, %Req.Response{status: status, body: body}} ->
{:error, %{status: status, body: body}}
{:error, reason} ->
{:error, reason}
end
end
end
@impl true
def embed_batch(texts, opts \\ []) do
api_key = opts[:api_key] || System.get_env("OPENAI_API_KEY")
model = opts[:model] || @default_model
base_url = opts[:base_url] || @default_base_url
unless api_key do
{:error, "OpenAI API key required. Set :api_key option or OPENAI_API_KEY env var."}
else
url = "#{base_url}/embeddings"
body = %{
input: texts,
model: model
}
headers = [
{"authorization", "Bearer #{api_key}"},
{"content-type", "application/json"}
]
case Req.post(url, json: body, headers: headers) do
{:ok, %Req.Response{status: 200, body: %{"data" => data}}} ->
embeddings =
data
|> Enum.sort_by(& &1["index"])
|> Enum.map(& &1["embedding"])
{:ok, embeddings}
{:ok, %Req.Response{status: status, body: body}} ->
{:error, %{status: status, body: body}}
{:error, reason} ->
{:error, reason}
end
end
end
@impl true
def dimension, do: @default_dimension
end