Packages

LlmEx - A flexible client for interacting with various LLM providers.

Current section

Files

Jump to
llm_ex lib llm_ex.ex
Raw

lib/llm_ex.ex

defmodule LlmEx do
@moduledoc """
LlmEx is a flexible client for interacting with various LLM providers.
This library provides a unified API for working with different LLM services,
including local models via Ollama and cloud services like Anthropic.
## Getting Started
Add LlmEx to your dependencies in mix.exs:
```elixir
def deps do
[
{:llm_ex, "~> 0.1.0"}
]
end
```
Configure your provider API keys (if needed) in your config.exs:
```elixir
config :llm_ex,
anthropic_api_key: System.get_env("ANTHROPIC_API_KEY")
```
## Usage
Create a client module and specify the provider:
```elixir
defmodule MyApp.LlmClient do
use LlmEx.Client, provider: LlmEx.Providers.OllamaClient
def get_knowledge do
with_tool(MyTool)
|> with_prompt("What do you know about Elixir?")
|> stream()
end
end
```
Process the streaming response:
```elixir
def handle_info({:llm_response, _id, content}, socket) do
# Handle the response content
{:noreply, socket}
end
```
"""
@doc """
Creates a new client with the specified provider.
## Parameters
* `provider` - The LLM provider module to use
* `opts` - Additional configuration options
## Examples
iex> client = LlmEx.client(LlmEx.Providers.OllamaClient)
iex> is_map(client)
true
iex> client.provider == LlmEx.Providers.OllamaClient
true
"""
def client(provider, opts \\ []) do
%{
provider: provider,
tools: [],
prompt: nil,
system: "",
messages: [],
options: opts
}
end
@doc """
Adds a tool to the client configuration.
## Parameters
* `client` - The client configuration
* `tool` - The tool to add
## Examples
iex> client = LlmEx.client(LlmEx.Providers.OllamaClient)
iex> result = LlmEx.with_tool(client, :test_tool)
iex> result.tools
[:test_tool]
"""
def with_tool(client, tool) do
Map.update(client, :tools, [tool], fn tools -> [tool | tools] end)
end
@doc """
Sets the prompt for the client.
## Parameters
* `client` - The client configuration
* `prompt` - The prompt text
## Examples
iex> client = LlmEx.client(LlmEx.Providers.OllamaClient)
iex> result = LlmEx.with_prompt(client, "What is Elixir?")
iex> result.prompt
"What is Elixir?"
"""
def with_prompt(client, prompt) when is_binary(prompt) do
Map.put(client, :prompt, prompt)
end
@doc """
Sets the system message for the client.
## Parameters
* `client` - The client configuration
* `system` - The system message text
## Examples
iex> client = LlmEx.client(LlmEx.Providers.OllamaClient)
iex> result = LlmEx.with_system(client, "You are a helpful assistant.")
iex> result.system
"You are a helpful assistant."
"""
def with_system(client, system) when is_binary(system) do
Map.put(client, :system, system)
end
@doc """
Adds a message to the conversation history.
## Parameters
* `client` - The client configuration
* `message` - The message to add
## Examples
iex> client = LlmEx.client(LlmEx.Providers.OllamaClient)
iex> message = %LlmEx.Types.Message{role: :user, content: "Hello"}
iex> result = LlmEx.with_message(client, message)
iex> length(result.messages)
1
"""
def with_message(client, message) do
Map.update(client, :messages, [message], fn messages -> messages ++ [message] end)
end
@doc """
Streams the response from the LLM provider.
## Parameters
* `client` - The client configuration
## Examples
iex> client = LlmEx.client(LlmEx.Providers.OllamaClient) |> LlmEx.with_prompt("Hello")
iex> # Function will call provider.stream_chat which returns :ok
iex> # This is just a mock example for doctest
iex> client.provider != nil
true
"""
def stream(client) do
alias LlmEx.Types.Message
# Initialize message list if needed
messages =
if client.messages == [] and client.prompt do
[%Message{role: :user, content: client.prompt}]
else
client.messages
end
# Start streaming with provided options and tools
message_id = "msg_#{System.unique_integer() |> abs()}"
opts =
[
tools: client.tools,
system: client.system
] ++ client.options
provider = client.provider
provider.stream_chat(messages, message_id, self(), opts)
end
end