Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add callbacks for debugging #46

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8b544aa
fix typo
petrus-jvrensburg Jan 16, 2024
e2ff298
update 'cassification' livebook from example in README
petrus-jvrensburg Jan 16, 2024
aa327c8
add missing livebook link to docs
petrus-jvrensburg Jan 16, 2024
fec0488
Introduction to Instructor -> Quickstart
petrus-jvrensburg Jan 16, 2024
2dc5f17
review README
petrus-jvrensburg Jan 16, 2024
1affca1
move llama livebook into 'cookbooks'
petrus-jvrensburg Jan 16, 2024
cff8ca2
update livebooks
petrus-jvrensburg Jan 16, 2024
0216bc5
resolve conflicts
petrus-jvrensburg Jan 22, 2024
c23643d
Merge branch 'main' of github.com:thmsmlr/instructor_ex
petrus-jvrensburg Feb 18, 2024
1d6f89f
Merge branch 'main' of github.com:thmsmlr/instructor_ex
petrus-jvrensburg Feb 23, 2024
537e59f
Merge branch 'main' of github.com:thmsmlr/instructor_ex
petrus-jvrensburg Mar 19, 2024
6da3fdd
Merge branch 'main' of github.com:thmsmlr/instructor_ex
petrus-jvrensburg Apr 11, 2024
6928d51
update .gitignore
petrus-jvrensburg Apr 15, 2024
872348a
openai: add optional params for inspecting request / response
petrus-jvrensburg Apr 15, 2024
c6a7a2e
llama.cpp: add optional params for inspecting request / response
petrus-jvrensburg Apr 15, 2024
fca0871
document new params
petrus-jvrensburg Apr 15, 2024
5490364
fix linting errors
petrus-jvrensburg Apr 15, 2024
5cf4e9d
provide a callback, rather than setting a flag
petrus-jvrensburg Apr 22, 2024
c90f15e
update Quickstart livebook with a section on debugging
petrus-jvrensburg Apr 22, 2024
98d33b8
Merge branch 'main' of github.com:petrus-jvrensburg/instructor_ex int…
petrus-jvrensburg Jun 25, 2024
52df85c
Merge branch 'main' of github.com:thmsmlr/instructor_ex
petrus-jvrensburg Jun 25, 2024
a3dbd1d
Merge branch 'main' into debugging
petrus-jvrensburg Jun 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ instructor-*.tar

# Temporary files, for example, from tests.
/tmp/

*.DS_Store
llama.log
2 changes: 2 additions & 0 deletions lib/instructor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ defmodule Instructor do
* `:mode` - The mode to use when parsing the response, :tools, :json, :md_json (defaults to `:tools`), generally speaking you don't need to change this unless you are not using OpenAI.
* `:max_retries` - The maximum number of times to retry the LLM call if it fails, or does not pass validations.
(defaults to `0`)
* `:before_request` - An optional callback function, to run just before passing a request to the LLM, useful for debugging.
* `:after_response` - An optional callback function to run after receiving a response from the LLM, and before processing the response, useful for debugging.

## Examples

Expand Down
62 changes: 43 additions & 19 deletions lib/instructor/adapters/llamacpp.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,38 +34,51 @@ defmodule Instructor.Adapters.Llamacpp do
def chat_completion(params, _config \\ nil) do
{response_model, _} = Keyword.pop!(params, :response_model)
{messages, _} = Keyword.pop!(params, :messages)
{before_request, params} = Keyword.pop(params, :before_request)
{after_response, params} = Keyword.pop(params, :after_response)

json_schema = JSONSchema.from_ecto_schema(response_model)
grammar = GBNF.from_json_schema(json_schema)
prompt = apply_chat_template(chat_template(), messages)
stream = Keyword.get(params, :stream, false)

