1 line
205 KiB
JSON
1 line
205 KiB
JSON
{"repo": "alexrudall/ruby-openai", "files": {"spec/openai/client/chat_spec.rb": {"62938e02bb83e9f243ad2447805bc461d5d126fe": {"t": 1785746180.0533323, "n": 9485, "h": "32784ba4ba3053ee", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) do\n \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase\n end\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n\n context \"with multiple tool calls\" do\n let(:cassette) { \"#{model} multiple tool calls full conversation\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in San Francisco and Japan?\"\n }\n ]\n end\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools,\n tool_choice: \"required\"\n }\n end\n\n it \"handles full conversation with multiple tool calls\" do\n VCR.use_cassette(cassette) do\n message = response.dig(\"choices\", 0, \"message\")\n\n if message[\"role\"] == \"assistant\" && message[\"tool_calls\"]\n messages << message\n\n message[\"tool_calls\"].each do |tool_call|\n messages << {\n tool_call_id: tool_call[\"id\"],\n role: \"tool\",\n name: \"get_current_weather\",\n content: \"The weather is nice 🌞\"\n }\n end\n\n second_response = OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages\n }\n )\n\n expect(second_response[\"error\"]).to be_nil\n end\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Deepseek + model: deepseek-chat\" do\n let(:uri_base) { \"https://api.deepseek.com/\" }\n let(:provider) { \"deepseek\" }\n let(:model) { \"deepseek-chat\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Deepseek API key\"\n end\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "33341ea00134645674d2a3bd05af191df5b0332e": {"t": 1785760342.3415391, "n": 9485, "h": "32784ba4ba3053ee", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) do\n \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase\n end\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n\n context \"with multiple tool calls\" do\n let(:cassette) { \"#{model} multiple tool calls full conversation\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in San Francisco and Japan?\"\n }\n ]\n end\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools,\n tool_choice: \"required\"\n }\n end\n\n it \"handles full conversation with multiple tool calls\" do\n VCR.use_cassette(cassette) do\n message = response.dig(\"choices\", 0, \"message\")\n\n if message[\"role\"] == \"assistant\" && message[\"tool_calls\"]\n messages << message\n\n message[\"tool_calls\"].each do |tool_call|\n messages << {\n tool_call_id: tool_call[\"id\"],\n role: \"tool\",\n name: \"get_current_weather\",\n content: \"The weather is nice 🌞\"\n }\n end\n\n second_response = OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages\n }\n )\n\n expect(second_response[\"error\"]).to be_nil\n end\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Deepseek + model: deepseek-chat\" do\n let(:uri_base) { \"https://api.deepseek.com/\" }\n let(:provider) { \"deepseek\" }\n let(:model) { \"deepseek-chat\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Deepseek API key\"\n end\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "2fef3eb8d765398dac2ff556cbd6ae5fb2ba1a40": {"t": 1785760343.6445994, "n": 9493, "h": "856af5d4d3255b23", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) do\n \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase\n end\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n\n context \"with multiple tool calls\" do\n let(:cassette) { \"#{model} multiple tool calls full conversation\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in San Francisco and Japan?\"\n }\n ]\n end\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools,\n tool_choice: \"required\"\n }\n end\n\n it \"handles full conversation with multiple tool calls\" do\n VCR.use_cassette(cassette) do\n message = response.dig(\"choices\", 0, \"message\")\n\n if message[\"role\"] == \"assistant\" && message[\"tool_calls\"]\n messages << message\n\n message[\"tool_calls\"].each do |tool_call|\n messages << {\n tool_call_id: tool_call.dig(\"id\"),\n role: \"tool\",\n name: \"get_current_weather\",\n content: \"The weather is nice 🌞\"\n }\n end\n\n second_response = OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages\n }\n )\n\n expect(second_response.dig(\"error\")).to be_nil\n end\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Deepseek + model: deepseek-chat\" do\n let(:uri_base) { \"https://api.deepseek.com/\" }\n let(:provider) { \"deepseek\" }\n let(:model) { \"deepseek-chat\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Deepseek API key\"\n end\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "d8a195136d639bf97092c6b25a5edb36738a25c2": {"t": 1785760345.0869455, "n": 7890, "h": "4bf4ff261a0d24be", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) do\n \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase\n end\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Deepseek + model: deepseek-chat\" do\n let(:uri_base) { \"https://api.deepseek.com/\" }\n let(:provider) { \"deepseek\" }\n let(:model) { \"deepseek-chat\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Deepseek API key\"\n end\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _event|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "43d66be997a1221cb43ba68712746e9d7ca20919": {"t": 1785760347.607741, "n": 7899, "h": "ec5a61a8c85e9d65", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) do\n \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase\n end\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Deepseek + model: deepseek-chat\" do\n let(:uri_base) { \"https://api.deepseek.com/\" }\n let(:provider) { \"deepseek\" }\n let(:model) { \"deepseek-chat\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Deepseek API key\"\n end\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "fb156c85f0e34e20be67c51c3d3d0dcd8c3728de": {"t": 1785760348.9295685, "n": 7895, "h": "1024d38dccffe35f", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) do\n \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase\n end\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Deepseek + model: deepseek-chat\" do\n let(:uri_base) { \"https://api.deepseek.com/\" }\n let(:provider) { \"deepseek\" }\n let(:model) { \"deepseek-chat\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "2f7cfb74e51c868a57ed2f8b96efed0839abf9d1": {"t": 1785760351.0274024, "n": 7059, "h": "3350a955b4d3c0f3", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) do\n \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase\n end\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"mocks/#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "14e1f519e03ed1bd9233f94443eb2dad557010ab": {"t": 1785760352.2361317, "n": 7047, "h": "23e1cac6c31c8837", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) do\n \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase\n end\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "69ba82ed3f2f52900bdbd292cce68ee41bce09b5": {"t": 1785760353.3690677, "n": 7299, "h": "0d7fd9ee278bd5fb", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) do\n \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase\n end\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "9163a3006779575acc8beeb7e82dd8ed562d889a": {"t": 1785760354.612512, "n": 7282, "h": "5001254b365587cf", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) { \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "2c994eb4fc5297d248100741618569295304fc94": {"t": 1785760356.0999196, "n": 7400, "h": "ba447f3c821877b0", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) { \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:access_token) { ENV.fetch(\"GROQ_ACCESS_TOKEN\", nil) }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base, access_token: access_token }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n response\n rescue Faraday::UnauthorizedError\n pending \"This test needs the `OPENAI_ACCESS_TOKEN` to be a Groq API key\"\n end\n\n # response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "0d0c06aa718d818695852c424e6e39d567c407ed": {"t": 1785760358.3545702, "n": 7391, "h": "0c684c9132c95502", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) { \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n tap do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:access_token) { ENV.fetch(\"GROQ_ACCESS_TOKEN\", nil) }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base, access_token: access_token }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n vcr_skip do\n unless access_token\n pending \"This test needs a `GROQ_ACCESS_TOKEN` environment variable to run\"\n end\n end\n\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "eb8fe01c48aadb4c3374d4bc005a582f7049c10f": {"t": 1785760359.5148673, "n": 7396, "h": "e778dd0ebc8f38b2", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) { \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n vcr_skip do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:access_token) { ENV.fetch(\"GROQ_ACCESS_TOKEN\", nil) }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base, access_token: access_token }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n vcr_skip do\n unless access_token\n pending \"This test needs a `GROQ_ACCESS_TOKEN` environment variable to run\"\n end\n end\n\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "52c7b6b7baa4f6b675591e5ab26afe8e2070ca0f": {"t": 1785760360.895959, "n": 7344, "h": "11086a2a997406bb", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) { \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n vcr_skip do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n skip \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:access_token) { ENV.fetch(\"GROQ_ACCESS_TOKEN\", nil) }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base, access_token: access_token }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n unless access_token\n skip \"This test needs a `GROQ_ACCESS_TOKEN` environment variable to run\"\n end\n\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "b177fc4de82d37bf8ac09e6f091e12f2399787ef": {"t": 1785760364.13471, "n": 7408, "h": "0f0eff48d7f261b2", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:provider) { nil }\n let(:cassette) { \"#{\"#{provider}_\" if provider}#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:provider) { \"ollama\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n vcr_skip do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Groq + model: llama3\" do\n let(:uri_base) { \"https://api.groq.com/openai\" }\n let(:provider) { \"groq\" }\n let(:model) { \"llama3-8b-8192\" }\n let(:access_token) { ENV.fetch(\"GROQ_ACCESS_TOKEN\", nil) }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base, access_token: access_token }).chat(\n parameters: parameters\n )\n end\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n print chunk[\"choices\"][0][\"delta\"][\"content\"]\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n unless access_token\n pending \"This test needs a `GROQ_ACCESS_TOKEN` environment variable to run\"\n end\n\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n end\nend\n"}, "d74cc9de56acce3a709f36c9c5789aea0a89c71c": {"t": 1785760365.4648263, "n": 6368, "h": "ce60b6c28e49538b", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({ uri_base: uri_base }).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n vcr_skip do\n Faraday.new(url: uri_base).get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "79cbb42431236046444cd5885291523bd088489a": {"t": 1785760366.702972, "n": 6403, "h": "df9449a451aba416", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:uri_base) { nil }\n let(:response) do\n OpenAI::Client.new({uri_base: uri_base}).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:uri_base) { \"http://localhost:11434\" }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n vcr_skip do\n conn = Faraday.new(url: uri_base)\n response = conn.get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "aa7bcecf0cb5dd77dafc71f7aba46bb8b99d540b": {"t": 1785760369.069165, "n": 6471, "h": "149f0417d1fe529f", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:client_parameters) { nil }\n let(:response) do\n OpenAI::Client.new(client_parameters).chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n\n context \"with Ollama + model: llama3\" do\n let(:client_parameters) { { api_type: :ollama, uri_base: \"http://localhost:11434\" } }\n let(:model) { \"llama3\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n vcr_skip do\n conn = Faraday.new(url: client_parameters[:uri_base])\n response = conn.get\n rescue Faraday::ConnectionFailed\n pending \"This test needs `ollama serve` running locally with #{model} installed\"\n end\n\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "f452cb8c4874df6e02e3e7ad6540bf40a0507d31": {"t": 1785760370.3407571, "n": 5800, "h": "f37443c33304cdac", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\",\n \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "03a301b5de8ea741cecf21acaa27eff6f2893fc2": {"t": 1785760371.6116066, "n": 5728, "h": "62d40371fe534a12", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\", \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\", \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "199ecd23ef30956cddb64e68a462d27e73d3218a": {"t": 1785760373.006658, "n": 5729, "h": "15729928a178fdd0", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with a tool call\" do\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n tools: tools\n }\n end\n let(:tools) do\n [\n {\n \"type\" => \"function\",\n \"function\" => {\n \"name\" => \"get_current_weather\",\n \"description\" => \"Get the current weather in a given location\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"location\" => {\n \"type\" => \"string\",\n \"description\" => \"The geographic location to get the weather for\"\n }\n },\n \"required\" => [\"location\"]\n }\n }\n }\n ]\n end\n\n context \"with a valid message\" do\n let(:cassette) { \"#{model} valid tool call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"user\",\n \"content\" => \"What is the weather like in the Peak District?\"\n }\n ]\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\", \"name\")).to eq(\"get_current_weather\")\n expect(response.dig(\"choices\", 0, \"message\", \"tool_calls\", 0, \"function\", \"arguments\")).to include(\"Peak District\")\n end\n end\n end\n end\n\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "69fd4c40108f3093ab676c33a4676feefcd3e750": {"t": 1785760374.3031316, "n": 5409, "h": "274008104f067b6e", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with an invalid function call\" do\n let(:cassette) { \"#{model} function call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"function\",\n # \"name\" => \"function\",\n \"content\" => \"function\"\n }\n ]\n end\n let(:parameters) do\n {\n model: model,\n messages: messages,\n stream: stream,\n functions: functions\n }\n end\n let(:functions) do\n [\n {\n \"name\" => \"function\",\n \"description\" => \"function\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"user\" => {\n \"type\" => \"string\",\n \"description\" => \"the full name of the user\"\n }\n }\n }\n }\n ]\n end\n\n it \"raises an error containing the reason\" do\n VCR.use_cassette(cassette) do\n response\n rescue Faraday::Error => e\n expect(e.response.dig(:body, \"error\",\n \"message\")).to include(\"Missing parameter 'name'\")\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "c38679bb0dd25c07960d8464e82205555b82ccf6": {"t": 1785760375.7530391, "n": 5316, "h": "f9c0398c0aa9c2b2", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: parameters\n )\n end\n let(:parameters) { { model: model, messages: messages, stream: stream } }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with an invalid function call\" do\n let(:cassette) { \"#{model} function call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"function\",\n # \"name\" => \"function\",\n \"content\" => \"function\"\n }\n ]\n end\n let(:parameters) { { model: model, messages: messages, stream: stream, functions: functions } }\n let(:functions) do\n [\n {\n \"name\" => \"function\",\n \"description\" => \"function\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"user\" => {\n \"type\" => \"string\",\n \"description\" => \"the full name of the user\"\n }\n }\n }\n }\n ]\n end\n\n it \"raises an error containing the reason\" do\n VCR.use_cassette(cassette) do\n response\n rescue Faraday::Error => e\n expect(e.response.dig(:body, \"error\",\n \"message\")).to include(\"Missing parameter 'name'\")\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "cd9743a18c5ec90d8fe7121924b771d9f6341ecc": {"t": 1785760377.0433102, "n": 5281, "h": "d762b4400e8b9ca7", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages,\n functions: functions,\n stream: stream\n }\n )\n end\n let(:functions) { [] }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with an invalid function call\" do\n let(:cassette) { \"#{model} function call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\" => \"function\",\n # \"name\" => \"function\",\n \"content\" => \"function\"\n }\n ]\n end\n let(:functions) do\n [\n {\n \"name\" => \"function\",\n \"description\" => \"function\",\n \"parameters\" =>\n {\n \"type\" => \"object\",\n \"properties\" => {\n \"user\" => {\n \"type\" => \"string\",\n \"description\" => \"the full name of the user\"\n }\n }\n }\n }\n ]\n end\n\n it \"raises an error containing the reason\" do\n VCR.use_cassette(cassette) do\n response\n rescue Faraday::Error => e\n expect(e.response.dig(:body, \"error\",\n \"message\")).to include(\"Missing parameter 'name'\")\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "8c10996555746602455aa2268a0de57dbf7bfd21": {"t": 1785760378.5096815, "n": 5318, "h": "3126cfc6e7122d46", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages,\n functions: functions,\n stream: stream\n }\n )\n end\n let(:functions) { [] }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with an invalid function call\" do\n let(:cassette) { \"#{model} function call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\"=>\"function\",\n # \"name\" => \"function\",\n \"content\"=>\"function\"\n }\n ]\n end\n let(:functions) do\n [\n {\n \"name\"=>\"function\",\n \"description\"=>\"function\",\n \"parameters\"=>\n {\n \"type\"=>\"object\",\n \"properties\"=>{\n \"user\"=>{\n \"type\"=>\"string\",\n \"description\"=>\"the full name of the user\"\n }\n },\n }\n },\n ]\n end\n\n it \"raises an error containing the reason\" do\n VCR.use_cassette(cassette) do\n begin\n response\n rescue Faraday::Error => e\n expect(e.response.dig(:body, \"error\", \"message\")).to eq(\"Missing parameter 'name': messages with role 'function' must have a 'name'.\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "832c81bf5d10ac2892b86a4a550e230e61ce733e": {"t": 1785760379.888119, "n": 5437, "h": "2274bc4275c5111c", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n client = OpenAI::Client.new do |client|\n client.response :logger, ::Logger.new(STDOUT), bodies: true\n end\n\n client.chat(\n parameters: {\n model: model,\n messages: messages,\n functions: functions,\n stream: stream\n }\n )\n end\n let(:functions) { [] }\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n context \"with an invalid function call\" do\n let(:cassette) { \"#{model} function call chat\".downcase }\n let(:messages) do\n [\n {\n \"role\"=>\"function\",\n # \"name\" => \"function\",\n \"content\"=>\"function\"\n }\n ]\n end\n let(:functions) do\n [\n {\n \"name\"=>\"function\",\n \"description\"=>\"function\",\n \"parameters\"=>\n {\n \"type\"=>\"object\",\n \"properties\"=>{\n \"user\"=>{\n \"type\"=>\"string\",\n \"description\"=>\"the full name of the user\"\n }\n },\n }\n },\n ]\n end\n\n it \"raises an error containing the reason\" do\n VCR.use_cassette(cassette) do\n begin\n response\n rescue Faraday::Error => e\n expect(e.response.dig(:body, \"error\", \"message\")).to eq(\"Missing parameter 'name': messages with role 'function' must have a 'name'.\")\n end\n end\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "cf6f3a2080b0111d8dd3272f71cb41776c574118": {"t": 1785760381.261962, "n": 4007, "h": "a588d7e8178d2bcc", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages,\n stream: stream\n }\n )\n end\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response with a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with json error response\".downcase }\n\n it \"raises an HTTP error with the parsed body\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n\n context \"with an error response without a JSON body\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::ServerError => e\n expect(e.response).to include(status: 500)\n expect(e.response[:body]).to eq(\"\")\n else\n raise \"Expected to raise Faraday::ServerError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "1a09ecd59bc3d6b19a2f9449c342f432aceda0ab": {"t": 1785760383.2625635, "n": 3398, "h": "1d1aec217baaf7e3", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages,\n stream: stream\n }\n )\n end\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette, record: :none) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "a22138a45ec1e164e8a16885ea8f16ed96c0826c": {"t": 1785760384.6229138, "n": 3383, "h": "9c23ff33eaec8a44", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages,\n stream: stream\n }\n )\n end\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n\n context \"with an error response\" do\n let(:cassette) { \"#{model} streamed chat with error response\".downcase }\n\n it \"raises an HTTP error\" do\n VCR.use_cassette(cassette) do\n response\n rescue Faraday::BadRequestError => e\n expect(e.response).to include(status: 400)\n expect(e.response[:body]).to eq({\n \"error\" => {\n \"message\" => \"Test error\",\n \"type\" => \"test_error\",\n \"param\" => nil,\n \"code\" => \"test\"\n }\n })\n else\n raise \"Expected to raise Faraday::BadRequestError\"\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "6776c1e40731900dfcef5436913aa6e51189f9e0": {"t": 1785760385.8068137, "n": 2388, "h": "2ea3babb72b87036", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages,\n stream: stream\n }\n )\n end\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n\n context \"with an object with a call method\" do\n let(:cassette) { \"#{model} streamed chat without proc\".downcase }\n let(:stream) do\n Class.new do\n attr_reader :chunks\n\n def initialize\n @chunks = []\n end\n\n def call(chunk)\n @chunks << chunk\n end\n end.new\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(stream.chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n\n context \"with an object without a call method\" do\n let(:stream) { Object.new }\n\n it \"raises an error\" do\n VCR.use_cassette(cassette) do\n expect { response }.to raise_error(ArgumentError)\n end\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}, "0cb68600a9b3842901699fb70d8a09d6c1ca5b33": {"t": 1785760386.9471254, "n": 1432, "h": "305c7d9233091167", "c": "RSpec.describe OpenAI::Client do\n describe \"#chat\" do\n context \"with messages\", :vcr do\n let(:messages) { [{ role: \"user\", content: \"Hello!\" }] }\n let(:stream) { false }\n let(:response) do\n OpenAI::Client.new.chat(\n parameters: {\n model: model,\n messages: messages,\n stream: stream\n }\n )\n end\n let(:content) { response.dig(\"choices\", 0, \"message\", \"content\") }\n let(:cassette) { \"#{model} #{'streamed' if stream} chat\".downcase }\n\n context \"with model: gpt-3.5-turbo\" do\n let(:model) { \"gpt-3.5-turbo\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n\n describe \"streaming\" do\n let(:chunks) { [] }\n let(:stream) do\n proc do |chunk, _bytesize|\n chunks << chunk\n end\n end\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n response\n expect(chunks.dig(0, \"choices\", 0, \"index\")).to eq(0)\n end\n end\n end\n end\n\n context \"with model: gpt-3.5-turbo-0301\" do\n let(:model) { \"gpt-3.5-turbo-0301\" }\n\n it \"succeeds\" do\n VCR.use_cassette(cassette) do\n expect(content.split.empty?).to eq(false)\n end\n end\n end\n end\n end\nend\n"}}}} |