thmsmlr / instructor_ex

Structured outputs for LLMs in Elixir
https://hexdocs.pm/instructor
545 stars 59 forks source link

SpamPrediction example failing to compile with "Unknown Registry" #39

Closed medoror closed 6 months ago

medoror commented 7 months ago

Great library! I wanted to dig in more by first using the example. For some reason, taking the SpamPrediction example and adding it to my fork does not compile. There error looks like the following

07:28:15.482 [warning] Failed to lookup telemetry handlers. Ensure the telemetry application has been started. 

07:28:15.485 [warning] Failed to lookup telemetry handlers. Ensure the telemetry application has been started. 

== Compilation error in file lib/spam_prediction.ex ==
** (ArgumentError) unknown registry: Req.Finch
    (elixir 1.15.4) lib/registry.ex:1400: Registry.key_info!/1
    (elixir 1.15.4) lib/registry.ex:590: Registry.lookup/2
    (finch 0.16.0) lib/finch/pool_manager.ex:44: Finch.PoolManager.lookup_pool/2
    (finch 0.16.0) lib/finch/pool_manager.ex:34: Finch.PoolManager.get_pool/2
    (finch 0.16.0) lib/finch.ex:284: Finch.__stream__/5
    (finch 0.16.0) lib/finch.ex:324: anonymous fn/4 in Finch.request/3
    (telemetry 1.2.1) /Users/michaeledoror/workspace/instructor_ex/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
    (req 0.4.8) lib/req/steps.ex:836: Req.Steps.run_finch_request/3

I feel like I might be setting up my creds for openai incorrectly? Below is the file that I am using. Same everything but I had to do some work to configure the :api_key, http_options, and api_url. Am I going about this the write way?

defmodule SpamPrediction do
  use Ecto.Schema
  use Instructor.Validator

  @doc """
  ## Field Descriptions:
  - class: Whether or not the email is spam.
  - reason: A short, less than 10 word rationalization for the classification.
  - score: A confidence score between 0.0 and 1.0 for the classification.
  """
  @primary_key false
  embedded_schema do
    field(:class, Ecto.Enum, values: [:spam, :not_spam])
    field(:reason, :string)
    field(:score, :float)
  end

  @impl true
  def validate_changeset(changeset) do
    changeset
    |> Ecto.Changeset.validate_number(:score,
      greater_than_or_equal_to: 0.0,
      less_than_or_equal_to: 1.0
    )
  end
end

is_spam? = fn text ->
  Instructor.chat_completion([
      model: "gpt-3.5-turbo",
      response_model: SpamPrediction,
      max_retries: 3,
      messages: [
        %{
          role: "user",
          content: """
          Your purpose is to classify customer support emails as either spam or not.
          This is for a clothing retail business.
          They sell all types of clothing.

          Classify the following email:
      #{text}
      ```
      """
    }
  ]],
  [api_key: System.get_env("OPENAI_API_KEY"), http_options: [receive_timeout: 60_000], api_url: "https://api.openai.com"]

) end

is_spam?.("Hello I am a Nigerian prince and I would like to send you money")

=> {:ok, %SpamPrediction{class: :spam, reason: "Nigerian prince email scam", score: 0.98}}

knewter commented 7 months ago

Where is the code being called? Before you make any calls, you need to ensure that the :req app has been started.

Here's another discussion of this happening - https://www.reddit.com/r/elixir/comments/1667o93/problem_on_a_simple_script_with_req/

It looks like you're making an outbound call with Req during compilation of the lib/spam_prediction.ex file - this is unusual.

By chance, do you have code in that file outside of the defmodule body, perhaps an example that makes an outbound call?

medoror commented 6 months ago

@knewter you are right here. I was attempting to invoke the instructor call at compile time. Closing!