Packages
langchain
0.6.0
0.9.2
0.9.1
0.9.0
0.8.14
0.8.13
0.8.12
0.8.11
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.4.0-rc.3
0.4.0-rc.2
0.4.0-rc.1
0.4.0-rc.0
0.3.3
0.3.2
0.3.1
0.3.0
0.3.0-rc.2
0.3.0-rc.1
0.3.0-rc.0
0.2.0
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Elixir implementation of a LangChain style framework that lets Elixir projects integrate with and leverage LLMs.
Current section
Files
Jump to
Current section
Files
lib/chains/llm_chain/mode.ex
defmodule LangChain.Chains.LLMChain.Mode do
@moduledoc """
Behaviour for LLMChain execution modes.
A mode controls the execution loop of an LLMChain - how many times the LLM
is called, when tools are executed, and under what conditions the loop
terminates.
## Built-in Modes
- `LangChain.Chains.LLMChain.Modes.WhileNeedsResponse` - loop while `needs_response` is true
- `LangChain.Chains.LLMChain.Modes.UntilSuccess` - loop until successful tool execution or assistant response
- `LangChain.Chains.LLMChain.Modes.Step` - single step with optional continuation
- `LangChain.Chains.LLMChain.Modes.UntilToolUsed` - loop until a specific tool is called
## Custom Modes
Implement this behaviour to define custom execution loops. The simplest
approach is to import `LangChain.Chains.LLMChain.Mode.Steps` and compose
the provided step functions into a pipeline. Each step follows a consistent
contract:
- `{:continue, chain}` - keep processing, pipe into the next step
- Any other tuple (`:ok`, `:pause`, `:error`) — terminal result, passed through unchanged
This means a pipeline short-circuits automatically when any step returns a
terminal value.
### Minimal Example
defmodule MyApp.Modes.Custom do
@behaviour LangChain.Chains.LLMChain.Mode
@impl true
def run(chain, opts) do
case LLMChain.execute_step(chain) do
{:ok, updated} ->
updated = LLMChain.execute_tool_calls(updated)
if updated.needs_response, do: run(updated, opts), else: {:ok, updated}
error -> error
end
end
end
### Composable Example Using Steps
The built-in modes are all composed from `Steps` functions. You can do the
same to build a mode that adds custom logic at any point in the pipeline.
For example, a mode that loops like `WhileNeedsResponse` but adds a custom
check after each tool execution round:
defmodule MyApp.Modes.WithAudit do
@behaviour LangChain.Chains.LLMChain.Mode
import LangChain.Chains.LLMChain.Mode.Steps
@impl true
def run(chain, opts) do
chain = ensure_mode_state(chain)
{:continue, chain}
|> execute_tools()
|> call_llm()
|> check_max_runs(opts)
|> audit_step(opts)
|> continue_or_done(&run/2, opts)
end
# A custom step - same contract as the built-in steps:
# accept {:continue, chain} and return {:continue, chain} or a terminal.
defp audit_step({:continue, chain}, _opts) do
run_count = get_run_count(chain)
Logger.info("LLM call #\#{run_count} completed")
{:continue, chain}
end
defp audit_step(terminal, _opts), do: terminal
end
The pattern is always the same: start with `{:continue, chain}`, pipe
through as many steps as needed, and end with `continue_or_done/3` to
decide whether to loop.
See `LangChain.Chains.LLMChain.Mode.Steps` for the full list of available
step functions. The built-in modes (`WhileNeedsResponse`, `UntilSuccess`,
`Step`, `UntilToolUsed`) also serve as practical examples to reference.
## Return Types
- `{:ok, chain}` - normal completion
- `{:ok, chain, extra}` - completion with additional data
- `{:pause, chain}` - execution paused at a clean checkpoint; resumable
- `{:error, chain, reason}` - execution failed
"""
alias LangChain.Chains.LLMChain
alias LangChain.LangChainError
@type run_result ::
{:ok, LLMChain.t()}
| {:ok, LLMChain.t(), term()}
| {:pause, LLMChain.t()}
| {:error, LLMChain.t(), LangChainError.t()}
@doc """
Execute the chain according to this mode's logic.
The `opts` keyword list contains all options passed to `LLMChain.run/2`,
allowing modes to define their own options.
"""
@callback run(chain :: LLMChain.t(), opts :: Keyword.t()) :: run_result()
end