if stream do
do_streaming_chat_completion(prompt, grammar)
do_streaming_chat_completion(prompt, grammar, before_request, after_response)
else
do_chat_completion(prompt, grammar)
do_chat_completion(prompt, grammar, before_request, after_response)
end
end

defp do_streaming_chat_completion(prompt, grammar) do
defp do_streaming_chat_completion(prompt, grammar, before_request, after_response) do
pid = self()

Stream.resource(
fn ->
Task.async(fn ->
Req.post!(url(),
json: %{
grammar: grammar,
prompt: prompt,
stream: true
},
receive_timeout: 60_000,
into: fn {:data, data}, {req, resp} ->
send(pid, data)
{:cont, {req, resp}}
end
)

req =
Req.new(
url: url(),
json: %{
grammar: grammar,
prompt: prompt,
stream: true
},
receive_timeout: 60_000,
into: fn {:data, data}, {req, resp} ->
if is_function(after_response) do
after_response.({{:data, data}, {req, resp}})
end

send(pid, data)
{:cont, {req, resp}}
end
)

if is_function(before_request) do
before_request.(req)
end

Req.post!(req)
send(pid, :done)
end)
end,
Expand Down Expand Up @@ -94,16 +107,27 @@ defmodule Instructor.Adapters.Llamacpp do
}
end

defp do_chat_completion(prompt, grammar) do
response =
Req.post!(url(),
defp do_chat_completion(prompt, grammar, before_request, after_response) do
req =
Req.new(
url: url(),
json: %{
grammar: grammar,
prompt: prompt
},
receive_timeout: 60_000
)

if is_function(before_request) do
before_request.(req)
end

response = Req.post!(req)

if is_function(after_response) do
after_response.(response)
end

case response do
%{status: 200, body: %{"content" => params}} ->
{:ok, to_openai_response(params)}
Expand Down
34 changes: 28 additions & 6 deletions lib/instructor/adapters/openai.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@ defmodule Instructor.Adapters.OpenAI do
{_, params} = Keyword.pop(params, :validation_context)
{_, params} = Keyword.pop(params, :max_retries)
{_, params} = Keyword.pop(params, :mode)
{before_request, params} = Keyword.pop(params, :before_request)
{after_response, params} = Keyword.pop(params, :after_response)
stream = Keyword.get(params, :stream, false)
params = Enum.into(params, %{})

if stream do
do_streaming_chat_completion(params, config)
do_streaming_chat_completion(params, config, before_request, after_response)
else
do_chat_completion(params, config)
do_chat_completion(params, config, before_request, after_response)
end
end

defp do_streaming_chat_completion(params, config) do
defp do_streaming_chat_completion(params, config, before_request, after_response) do
pid = self()
options = http_options(config)

Expand All @@ -35,6 +37,10 @@ defmodule Instructor.Adapters.OpenAI do
json: params,
auth: {:bearer, api_key(config)},
into: fn {:data, data}, {req, resp} ->
if is_function(after_response) do
after_response.({{:data, data}, {req, resp}})
end

chunks =
data
|> String.split("\n")
Expand All @@ -55,7 +61,13 @@ defmodule Instructor.Adapters.OpenAI do
end
)

Req.post!(url(config), options)
req = Req.new([url: url(config)] ++ options)

if is_function(before_request) do
before_request.(req)
end

Req.post!(req)
send(pid, :done)
end)
end,
Expand All @@ -75,9 +87,19 @@ defmodule Instructor.Adapters.OpenAI do
)
end

defp do_chat_completion(params, config) do
defp do_chat_completion(params, config, before_request, after_response) do
options = Keyword.merge(http_options(config), json: params, auth: {:bearer, api_key(config)})
response = Req.post!(url(config), options)
req = Req.new([url: url(config)] ++ options)

if is_function(before_request) do
before_request.(req)
end

response = Req.post!(req)

if is_function(after_response) do
after_response.(response)
end

case response.status do
200 -> {:ok, response.body}
Expand Down
Loading