Skip to content

Commit

Permalink
Convert to use mimic for mocking calls (#155)
Browse files Browse the repository at this point in the history
* use mimic for stubbing ChatOpenAI code
- updated LLMChain tests
- removed special test handling code from ChatOpenAI
- setup test helper

* more migration to Mimic
- removed production test code from ChatBumblebee
- removed from ChatMistral
- removed from ChatAnthropic
- removed from OpenAIImage
- removed LangChain.Utils.ApiOverride
- migrated more tests to use mimic
  - TextToTitleChain tests
  - RoutingChain tests
  - ChatBumblebee tests
  • Loading branch information
brainlid authored Jul 17, 2024
1 parent 17b1910 commit 0d2dc6a
Show file tree
Hide file tree
Showing 15 changed files with 153 additions and 294 deletions.
44 changes: 11 additions & 33 deletions lib/chat_models/chat_anthropic.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ defmodule LangChain.ChatModels.ChatAnthropic do
use Ecto.Schema
require Logger
import Ecto.Changeset
import LangChain.Utils.ApiOverride
alias __MODULE__
alias LangChain.Config
alias LangChain.ChatModels.ChatModel
Expand Down Expand Up @@ -259,40 +258,19 @@ defmodule LangChain.ChatModels.ChatAnthropic do
call(anthropic, messages, functions)
end

def call(%ChatAnthropic{} = anthropic, messages, functions)
when is_list(messages) do
if override_api_return?() do
Logger.warning("Found override API response. Will not make live API call.")
def call(%ChatAnthropic{} = anthropic, messages, functions) when is_list(messages) do
try do
# make base api request and perform high-level success/failure checks
case do_api_request(anthropic, messages, functions) do
{:error, reason} ->
{:error, reason}

case get_api_override() do
{:ok, {:ok, data, callback_name}} ->
# fire callback for fake responses too
Callbacks.fire(anthropic.callbacks, callback_name, [anthropic, data])
# return the data portion
{:ok, data}

# fake error response
{:ok, {:error, _reason} = response} ->
response

_other ->
raise LangChainError,
"An unexpected fake API response was set. Should be an `{:ok, value, nil_or_callback_name}`"
end
else
try do
# make base api request and perform high-level success/failure checks
case do_api_request(anthropic, messages, functions) do
{:error, reason} ->
{:error, reason}

parsed_data ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
parsed_data ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
end
end

Expand Down
39 changes: 11 additions & 28 deletions lib/chat_models/chat_bumblebee.ex
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ defmodule LangChain.ChatModels.ChatBumblebee do
use Ecto.Schema
require Logger
import Ecto.Changeset
import LangChain.Utils.ApiOverride
alias __MODULE__
alias LangChain.ChatModels.ChatModel
alias LangChain.Message
Expand Down Expand Up @@ -218,35 +217,19 @@ defmodule LangChain.ChatModels.ChatBumblebee do
call(model, messages, functions)
end

def call(%ChatBumblebee{} = model, messages, functions)
when is_list(messages) do
if override_api_return?() do
Logger.warning("Found override API response. Will not make live API call.")
def call(%ChatBumblebee{} = model, messages, functions) when is_list(messages) do
try do
# make base api request and perform high-level success/failure checks
case do_serving_request(model, messages, functions) do
{:error, reason} ->
{:error, reason}

# fire callback for fake responses too
case get_api_override() do
{:ok, {:ok, data, callback_name}} ->
Callbacks.fire(model.callbacks, callback_name, [model, data])
{:ok, data}

_other ->
raise LangChainError,
"An unexpected fake API response was set. Should be an `{:ok, value, nil_or_callback_name}`"
end
else
try do
# make base api request and perform high-level success/failure checks
case do_serving_request(model, messages, functions) do
{:error, reason} ->
{:error, reason}

parsed_data ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
parsed_data ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
end
end

Expand Down
42 changes: 11 additions & 31 deletions lib/chat_models/chat_mistral_ai.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ defmodule LangChain.ChatModels.ChatMistralAI do
use Ecto.Schema
require Logger
import Ecto.Changeset
import LangChain.Utils.ApiOverride
alias __MODULE__
alias LangChain.Config
alias LangChain.ChatModels.ChatOpenAI
Expand Down Expand Up @@ -146,37 +145,18 @@ defmodule LangChain.ChatModels.ChatMistralAI do
end

def call(%ChatMistralAI{} = mistral, messages, functions) when is_list(messages) do
if override_api_return?() do
Logger.warning("Found override API response. Will not make live API call.")

case get_api_override() do
{:ok, {:ok, data, callback_name} = response} ->
# fire callback for fake responses too
Callbacks.fire(mistral.callbacks, callback_name, [mistral, data])
response

# fake error response
{:ok, {:error, _reason} = response} ->
response

_other ->
raise LangChainError,
"An unexpected fake API response was set. Should be an `{:ok, value, nil_or_callback_name}`"
end
else
try do
# make base api request and perform high-level success/failure checks
case do_api_request(mistral, messages, functions) do
{:error, reason} ->
{:error, reason}

parsed_data ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
try do
# make base api request and perform high-level success/failure checks
case do_api_request(mistral, messages, functions) do
{:error, reason} ->
{:error, reason}

parsed_data ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
end
end

Expand Down
43 changes: 11 additions & 32 deletions lib/chat_models/chat_open_ai.ex
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ defmodule LangChain.ChatModels.ChatOpenAI do
use Ecto.Schema
require Logger
import Ecto.Changeset
import LangChain.Utils.ApiOverride
alias __MODULE__
alias LangChain.Config
alias LangChain.ChatModels.ChatModel
Expand Down Expand Up @@ -432,38 +431,18 @@ defmodule LangChain.ChatModels.ChatOpenAI do
end

def call(%ChatOpenAI{} = openai, messages, tools) when is_list(messages) do
if override_api_return?() do
Logger.warning("Found override API response. Will not make live API call.")

case get_api_override() do
{:ok, {:ok, data, callback_name}} ->
# fire callback for fake responses too
Callbacks.fire(openai.callbacks, callback_name, [openai, data])
# return the data portion
{:ok, data}

# fake error response
{:ok, {:error, _reason} = response} ->
response

_other ->
raise LangChainError,
"An unexpected fake API response was set. Should be an `{:ok, value, nil_or_callback_name}`"
end
else
try do
# make base api request and perform high-level success/failure checks
case do_api_request(openai, messages, tools) do
{:error, reason} ->
{:error, reason}

parsed_data ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
try do
# make base api request and perform high-level success/failure checks
case do_api_request(openai, messages, tools) do
{:error, reason} ->
{:error, reason}

parsed_data ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
end
end

Expand Down
40 changes: 11 additions & 29 deletions lib/images/open_ai_image.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ defmodule LangChain.Images.OpenAIImage do
use Ecto.Schema
require Logger
import Ecto.Changeset
import LangChain.Utils.ApiOverride
alias __MODULE__
alias LangChain.Images.GeneratedImage
alias LangChain.Config
Expand Down Expand Up @@ -184,35 +183,18 @@ defmodule LangChain.Images.OpenAIImage do
def call(openai)

def call(%OpenAIImage{} = openai) do
if override_api_return?() do
Logger.warning("Found override API response. Will not make live API call.")

case get_api_override() do
{:ok, {:ok, data, _callback_name} = _response} ->
{:ok, data}

# fake error response
{:ok, {:error, _reason} = response} ->
response

_other ->
raise LangChainError,
"An unexpected fake API response was set. Should be an `{:ok, value, nil_or_callback_name}`"
end
else
try do
# make base api request and perform high-level success/failure checks
case do_api_request(openai) do
{:error, reason} ->
{:error, reason}

{:ok, parsed_data} ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
try do
# make base api request and perform high-level success/failure checks
case do_api_request(openai) do
{:error, reason} ->
{:error, reason}

{:ok, parsed_data} ->
{:ok, parsed_data}
end
rescue
err in LangChainError ->
{:error, err.message}
end
end

Expand Down
77 changes: 0 additions & 77 deletions lib/utils/api_override.ex

This file was deleted.

3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ defmodule LangChain.MixProject do
{:req, ">= 0.5.0"},
{:abacus, "~> 2.1.0"},
{:nx, ">= 0.7.0", optional: true},
{:ex_doc, "~> 0.34", only: :dev, runtime: false}
{:ex_doc, "~> 0.34", only: :dev, runtime: false},
{:mimic, "~> 1.8", only: :test}
]
end

Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"},
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
"mimic": {:hex, :mimic, "1.8.2", "f4cf6ad13a305c5ee1a6c304ee36fc7afb3ad748e2af8cd5fbf122f44a283534", [:mix], [], "hexpm", "abc982d5fdcc4cb5292980cb698cd47c0c5d9541b401e540fb695b69f1d46485"},
"mint": {:hex, :mint, "1.6.1", "065e8a5bc9bbd46a41099dfea3e0656436c5cbcb6e741c80bd2bad5cd872446f", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "4fc518dcc191d02f433393a72a7ba3f6f94b101d094cb6bf532ea54c89423780"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
"nimble_ownership": {:hex, :nimble_ownership, "0.3.1", "99d5244672fafdfac89bfad3d3ab8f0d367603ce1dc4855f86a1c75008bce56f", [:mix], [], "hexpm", "4bf510adedff0449a1d6e200e43e57a814794c8b5b6439071274d248d272a549"},
Expand Down
Loading

0 comments on commit 0d2dc6a

Please sign in to comment.