Packages
langchain
0.8.13
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/modes/until_success.ex
defmodule LangChain.Chains.LLMChain.Modes.UntilSuccess do
@moduledoc """
Execution mode that loops until a successful result.
Calls the LLM, executes tool calls, and repeats until:
- The last message is an assistant response (success)
- The last message is a tool result with no errors (success)
- Max retry count is exceeded (error)
## Options
- `:force_recurse` — When `true`, forces recursion even after a successful
result. Used internally by `UntilToolUsed` mode. Default: `false`.
## Usage
LLMChain.run(chain, mode: :until_success)
"""
@behaviour LangChain.Chains.LLMChain.Mode
alias LangChain.Chains.LLMChain
alias LangChain.Message
alias LangChain.LangChainError
@impl true
def run(%LLMChain{last_message: %Message{} = last_message} = chain, opts) do
force_recurse = Keyword.get(opts, :force_recurse, false)
stop_or_recurse =
cond do
force_recurse ->
:recurse
chain.current_failure_count >= chain.max_retry_count ->
{:error, chain,
LangChainError.exception(
type: "exceeded_failure_count",
message: "Exceeded max failure count"
)}
last_message.role == :tool && !Message.tool_had_errors?(last_message) ->
{:ok, chain}
last_message.role == :assistant ->
{:ok, chain}
true ->
:recurse
end
case stop_or_recurse do
:recurse ->
case LLMChain.execute_step(chain) do
{:ok, updated_chain} ->
updated_chain
|> LLMChain.execute_tool_calls()
|> run(opts)
{:error, _chain, _reason} = error ->
error
end
other ->
other
end
end
# Initial call when no messages have been processed yet
def run(%LLMChain{} = chain, opts) do
case LLMChain.execute_step(chain) do
{:ok, updated_chain} ->
updated_chain
|> LLMChain.execute_tool_calls()
|> run(opts)
{:error, _chain, _reason} = error ->
error
end
end
end