diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..475e926 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,61 @@ +name: Bug report +description: Report a reproducible bug or unexpected behavior +labels: [bug] +body: + - type: markdown + attributes: + value: | + Thanks for reporting a bug! Please provide as much detail as possible. + + - type: input + id: gem_version + attributes: + label: Gem Version + placeholder: e.g., 0.2.1 + validations: + required: true + + - type: textarea + id: description + attributes: + label: What happened? + description: Describe the unexpected behavior or error message + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: Provide a minimal script or code snippet to reproduce the issue + placeholder: | + 1. Call method `X` with parameter `Y` + 2. Observe error message `Z` + validations: + required: true + + - type: textarea + id: expected + attributes: + label: What did you expect to happen? + description: What should the correct behavior be? + + - type: textarea + id: environment + attributes: + label: Environment + description: Ruby version, OS, and any other relevant info + placeholder: | + Ruby version: 3.2.2 + OS: macOS 14.0 + Bundler version: 2.4.0 + + - type: checkboxes + id: confirmation + attributes: + label: Before submitting + options: + - label: I've updated to the latest version of the gem + required: true + - label: I've read the README and documentation + required: true \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a2e01d1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,29 @@ +name: Release + +on: + push: + tags: + - 'v*.*.*' + +jobs: + release: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + + - name: Build and Push Gem + env: + GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_AUTH_TOKEN }} + run: | + mkdir -p ~/.gem + echo -e "---\n:rubygems_api_key: $GEM_HOST_API_KEY" > ~/.gem/credentials + chmod 0600 ~/.gem/credentials + gem build *.gemspec + gem push *.gem \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..b386563 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + ruby-version: ['3.1', '3.2', '3.3', '3.4'] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true + + - name: Run tests + run: bundle exec rspec \ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml index 0fa7209..c285a7a 100755 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,9 @@ +plugins: + - rubocop-rake + - rubocop-rspec + AllCops: - TargetRubyVersion: 2.6 + TargetRubyVersion: 3.1 NewCops: enable SuggestExtensions: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 578fd99..ec075f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## 1.0.0.rc3 (2025-04-06) + +- Added rspec test suite with vcr, covering current functionality: + - Chat and Multi-turn conversation tests + - Streaming response tests + - Tools calling functionality tests + - Embedding generation tests + - Image generation tests +- Added GitHub workflows for: + - CI testing across Ruby versions 3.1, 3.2, 3.3, and 3.4 + - Automated gem release process + - Issue templates for bug reports + ## 1.0.0.rc2 (2025-03-16) - Minor improvements to README documentation and fixes to GitHub repository links. diff --git a/Gemfile b/Gemfile index dea8dd5..f8d08b2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,12 +1,18 @@ +# frozen_string_literal: true + source "https://rubygems.org" -# Include gem dependencies from litellm.gemspec gemspec -gem "byebug", "~> 11.1.3" -gem "dotenv", "~> 2.8.1" -gem "rake", "~> 13.2" -gem "rspec", "~> 3.13" -gem "rubocop", "~> 1.73.1" -gem "vcr", "~> 6.1.0" -gem "webmock", "~> 3.24.0" +group :development do + gem "activesupport", "< 8.0" + gem "bundler", ">= 2.0" + gem "dotenv" + gem "rake", ">= 13.0" + gem "rspec", "~> 3.12" + gem "rubocop", ">= 1.0" + gem "rubocop-rake" + gem "rubocop-rspec" + gem "vcr" + gem "webmock" +end diff --git a/Gemfile.lock b/Gemfile.lock index ac1f74a..8f04c91 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,61 +1,81 @@ PATH remote: . specs: - litellm (1.0.0.rc1) + litellm (1.0.0.rc3) event_stream_parser (>= 0.3.0, < 2.0.0) faraday (>= 1) GEM remote: https://rubygems.org/ specs: + activesupport (7.2.2.1) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) - ast (2.4.2) + ast (2.4.3) + base64 (0.2.0) + benchmark (0.4.0) bigdecimal (3.1.9) - byebug (11.1.3) + concurrent-ruby (1.3.5) + connection_pool (2.5.0) crack (1.0.0) bigdecimal rexml - diff-lcs (1.5.1) - dotenv (2.8.1) + diff-lcs (1.6.1) + dotenv (3.1.7) + drb (2.2.1) event_stream_parser (1.0.0) - faraday (2.12.0) - faraday-net_http (>= 2.0, < 3.4) + faraday (2.12.2) + faraday-net_http (>= 2.0, < 3.5) json logger - faraday-net_http (3.3.0) - net-http - hashdiff (1.1.1) - json (2.9.1) + faraday-net_http (3.4.0) + net-http (>= 0.5.0) + hashdiff (1.1.2) + i18n (1.14.7) + concurrent-ruby (~> 1.0) + json (2.10.2) language_server-protocol (3.17.0.4) lint_roller (1.1.0) - logger (1.6.6) - net-http (0.5.0) + logger (1.7.0) + minitest (5.25.5) + net-http (0.6.0) uri parallel (1.26.3) - parser (3.3.6.0) + parser (3.3.7.4) ast (~> 2.4.1) racc + prism (1.4.0) public_suffix (6.0.1) racc (1.8.1) rainbow (3.1.1) rake (13.2.1) regexp_parser (2.10.0) - rexml (3.3.9) + rexml (3.4.1) rspec (3.13.0) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) - rspec-core (3.13.0) + rspec-core (3.13.3) rspec-support (~> 3.13.0) - rspec-expectations (3.13.0) + rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.0) + rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-support (3.13.1) - rubocop (1.73.2) + rspec-support (3.13.2) + rubocop (1.75.2) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -63,16 +83,29 @@ GEM parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.9.3, < 3.0) - rubocop-ast (>= 1.38.0, < 2.0) + rubocop-ast (>= 1.44.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.38.1) - parser (>= 3.3.1.0) + rubocop-ast (1.44.0) + parser (>= 3.3.7.2) + prism (~> 1.4) + rubocop-rake (0.7.1) + lint_roller (~> 1.1) + rubocop (>= 1.72.1) + rubocop-rspec (3.5.0) + lint_roller (~> 1.1) + rubocop (~> 1.72, >= 1.72.1) ruby-progressbar (1.13.0) - unicode-display_width (2.6.0) - uri (1.0.2) - vcr (6.1.0) - webmock (3.24.0) + securerandom (0.4.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (3.1.4) + unicode-emoji (~> 4.0, >= 4.0.4) + unicode-emoji (4.0.4) + uri (1.0.3) + vcr (6.3.1) + base64 + webmock (3.25.1) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -82,14 +115,17 @@ PLATFORMS ruby DEPENDENCIES - byebug (~> 11.1.3) - dotenv (~> 2.8.1) + activesupport (< 8.0) + bundler (>= 2.0) + dotenv litellm! - rake (~> 13.2) - rspec (~> 3.13) - rubocop (~> 1.73.1) - vcr (~> 6.1.0) - webmock (~> 3.24.0) + rake (>= 13.0) + rspec (~> 3.12) + rubocop (>= 1.0) + rubocop-rake + rubocop-rspec + vcr + webmock BUNDLED WITH - 2.6.2 + 2.6.5 diff --git a/README.md b/README.md index 85908dd..44010c5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # LiteLLM Ruby Client +Gem Version + A Ruby client for [LiteLLM](https://docs.litellm.ai/docs) with support for completions, embeddings, and image generation. ## Installation diff --git a/VERSION b/VERSION index 525b339..facbc65 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.0.rc2 \ No newline at end of file +1.0.0.rc3 \ No newline at end of file diff --git a/bin/console b/bin/console index dfb0352..e5dba7d 100755 --- a/bin/console +++ b/bin/console @@ -1,14 +1,16 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require "bundler/setup" -require "openai" +require "litellm" +require "dotenv/load" -# You can add fixtures and/or initialization code here to make experimenting -# with your gem easier. You can also use a different console, if you like. +require "irb" -# (If you use this, don't forget to add pry to your Gemfile!) -# require "pry" -# Pry.start +LiteLLM.configure do |config| + config.base_url = "http://localhost:8000" + config.debug = true + config.model = "gpt-4o" +end -require "irb" IRB.start(__FILE__) diff --git a/bin/start_litellm_server b/bin/start_litellm_server new file mode 100755 index 0000000..8985021 --- /dev/null +++ b/bin/start_litellm_server @@ -0,0 +1,8 @@ +#!/bin/bash + +# Get the directory where this script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +# Change to the test_server directory and run the start script +cd "$PROJECT_ROOT/test_server" && ./start_litellm.sh \ No newline at end of file diff --git a/lib/litellm.rb b/lib/litellm.rb index 63d0f53..a5507ec 100644 --- a/lib/litellm.rb +++ b/lib/litellm.rb @@ -1,17 +1,17 @@ # frozen_string_literal: true -require 'faraday' -require 'event_stream_parser' -require 'json' -require 'logger' - -require_relative 'litellm/version' -require_relative 'litellm/configuration' -require_relative 'litellm/streaming' -require_relative 'litellm/client' -require_relative 'litellm/errors' -require_relative 'litellm/tool_handler' -require_relative 'litellm/utils/tool_definition' +require "faraday" +require "event_stream_parser" +require "json" +require "logger" + +require_relative "litellm/version" +require_relative "litellm/configuration" +require_relative "litellm/streaming" +require_relative "litellm/client" +require_relative "litellm/errors" +require_relative "litellm/tool_handler" +require_relative "litellm/utils/tool_definition" module LiteLLM class Error < StandardError; end diff --git a/lib/litellm/client.rb b/lib/litellm/client.rb index 1497bd3..eeb965c 100644 --- a/lib/litellm/client.rb +++ b/lib/litellm/client.rb @@ -16,6 +16,14 @@ def initialize(config = LiteLLM.configuration) validate_configuration! end + # Get a list of available models from the LiteLLM server + # @return [Array] Array of model names + def models + response = make_get_request("/models") + parsed_response = handle_json_response(response) + parsed_response["data"].map { |model| model["id"] } + end + # Make a completion request # @param messages [Array] Array of message objects # @param model [String, nil] Optional model override @@ -131,13 +139,13 @@ def build_tools_schema(tools) end end - def make_request(endpoint, payload, &block) + def make_request(endpoint, payload, method: :post, &block) request_id = SecureRandom.uuid log_request(request_id, endpoint, payload) - response = connection.post(endpoint) do |req| + response = connection.send(method, endpoint) do |req| req.headers["X-Request-ID"] = request_id - req.body = payload.to_json + req.body = payload.to_json if method == :post req.options.on_data = Streaming.process_stream(&block) if payload[:stream] end @@ -148,7 +156,25 @@ def make_request(endpoint, payload, &block) raise end - def handle_tool_calls(response_data, tools, model, stream, &block) + # Make a GET request to the specified endpoint + # @param endpoint [String] The API endpoint to call + # @param payload [Hash] The request payload + # @param block [Proc] Optional block for handling streaming responses + # @return [Faraday::Response] The API response + def make_get_request(endpoint, payload = {}, &) + make_request(endpoint, payload, method: :get, &) + end + + # Make a POST request to the specified endpoint + # @param endpoint [String] The API endpoint to call + # @param payload [Hash] The request payload + # @param block [Proc] Optional block for handling streaming responses + # @return [Faraday::Response] The API response + def make_post_request(endpoint, payload = {}, &) + make_request(endpoint, payload, method: :post, &) + end + + def handle_tool_calls(response_data, tools, model, stream, &) LiteLLM.logger.debug "Handling tool calls, stream=#{stream}" begin @@ -160,7 +186,7 @@ def handle_tool_calls(response_data, tools, model, stream, &block) LiteLLM.logger.debug "Tool handler generated messages: #{@messages.inspect}" - completion(messages: @messages, model: model, tools: tools, stream: stream, &block) + completion(messages: @messages, model: model, tools: tools, stream: stream, &) rescue StandardError => e LiteLLM.logger.error "Error in handle_tool_calls: #{e.message}\n#{e.backtrace.join("\n")}" raise diff --git a/lib/litellm/configuration.rb b/lib/litellm/configuration.rb index dcc4e12..d2297ef 100644 --- a/lib/litellm/configuration.rb +++ b/lib/litellm/configuration.rb @@ -32,8 +32,7 @@ def logger end class Configuration - attr_reader :base_url, :timeout, :model, :embedding_model, :image_model, :embedding_dimensions, - :debug, :logger, :enable_message_redaction, :api_key + attr_reader :base_url, :timeout, :model, :embedding_model, :image_model, :embedding_dimensions, :debug, :logger, :enable_message_redaction, :api_key def initialize @base_url = DEFAULTS[:base_url] diff --git a/lib/litellm/errors.rb b/lib/litellm/errors.rb index dab3f73..71c5ba2 100644 --- a/lib/litellm/errors.rb +++ b/lib/litellm/errors.rb @@ -79,8 +79,6 @@ def self.handle_tool_error(message, original_error = nil) raise error end - private - def self.parse_json(body) JSON.parse(body) rescue JSON::ParserError => e diff --git a/lib/litellm/tool_handler.rb b/lib/litellm/tool_handler.rb index ef5017f..c342c47 100644 --- a/lib/litellm/tool_handler.rb +++ b/lib/litellm/tool_handler.rb @@ -11,7 +11,7 @@ def self.call(response:, available_tools: []) # Build a mapping of function names to tools @available_tools = {} available_tools.each do |tool| - tool.class.function_definitions.each do |function_name, definition| + tool.class.function_definitions.each do |_function_name, definition| @available_tools[definition[:name]] = tool end end @@ -28,8 +28,6 @@ def self.call(response:, available_tools: []) messages end - private - def self.execute_tool_calls(tool_calls) tool_calls.map do |tool_call| function_name = tool_call.dig("function", "name") diff --git a/lib/litellm/utils/tool_definition.rb b/lib/litellm/utils/tool_definition.rb index 5237187..9b9beaf 100644 --- a/lib/litellm/utils/tool_definition.rb +++ b/lib/litellm/utils/tool_definition.rb @@ -28,11 +28,11 @@ def normalized_tool_name private - def build_parameters(&block) + def build_parameters(&) return nil unless block_given? builder = ParameterBuilder.new - schema = builder.build(&block) + schema = builder.build(&) { type: "object", @@ -101,8 +101,8 @@ def initialize @required = [] end - def build(&block) - instance_eval(&block) + def build(&) + instance_eval(&) { properties: @properties, required: @required } end diff --git a/spec/Rakefile b/spec/Rakefile new file mode 100644 index 0000000..5f25233 --- /dev/null +++ b/spec/Rakefile @@ -0,0 +1,14 @@ +require "fileutils" + +namespace :vcr do + desc "Delete all VCR cassettes" + task :reset do + cassette_dir = "spec/fixtures/vcr_cassettes" + if File.directory?(cassette_dir) + FileUtils.rm_rf(Dir.glob("#{cassette_dir}/*")) + puts "All VCR cassettes have been deleted from #{cassette_dir}" + else + puts "No VCR cassettes directory found at #{cassette_dir}" + end + end +end diff --git a/spec/fixtures/vcr_cassettes/client_basic_chat_functionality_can_handle_multi-turn_conversations.yml b/spec/fixtures/vcr_cassettes/client_basic_chat_functionality_can_handle_multi-turn_conversations.yml new file mode 100644 index 0000000..4c0b9b9 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_basic_chat_functionality_can_handle_multi-turn_conversations.yml @@ -0,0 +1,115 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"Who was Ruby''s creator?"},{"role":"assistant","content":"Yukihiro + Matsumoto (Matz)"},{"role":"user","content":"What year did he create Ruby?"}],"model":"gpt-3.5-turbo","stream":false}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - f8e0cda5-7755-42b3-a5cb-9f7921516e95 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:42 GMT + Server: + - uvicorn + Content-Length: + - '638' + Content-Type: + - application/json + X-Litellm-Call-Id: + - e1dcddbc-c06e-435d-958c-7bf7d402f8c2 + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - '3.9999999999999996e-05' + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '587.4979999999999' + X-Litellm-Overhead-Duration-Ms: + - '3.082' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Tokens: + - '1999976' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:43 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '256' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999976' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_c2166dd745242d7e4f4398d124752c5c + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf3fe41b93f9cd-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - gpt-3.5-turbo + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"id":"chatcmpl-BJDqdLFkNAUOCWH0hZUcd7zZHre0h","created":1743921163,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Yukihiro + Matsumoto created Ruby in 1995.","role":"assistant","tool_calls":null,"function_call":null,"refusal":null,"annotations":[]}}],"usage":{"completion_tokens":14,"prompt_tokens":38,"total_tokens":52,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}},"service_tier":"default"}' + recorded_at: Sun, 06 Apr 2025 06:32:43 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/client_basic_chat_functionality_can_have_a_basic_conversation.yml b/spec/fixtures/vcr_cassettes/client_basic_chat_functionality_can_have_a_basic_conversation.yml new file mode 100644 index 0000000..4613f79 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_basic_chat_functionality_can_have_a_basic_conversation.yml @@ -0,0 +1,119 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"What''s 2 + 2?"}],"model":"gpt-3.5-turbo","stream":false}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - 7691928f-4110-44df-b3be-17042df55a89 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:40 GMT + Server: + - uvicorn + Content-Length: + - '612' + Content-Type: + - application/json + X-Litellm-Call-Id: + - 2a9764e3-400c-41f2-9be3-7b01d3ae1b3e + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - '2.1e-05' + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '1605.4060000000002' + X-Litellm-Overhead-Duration-Ms: + - '25.89' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Tokens: + - '1999994' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:42 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '242' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999994' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_e237c8496b923623d03975a657b750e2 + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-Set-Cookie: + - __cf_bm=a7CYAzbs4uuFYWCAK4g8o8noSxY8SNunLrsMfrzpXNA-1743921162-1.0.1.1-AgTkrWj.4i2dDH8C.ngpDiu80YidnfuFJ5O_sl.Fh4zDLERPz0HBrjhwKGXEB6XFZmKlj0MmFNOQrHB7pij6LwTdbYQJ_eM9lp7cc5kmTOU; + path=/; expires=Sun, 06-Apr-25 07:02:42 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None, _cfuvid=XBwh4kk.PnKz5mo7.vGNCpRSAB2MvTm_bXdVTHSROWU-1743921162814-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf3fda7e97f9cd-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - gpt-3.5-turbo + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"id":"chatcmpl-BJDqcIL5W8QB1ACkd6X3Hklp1YYbQ","created":1743921162,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"choices":[{"finish_reason":"stop","index":0,"message":{"content":"2 + + 2 equals 4.","role":"assistant","tool_calls":null,"function_call":null,"refusal":null,"annotations":[]}}],"usage":{"completion_tokens":9,"prompt_tokens":15,"total_tokens":24,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}},"service_tier":"default"}' + recorded_at: Sun, 06 Apr 2025 06:32:42 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/client_basic_chat_functionality_successfully_uses_the_system_prompt.yml b/spec/fixtures/vcr_cassettes/client_basic_chat_functionality_successfully_uses_the_system_prompt.yml new file mode 100644 index 0000000..47432c5 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_basic_chat_functionality_successfully_uses_the_system_prompt.yml @@ -0,0 +1,118 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"system","content":"You must respond like a pirate + and include the phrase \"Arrr matey!\" in your response."},{"role":"user","content":"Tell + me about the weather."}],"model":"gpt-3.5-turbo","stream":false}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - 502ee239-97b9-4126-91c4-3d183374b0b0 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:43 GMT + Server: + - uvicorn + Content-Length: + - '797' + Content-Type: + - application/json + X-Litellm-Call-Id: + - efb02880-dfc7-4640-b841-f9c4f1808616 + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - '9.800000000000001e-05' + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '966.668' + X-Litellm-Overhead-Duration-Ms: + - '3.231' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Tokens: + - '1999969' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:44 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '583' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999969' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_5a06eaea2c8d2ee5297a43a772861267 + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf3fe81997f9cd-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - gpt-3.5-turbo + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"id":"chatcmpl-BJDqdTtckhrdLSpolnIyA1vmBNu6x","created":1743921163,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Arrr + matey! The weather be fair with a bit o'' sunshine and a gentle breeze. But + keep a weather eye open, for ye never know when a storm be brewin'' on the + horizon. Best be stayin'' prepared, me hearty!","role":"assistant","tool_calls":null,"function_call":null,"refusal":null,"annotations":[]}}],"usage":{"completion_tokens":53,"prompt_tokens":37,"total_tokens":90,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}},"service_tier":"default"}' + recorded_at: Sun, 06 Apr 2025 06:32:44 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/client_embedding_generation_generates_embeddings_for_text_input.yml b/spec/fixtures/vcr_cassettes/client_embedding_generation_generates_embeddings_for_text_input.yml new file mode 100644 index 0000000..60c442d --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_embedding_generation_generates_embeddings_for_text_input.yml @@ -0,0 +1,126 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/embeddings + body: + encoding: UTF-8 + string: '{"input":"Hello, world!","model":"text-embedding-3-small","dimensions":1536}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - 4e7549ba-beae-4059-b6e0-19e8bfb91338 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:48 GMT + Server: + - uvicorn + Content-Length: + - '32918' + Content-Type: + - application/json + X-Litellm-Call-Id: + - 276fca61-3053-4b43-9025-7378167b40a2 + X-Litellm-Model-Id: + - 4a7f0868c5473e06a5f20ae08390f921cbf173866984f81d99f3a3501adf13e2 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - 8e-08 + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '881.2449999999999' + X-Litellm-Overhead-Duration-Ms: + - '3.876' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '1000000' + X-Ratelimit-Remaining-Tokens: + - '999997' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:50 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Allow-Origin: + - "*" + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Model: + - text-embedding-3-small + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '64' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Via: + - envoy-router-868dc8d978-28dcm + Llm-Provider-X-Envoy-Upstream-Service-Time: + - '34' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '1000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '999997' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_e6b770cf9af00804c6668f143f09df39 + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-Set-Cookie: + - __cf_bm=Fh5Uf9vcOJ9RL5IQ1UJjmiF3tJ6dykToGy7EJmiKtrs-1743921170-1.0.1.1-gi5W2I.sjW2_QWG8ilI0_leIXLO6i1N2Peq76NuI.YSM3FocxAGXm82CfGIwpkBKR9JeOUFyP.5dJn93uT3__bE09pHTxwDdT_HkzCRG5rw; + path=/; expires=Sun, 06-Apr-25 07:02:50 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None, _cfuvid=_i6IM7dUspv6Y1Ry0Yz3eCbETZJ3eXFTjDAgfSHBj2M-1743921170124-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf400cbb05f9f8-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - text-embedding-3-small + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"model":"text-embedding-3-small","data":[{"embedding":[-0.019184619188308716,-0.025279032066464424,-0.0017195191467180848,0.01884828321635723,-0.033795066177845,-0.01969585195183754,-0.02094702236354351,0.051580529659986496,-0.03212684020400047,-0.030377890914678574,-0.002145825419574976,-0.028978731483221054,-0.0024737531784921885,-0.031481072306632996,0.010332250036299229,0.018606122583150864,-0.04614533483982086,0.04146353527903557,0.0004418617463670671,0.04122137278318405,0.05367926508188248,0.0018733929609879851,0.0045674461871385574,0.010022819973528385,0.04786737635731697,0.0022013208363205194,-0.009834472090005875,0.03847686946392059,0.00089213193859905,-0.05211866647005081,0.051150016486644745,-0.032557349652051926,-0.014031948521733284,-0.012632790021598339,0.013271828182041645,0.018565760925412178,0.0016068464610725641,-0.0008185583865270019,-0.012753871269524097,-0.029705218970775604,-0.004443001933395863,-0.015323479659855366,0.025655729696154594,0.009107985533773899,-0.03686245530843735,0.020328164100646973,-0.04071014001965523,-0.002621741034090519,0.03549019992351532,0.04851314052939415,-0.03368743881583214,-0.002441801130771637,0.017260776832699776,0.07598508894443512,0.0009232430020347238,-0.04267434403300285,0.008381499908864498,0.0760388970375061,-0.047275424003601074,0.015081318095326424,0.014247204177081585,0.024700535461306572,0.010197714902460575,-0.000978738535195589,0.013789786025881767,-0.010103541426360607,-0.020704859867691994,-0.001531170797534287,-0.011717955581843853,0.04934725537896156,0.0010939337080344558,0.037831101566553116,-0.019332608208060265,0.005855614319443703,-0.046279869973659515,-0.0045439028181135654,-0.022359633818268776,0.008751469664275646,-0.02657056413590908,-0.05440575256943703,-0.04423494264483452,0.019332608208060265,-0.03091602772474289,-0.06037908419966698,-0.018888644874095917,0.004372371360659599,-0.02389332838356495,-0.012027384713292122,-0.016601556912064552,0.0022013208363205194,-0.00802498310804367,0.01529657281935215,-0.014960236847400665,0.01245789509266615,0.014502819627523422,-0.027687201276421547,-0.022790145128965378,0.05666593089699745,0.061024848371744156,-0.04929343983530998,0.014610446989536285,-0.027323957532644272,0.013251648284494877,-0.0205434188246727,0.0298666600137949,0.022507622838020325,0.00819987803697586,-0.04068323224782944,-0.026584018021821976,0.004533812869340181,-0.12474039196968079,0.009417415596544743,0.031803958117961884,-0.031077470630407333,0.005801800638437271,0.030835308134555817,0.05367926508188248,-0.039553143084049225,0.02342245727777481,-0.05375998839735985,0.00868420209735632,-0.01152287982404232,0.019534409046173096,-0.04184022918343544,-0.043131761252880096,-0.04297031834721565,0.005852250847965479,0.057526953518390656,-0.031481072306632996,0.019911106675863266,0.03944551572203636,0.03982221335172653,0.01127399131655693,-0.0002850449818652123,-0.045553382486104965,0.0018666662508621812,-0.040656328201293945,-0.013446723110973835,-0.049105092883110046,0.047275424003601074,0.056450676172971725,-0.047248516231775284,-0.010890567675232887,-0.00996228028088808,-0.005926244892179966,-0.04119446501135826,-0.008791829459369183,0.026086239144206047,-0.009948826394975185,-0.00625585438683629,0.030377890914678574,0.060648154467344284,-0.051230739802122116,0.025776810944080353,0.00377705623395741,-0.002621741034090519,0.024512186646461487,-0.016816813498735428,-0.02782173454761505,0.015054411254823208,0.05510533228516579,0.039580050855875015,-0.04436947777867317,-0.007897174917161465,-0.008146064355969429,0.00850930716842413,-0.011744862422347069,0.002426665974780917,-0.04361608624458313,-0.002248407807201147,0.023974047973752022,0.020933568477630615,-0.0211219172924757,-0.04509596526622772,-0.0192249808460474,0.02634185552597046,0.023449363186955452,-0.04958941787481308,-0.01622486114501953,-0.025238672271370888,0.02852131426334381,0.04541884735226631,0.0022921315394341946,0.019090445712208748,-0.026584018021821976,-0.011179816909134388,-0.004473272245377302,-0.006804082542657852,-0.011913030408322811,0.0008563962182961404,-0.03298785910010338,0.056235421448946,0.023476270958781242,0.0019675670191645622,0.004510269034653902,-0.03659338504076004,0.0669981837272644,0.00536792678758502,-0.021565880626440048,0.02427002415060997,-0.00038993984344415367,0.012706783600151539,-0.05136527121067047,-0.031884677708148956,-0.02342245727777481,-0.04186713695526123,-0.000014254876077757217,0.07087277621030807,-0.00837477296590805,-0.05246845632791519,0.058603230863809586,-0.014677714556455612,-0.0541904978454113,-0.0020482877735048532,-0.04932034760713577,-0.017879635095596313,0.041275184601545334,0.02229236625134945,-0.011226904578506947,-0.03161560744047165,-0.07937535643577576,0.07157235592603683,0.08513343334197998,-0.04122137278318405,0.030889121815562248,-0.013339095748960972,-0.008536214008927345,-0.008213330991566181,0.04996611550450325,0.01458354014903307,0.020879754796624184,0.01826978474855423,0.02429693192243576,-0.021431345492601395,-0.010500418022274971,-0.004325284156948328,0.036727920174598694,-0.021350625902414322,-0.005657176021486521,-0.0071572354063391685,-0.0387459360063076,-0.0011199996806681156,-0.006037235725671053,0.034252483397722244,0.04563410207629204,-0.016103779897093773,-0.042728159576654434,-0.022413447499275208,0.011119276285171509,0.04076395556330681,0.017960356548428535,0.02724323607981205,0.005418376997113228,-0.02036852389574051,0.017166603356599808,-0.01021116878837347,0.006659457925707102,-0.027458492666482925,0.042728159576654434,-0.02106810361146927,-0.048728395253419876,-0.062101125717163086,-0.035301852971315384,-0.02779482863843441,0.012632790021598339,-0.027404678985476494,0.004089849069714546,-0.013897414319217205,-0.016615010797977448,-0.013164200820028782,0.04385824874043465,-0.0075810193084180355,0.03266497701406479,-0.004355554468929768,-0.025803716853260994,0.0032876869663596153,-0.005179578438401222,-0.017328044399619102,-0.01981693133711815,0.0369969867169857,-0.025763357058167458,-0.0014664260670542717,0.010513870976865292,0.033983416855335236,-0.05131145939230919,0.008832190185785294,0.027081795036792755,-0.01144888624548912,0.007722280453890562,-0.02479470893740654,0.03277260437607765,0.02774101495742798,0.016278674826025963,-0.02039542980492115,0.025911344215273857,-0.002879038453102112,-0.0013175972271710634,-0.041651882231235504,0.038153983652591705,0.0025460654869675636,0.07695373892784119,0.0007592791225761175,0.04294341430068016,-0.005845523905009031,-0.001709428965114057,0.04154425486922264,0.015901979058980942,-0.01701861433684826,0.05951806530356407,-0.0013714110245928168,-0.008959997445344925,0.009585583582520485,0.05666593089699745,-0.02784864231944084,0.01347362995147705,-0.045849356800317764,0.019857292994856834,-0.019332608208060265,0.0009694892796687782,-0.04003746807575226,0.023449363186955452,-0.06199349835515022,0.009477955289185047,-0.015713630244135857,-0.015162038616836071,-0.00862366147339344,0.045553382486104965,0.021538974717259407,0.0020180174615234137,0.013756153173744678,0.014664260670542717,-0.02706834115087986,-0.004664984066039324,0.010830027051270008,0.007224502973258495,-0.016951346769928932,-0.04372371360659599,0.05427121743559837,0.012767324224114418,0.04579554498195648,-0.02657056413590908,-0.027902456000447273,0.02179458923637867,-0.03651266545057297,-0.011987023986876011,-0.0041941129602491856,0.033929601311683655,-0.02712215483188629,0.004288287367671728,0.004399278201162815,-0.017381858080625534,-0.005243482068181038,0.016413209959864616,-0.02464671991765499,-0.01762402057647705,-0.009868105873465538,0.0716799795627594,-0.024727441370487213,-0.019534409046173096,0.021256450563669205,-0.006609007250517607,-0.006915073376148939,0.00413020933046937,-0.01210810523480177,0.03384888172149658,0.030431704595685005,-0.007258136291056871,-0.04081776738166809,-0.007345583755522966,0.04385824874043465,0.013298735953867435,0.01475843507796526,0.032153744250535965,-0.0036324316170066595,-0.03479062393307686,-0.015175491571426392,0.0117986761033535,-0.00017373869195580482,0.059625692665576935,-0.009249246679246426,0.04036035016179085,0.03371434658765793,-0.019736211746931076,-0.026610923931002617,0.010325523093342781,-0.005855614319443703,0.0206914059817791,0.011381618678569794,-0.01701861433684826,0.008576574735343456,0.03352599963545799,-0.011563240550458431,0.004426185041666031,0.00951158907264471,0.007809727918356657,-0.01757020689547062,-0.021808043122291565,-0.015188945457339287,-0.022682517766952515,-0.05763458088040352,0.04716779664158821,-0.023664619773626328,0.007527205627411604,0.011401799507439137,-0.02022053487598896,-0.03347218409180641,0.012229186482727528,0.05112311244010925,-0.0036391583271324635,-0.023503176867961884,0.004083122126758099,-0.052280109375715256,0.033956509083509445,0.03191158547997475,-0.025036871433258057,0.00199615559540689,-0.023261016234755516,-0.03928407281637192,-0.0007407806115224957,-0.0041201189160346985,0.00614150008186698,0.019036632031202316,-0.014153029769659042,0.025911344215273857,-0.032557349652051926,0.04006437584757805,0.03062005341053009,-0.028063897043466568,0.0187944695353508,-0.08260418474674225,-0.0015959155280143023,-0.03573236241936684,-0.00360216130502522,0.03624359518289566,0.02631494775414467,-0.04617224261164665,0.002162642078474164,-0.006302941590547562,0.058603230863809586,0.02322065457701683,-0.0025494287256151438,0.009013812057673931,0.008832190185785294,0.0022988582495599985,-0.009350148029625416,-0.05384070798754692,-0.003153152298182249,-0.013857053592801094,-0.040548697113990784,0.017812367528676987,0.0035248040221631527,-0.04358917847275734,0.013177654705941677,0.013978134840726852,0.03134653717279434,0.015175491571426392,-0.0002869368763640523,0.01687062717974186,0.01992456056177616,0.026449482887983322,-0.0039048639591783285,0.0231668408960104,-0.04773284122347832,0.052172478288412094,0.006410568952560425,-0.0035718909930437803,-0.02284395880997181,0.023328281939029694,-0.016305582597851753,-0.02229236625134945,-0.012525161728262901,0.025077231228351593,0.008226784877479076,-0.023758793249726295,-0.020314710214734077,-0.018202519044280052,-0.05445956811308861,0.01547146774828434,-0.044154223054647446,0.0001709008647594601,0.027525758370757103,0.007002520840615034,0.04143662750720978,0.02919398620724678,-0.003316275542601943,0.009773931466042995,-0.07211049646139145,0.026732005178928375,-0.004042761866003275,-0.010231348685920238,-0.034333206713199615,0.06193968653678894,0.0640922337770462,-0.015484921634197235,-0.009706663899123669,-0.008280598558485508,0.005670629441738129,-0.013251648284494877,-0.002973212394863367,-0.02879038266837597,-0.007143781986087561,-0.04157116264104843,-0.0066998181864619255,0.01987074688076973,0.06199349835515022,-0.006968887057155371,-0.04687182232737541,-0.014193389564752579,0.007399397436529398,-0.03374125435948372,-0.043481551110744476,-0.008139337413012981,0.007634832989424467,-0.005532731302082539,0.012087925337255001,-0.003134653903543949,0.009518316015601158,0.028252245858311653,-0.012000477872788906,-0.030835308134555817,0.026624377816915512,0.032557349652051926,-0.006575373932719231,-0.00798462238162756,-0.0033515908289700747,0.019386421889066696,-0.05160743370652199,-0.022104019299149513,0.008516034111380577,0.027875548228621483,0.019628584384918213,0.004991230089217424,0.028655849397182465,0.01359471119940281,-0.007782821077853441,-0.01109909638762474,-0.0005763962399214506,0.011953390203416348,-0.004738977644592524,-0.022790145128965378,0.007096694782376289,0.02948996238410473,-0.006481199525296688,-0.0007987986318767071,-0.011475793085992336,-0.00785008817911148,0.04687182232737541,0.006397115532308817,-0.002424984471872449,0.025157952681183815,0.00809897668659687,-0.016332488507032394,-0.013897414319217205,-0.012081198394298553,0.03387578949332237,0.0027613206766545773,-0.02149861305952072,-0.006656094454228878,0.015148584730923176,0.06586809456348419,0.004765884950757027,-0.010439877398312092,0.013762879185378551,0.027956269681453705,-0.00009002249862533063,0.03177705034613609,0.007190869189798832,-0.0212699044495821,-0.03772347420454025,-0.038530681282281876,-0.03616287559270859,-0.024014407768845558,-0.026032425463199615,-0.06387697905302048,0.021175730973482132,-0.007587745785713196,0.033929601311683655,0.026355309411883354,0.0013167564757168293,-0.004880239255726337,-0.004715434275567532,-0.0167495459318161,-0.0015866663306951523,0.029705218970775604,-0.04119446501135826,0.048755303025245667,0.02182149700820446,0.014368284493684769,0.024700535461306572,-0.032207559794187546,0.012188825756311417,0.003978857770562172,0.009249246679246426,0.04264743626117706,0.0012848045444115996,-0.0352480411529541,-0.018000716343522072,-0.02034161612391472,-0.029382335022091866,0.03702389448881149,0.011785222217440605,0.006400479003787041,-0.022238552570343018,-0.04845932871103287,0.027552666142582893,-0.014166482724249363,-0.01102510280907154,-0.0018464860040694475,0.0025527921970933676,-0.04958941787481308,-0.024956149980425835,0.03772347420454025,-0.021565880626440048,-0.05410977825522423,-0.004147026222199202,0.03053933195769787,-0.011354711838066578,0.011778495274484158,-0.015202398411929607,-0.021888762712478638,-0.008253691717982292,-0.042378369718790054,0.0026671465020626783,0.028225338086485863,-0.00250906846486032,0.016789905726909637,-0.018606122583150864,0.0023072666954249144,-0.02369152568280697,0.01987074688076973,0.012901858426630497,0.014960236847400665,0.0059800585731863976,-0.0016825221246108413,-0.006575373932719231,-0.005008046980947256,-0.008657295256853104,-0.01654774323105812,0.00396204087883234,-0.02334173582494259,0.04958941787481308,0.020852847024798393,0.0028454046696424484,-0.01757020689547062,0.05203794687986374,0.014260657131671906,0.013083480298519135,0.03137344494462013,0.009531769901514053,-0.013339095748960972,0.026705099269747734,0.004022581502795219,0.0033717709593474865,0.0017573569202795625,0.012908585369586945,-0.020489605143666267,-0.028117710724473,-0.01844467967748642,-0.021027741953730583,0.02234617993235588,-0.004634713754057884,0.07496262341737747,-0.016278674826025963,-0.006239037495106459,-0.009074351750314236,0.010049727745354176,0.019467143341898918,0.014193389564752579,-0.008072069846093655,-0.019561316817998886,0.00862366147339344,-0.014314470812678337,0.04251290112733841,0.0033566358033567667,0.03659338504076004,0.0019103899830952287,-0.030108822509646416,-0.007305223494768143,0.0018733929609879851,-0.024431465193629265,0.01335927564650774,0.006326484959572554,-0.04105992987751961,-0.03629740700125694,-0.0020953749772161245,0.028924917802214622,0.029785938560962677,0.01069549284875393,-0.003615614725276828,-0.0005154352984391153,-0.02922089397907257,-0.021808043122291565,-0.0036324316170066595,0.04243218153715134,-0.010480238124728203,-0.03156179562211037,0.022709423676133156,0.004443001933395863,-0.01286149863153696,-0.03826161101460457,0.024660173803567886,-0.011004921980202198,-0.006393752060830593,0.02114882320165634,0.026906900107860565,-0.023462817072868347,-0.024135489016771317,0.03446773812174797,0.028036991134285927,0.014341377653181553,-0.04700635373592377,0.005378016736358404,-0.02914017252624035,0.0093232411891222,-0.05881848558783531,-0.0029210804495960474,-0.029678311198949814,-0.060701966285705566,-0.006797355599701405,0.002322401851415634,-0.034306298941373825,0.0004843242058996111,-0.023651165887713432,0.01073585357517004,-0.021310264244675636,-0.035005878657102585,0.0028050444088876247,-0.01596924476325512,0.03126581758260727,0.018256332725286484,0.0285482220351696,-0.01844467967748642,0.013688885606825352,0.02581717073917389,0.0167495459318161,-0.0010073271114379168,-0.023826060816645622,-0.01404540240764618,0.015054411254823208,-0.01493333000689745,-0.022978492081165314,0.02494269609451294,0.04407350346446037,0.022938132286071777,-0.016655370593070984,0.012807684950530529,0.001075435196980834,0.001704383990727365,-0.016386302188038826,-0.00007651649502804503,0.011771769262850285,0.01046005729585886,-0.028575127944350243,-0.003598797833546996,0.004406005144119263,-0.012377174571156502,0.017704740166664124,-0.0015740536618977785,-0.017112787812948227,0.021565880626440048,-0.01887519098818302,0.030862214043736458,0.00434210104867816,0.05147290229797363,-0.020449243485927582,0.006454292684793472,0.011926483362913132,0.0012721918756142259,-0.001787627232261002,0.003323002252727747,0.04606461524963379,-0.003995674662292004,0.01133453194051981,0.0022013208363205194,0.0026419213972985744,0.0064273858442902565,-0.04157116264104843,0.022332727909088135,-0.042324554175138474,-0.018431227654218674,-0.006249127443879843,0.009444322437047958,-0.024108583107590675,-0.0015706903068348765,0.01404540240764618,-0.017812367528676987,0.0015967563958838582,0.011516153812408447,0.022211646661162376,-0.04229764640331268,-0.024175850674510002,-0.046279869973659515,-0.01168432179838419,0.005357836373150349,0.005263662431389093,0.044907618314027786,-0.01824287883937359,-0.032207559794187546,0.010641679167747498,0.003783782944083214,0.004570809658616781,-0.04751758649945259,0.02071831375360489,0.04009127989411354,0.004762521479278803,-0.026678191497921944,-0.014395191334187984,0.008838917128741741,0.006434112787246704,-0.008267145603895187,0.021525520831346512,0.03406413644552231,-0.012101378291845322,-0.012356993742287159,0.005690809339284897,-0.03982221335172653,0.006400479003787041,0.0035483473911881447,0.02304575964808464,-0.00011897894728463143,0.02071831375360489,0.008327685296535492,-0.018552307039499283,-0.014206843450665474,0.046898726373910904,0.0218484029173851,-0.023974047973752022,0.014287563972175121,0.03376815840601921,-0.003514713840559125,-0.018565760925412178,0.0023139934055507183,-0.006820899434387684,-0.006615734193474054,0.006568646989762783,0.02922089397907257,0.00862366147339344,-0.01687062717974186,-0.03522113338112831,-0.010668586008250713,0.0003584083169698715,-0.0030942936427891254,0.0010552549501881003,-0.0161710474640131,0.02601897343993187,-0.008072069846093655,0.021538974717259407,-0.02456600032746792,-0.0029093085322529078,0.012942219153046608,-0.043454643338918686,-0.012854771688580513,0.026207320392131805,-0.006733451969921589,-0.03209993243217468,0.016063420102000237,-0.026032425463199615,-0.012195552699267864,-0.002974894130602479,-0.01949404925107956,-0.005391470156610012,0.019655490294098854,0.018485041335225105,0.017139695584774017,0.033283837139606476,-0.014731528237462044,-0.0006108707166276872,-0.012377174571156502,0.0495356023311615,0.050100646913051605,0.0015606002416461706,-0.00031111104181036353,0.001344504184089601,-0.02948996238410473,0.020758673548698425,0.04474617540836334,-0.05475554242730141,0.02784864231944084,-0.006649367976933718,-0.007708827033638954,0.022790145128965378,0.04264743626117706,0.010338976047933102,0.006767085287719965,-0.036028340458869934,-0.026032425463199615,0.01494678296148777,0.02324756234884262,0.01347362995147705,0.008246964775025845,-0.014341377653181553,0.003151470795273781,-0.0016581377713009715,-0.00967303104698658,0.006259217858314514,-0.02124299854040146,-0.010675312951207161,0.027202876284718513,0.014879516325891018,0.009269427508115768,0.010675312951207161,-0.007937535643577576,0.02121609076857567,0.02779482863843441,0.018135251477360725,-0.007567565888166428,-0.0042714704759418964,-0.002071831375360489,-0.006245764438062906,0.0018363959388807416,-0.014650807715952396,-0.0521455742418766,0.02922089397907257,0.024485278874635696,0.047975003719329834,0.009081078693270683,0.015592548996210098,0.022238552570343018,-0.0061784968711435795,0.006121319718658924,-0.01894245855510235,-0.04353536665439606,-0.016937894746661186,0.0056975362822413445,-0.004089849069714546,-0.009121439419686794,-0.032853323966264725,0.0556434690952301,0.006935253739356995,-0.017435671761631966,0.029086358845233917,0.029624497517943382,-0.016036512330174446,0.01809488981962204,0.007897174917161465,-0.013453450053930283,-0.051580529659986496,0.030512424185872078,0.0027512304950505495,-0.031104376539587975,-0.03099674917757511,0.03879975154995918,0.0193729680031538,0.00539819709956646,0.06226256862282753,0.00551255140453577,0.017906542867422104,-0.004089849069714546,-0.015229305252432823,-0.0192249808460474,-0.023651165887713432,-0.002043242799118161,0.0007563361432403326,0.007587745785713196,-0.010830027051270008,0.008246964775025845,0.044127315282821655,-0.008919637650251389,-0.005472190678119659,0.012404081411659718,-0.01666882447898388,-0.016426661983132362,-0.02474089525640011,-0.012195552699267864,-0.0016488884575664997,-0.004607806913554668,-0.01870029605925083,-0.013830146752297878,0.009713390842080116,0.015632908791303635,-0.0273912250995636,0.0006550148827955127,0.03656647726893425,-0.01140852551907301,0.0023745340295135975,-0.017287682741880417,-0.035328760743141174,0.025884438306093216,0.04052179306745529,-0.006302941590547562,0.023624258115887642,0.02266906388103962,0.02584407851099968,-0.005145944654941559,-0.005293932743370533,0.001347026671282947,0.01459699310362339,0.006010328885167837,-0.016184501349925995,-0.014475912787020206,0.007305223494768143,-0.006706545129418373,-0.02092011459171772,0.03452155366539955,0.03976839780807495,-0.003048888174816966,-0.025938251987099648,-0.011354711838066578,-0.02129681222140789,-0.0167495459318161,0.0022753148805350065,0.01684371940791607,0.02414894290268421,-0.002409849315881729,0.0163190346211195,-0.0012705102562904358,-0.006528286729007959,0.006094412878155708,0.012955672107636929,-0.015727084130048752,0.030700773000717163,-0.003481080289930105,-0.014085762202739716,0.025857530534267426,0.026503296568989754,0.005149308126419783,-0.029086358845233917,0.04140971973538399,-0.004678437486290932,0.0144220981746912,-0.025951705873012543,-0.005445283837616444,0.005421740468591452,-0.009706663899123669,-0.007971169427037239,-0.018955910578370094,0.010769487358629704,-0.011213450692594051,-0.02919398620724678,0.027606479823589325,-0.018256332725286484,0.02114882320165634,-0.00399231119081378,0.0361359678208828,-0.00720432261005044,0.03137344494462013,-0.02589789219200611,-0.012067744508385658,-0.017731647938489914,-0.009471229277551174,-0.004722161218523979,-0.018377412110567093,-0.01338618341833353,0.02324756234884262,0.0035853444132953882,-0.004755794536322355,-0.03029716946184635,0.029032545164227486,0.0035449841525405645,-0.010628225281834602,-0.015942338854074478,0.029059452936053276,-0.00629285117611289,0.02421621046960354,0.022063657641410828,0.00978738535195589,0.010103541426360607,-0.0140588553622365,0.005495734512805939,0.02281705103814602,-0.054325032979249954,-0.029059452936053276,-0.02983975224196911,0.00378041947260499,0.016776451840996742,-0.028063897043466568,0.023287922143936157,0.003978857770562172,0.00819987803697586,0.03656647726893425,-0.01899627223610878,0.014502819627523422,-0.012787504121661186,0.033283837139606476,-0.009020538069307804,-0.018108343705534935,0.02992047369480133,-0.025938251987099648,0.016467023640871048,-0.011011648923158646,0.021808043122291565,-0.011038555763661861,0.023328281939029694,-0.031185097992420197,-0.03979530557990074,-0.031158190220594406,0.0022265459410846233,0.005660539027303457,0.029032545164227486,-0.014664260670542717,0.0030051644425839186,0.0048028817400336266,-0.026301495730876923,0.016480475664138794,-0.044477105140686035,0.018054530024528503,0.027081795036792755,0.010076634585857391,0.05316803604364395,-0.02642257697880268,-0.00046036025742068887,0.02024744264781475,0.023355189710855484,-0.018955910578370094,-0.010049727745354176,0.007998076267540455,-0.01303639356046915,-0.01387050747871399,0.0035550743341445923,0.039230260998010635,0.021579334512352943,-0.00399231119081378,0.003669428639113903,-0.0096124904230237,0.02409512922167778,0.0008652250398881733,-0.022588342428207397,0.00023102096747606993,0.00042714705341495574,-0.0077895475551486015,0.02024744264781475,-0.03688935935497284,0.02004563994705677,-0.0068747131153941154,-0.008637115359306335,-0.009471229277551174,0.05306040868163109,0.021606240421533585,-0.03347218409180641,0.007365764118731022,0.02414894290268421,0.005129127763211727,0.022440355271100998,-0.04375062137842178,0.015431107021868229,0.05074641481041908,-0.017301136627793312,-0.01722041703760624,-0.027256689965724945,0.022009843960404396,0.04829788580536842,-0.007305223494768143,-0.008361319079995155,-0.0010258256224915385,-0.03801944851875305,-0.0056437221355736256,-0.006834352854639292,0.10095468908548355,-0.004984503146260977,-0.022655609995126724,0.004284923896193504,0.038180891424417496,-0.028763476759195328,0.007809727918356657,-0.0008156154071912169,-0.009491409175097942,-0.015256212092936039,-0.012309907004237175,-0.012666423805058002,-0.04536503553390503,-0.008018256165087223,-0.008240237832069397,0.02954377606511116,-0.006114593241363764,-0.03207302466034889,-0.007856815122067928,0.0016387983923777938,0.008119157515466213,-0.050477344542741776,-0.009168526157736778,0.005889247637242079,0.0017842638771981,-0.02427002415060997,-0.04014509543776512,-0.0161710474640131,0.019964920356869698,0.03839614614844322,-0.014368284493684769,0.00034768760087899864,0.04614533483982086,-0.018727201968431473,-0.01388396043330431,0.020207082852721214,-0.044826894998550415,-0.021686961874365807,-0.03686245530843735,0.0249157901853323,-0.03627050295472145,0.0027461855206638575,0.028010083362460136,-0.02529248595237732,0.0016228224849328399,0.005280479323118925,0.00720432261005044,-0.00756083894520998,0.0009156754822470248,-0.01444900594651699,-0.005129127763211727,0.04116755723953247,-0.004897055681794882,0.012962399050593376,0.01423375029116869,-0.01203411165624857,0.03374125435948372,0.055078424513339996,0.05591253936290741,-0.01292203925549984,0.0007449848344549537,0.012054291553795338,0.0142741110175848,0.010372609831392765,0.005805163644254208,-0.015780897811055183,-0.0396338626742363,0.038934286683797836,-0.010325523093342781,0.04700635373592377,-0.008455493487417698,0.0192249808460474,0.01477188803255558,0.03387578949332237,0.009242520667612553,0.012881678529083729,-0.015498374588787556,0.022978492081165314,-0.001986065646633506,0.039176445454359055,-0.007540659047663212,-0.023180294781923294,0.007991349324584007,0.0419478565454483,-0.014327924698591232,0.03239590674638748,-0.006343301851302385,-0.005465464200824499,-0.01512167789041996,-0.008462220430374146,0.0028403596952557564,-0.0056336321868002415,0.023059213533997536,0.0068612596951425076,-0.012552069500088692,0.025184858590364456,-0.054002150893211365,0.020906662568449974,-0.02377224713563919,0.020301256328821182,0.020435791462659836,0.019184619188308716,0.03352599963545799,0.019413327798247337,-0.028951825574040413,-0.011065462604165077,-0.008125883527100086,-0.0582803450524807,-0.03939170390367508,0.031077470630407333,-0.00020705700444523245,-0.009794111363589764,0.015135131776332855,-0.004722161218523979,0.05106929689645767,-0.07060370594263077,-0.03624359518289566,-0.03161560744047165,0.0004237836692482233,0.013513990677893162,0.045176684856414795,0.03314930200576782,0.014287563972175121,-0.022453809157013893,0.03656647726893425,-0.008280598558485508,0.04996611550450325,0.013379456475377083,0.025184858590364456,-0.021888762712478638,0.003402041271328926,-0.014153029769659042,-0.001526966574601829,0.014502819627523422,0.02059723250567913,-0.0005839638179168105,0.013628344982862473,-0.012948946096003056,-0.0027663656510412693,0.00431183073669672,0.0013747744960710406,-0.03645884990692139,0.013379456475377083,-0.009255973622202873,-0.01739531196653843,-0.0028117711190134287,0.025938251987099648,-0.00592960836365819,-0.03559783101081848,-0.039902932941913605,-0.003255734918639064,-0.021754229441285133,0.009269427508115768,0.0029849843122065067,-0.0046414402313530445,-0.004863422363996506,-0.029759032651782036,0.0034777168184518814,0.01704552210867405,-0.03573236241936684,-0.047329239547252655,-0.013063300400972366,-0.01346017699688673,-0.0034642633982002735,-0.015928884968161583,0.02339554950594902,-0.02339554950594902,0.021660054102540016,-0.00933669414371252,-0.0029160352423787117,0.022951586171984673,-0.031050562858581543,-0.019278794527053833,0.014435552060604095,0.005872431211173534,-0.01672263815999031,0.0056100888177752495,0.014354831539094448,0.04210929945111275,0.008711108937859535,-0.06419986486434937,-0.037077710032463074,0.02199639193713665,-0.018363960087299347,-0.0029059452936053276,0.024135489016771317,-0.014987143687903881,-0.019305700436234474,-0.012942219153046608,-0.03269188478589058,0.0018212607828900218,-0.018982818350195885,-0.005663902498781681,-0.005209848750382662,-0.013574531301856041,-0.01777200773358345,-0.03476371616125107,-0.04081776738166809,0.02104119583964348,-0.010069907642900944,-0.047652121633291245,-0.026624377816915512,0.017637472599744797,0.012720237486064434,0.03164251521229744,0.016426661983132362,-0.01779891550540924,0.023005399852991104,-0.013843600638210773,-0.018337052315473557,-0.004385824780911207,0.02414894290268421,-0.01241080742329359,0.009155073203146458,0.051499806344509125,0.05456719547510147,-0.0008387385169044137,0.032207559794187546,-0.0035315307322889566,0.01722041703760624,-0.006262580864131451,-0.0008812010055407882,0.01404540240764618,-0.013466903939843178,-0.013756153173744678,0.019103899598121643,-0.005468827672302723,-0.020059093832969666,-0.02039542980492115,-0.015188945457339287,0.02494269609451294,0.011812129057943821,0.025009963661432266,0.041624974459409714,-0.013184381648898125,0.008354592137038708,-0.004651530645787716,0.0001839338947320357,-0.01409921608865261,-0.008408406749367714,-0.008226784877479076,-0.02159278839826584,0.006181860342621803,-0.017879635095596313,-0.0016127323033288121,0.037804193794727325,0.03376815840601921,-0.0008383181411772966,0.01814870350062847,-0.001523603219538927,0.0018178974278271198,0.028063897043466568,-0.02304575964808464,-0.011879396624863148,0.008421859703958035,-0.0053611998446285725,0.004611169919371605,-0.006888166535645723,0.021552426740527153,-0.00696216057986021,-0.026879994198679924,-0.006548467092216015,0.008442039601504803,-0.032503534108400345,-0.00047045035171322525,-0.02989356592297554,0.02217128686606884,0.019655490294098854,-0.0013302098959684372,0.02774101495742798,-0.010715672746300697,0.006901619955897331,0.008119157515466213,-0.028225338086485863,-0.02441801130771637,0.019763117656111717,0.032853323966264725,-0.01812179759144783,0.022252006456255913,-0.01359471119940281,-0.009713390842080116,-0.020274348556995392,-0.011791949160397053,0.007688646670430899,-0.014072309248149395,0.015632908791303635,-0.008213330991566181,0.0011511108605191112,-0.031131284311413765,-0.011132730171084404,0.06769776344299316,-0.008805283345282078,0.008576574735343456,0.02097392827272415,-0.01494678296148777,0.005024863872677088,-0.012007203884422779,0.005277115851640701,0.020987382158637047,-0.0036593384575098753,-0.024835068732500076,0.0002877777151297778,0.004056215286254883,-0.013830146752297878,-0.004335374105721712,0.02342245727777481,0.018754109740257263,0.008812010288238525,-0.012013930827379227,0.0008509307517670095,0.012518435716629028,0.020987382158637047,-0.008845643140375614,-0.005741260014474392,-0.017085881903767586,0.020906662568449974,-0.00992191955447197,-0.011966844089329243,-0.004540539346635342,0.03592071309685707,0.02669164538383484,0.014960236847400665,-0.007365764118731022,-0.01044660434126854,-0.02784864231944084,-0.025978611782193184,0.005667265970259905,-0.0040965755470097065,0.027875548228621483,-0.03939170390367508,0.0031649242155253887,0.004587626550346613,0.04038725793361664,-0.028359873220324516,0.036055248230695724,-0.027902456000447273,-0.021552426740527153,0.011132730171084404,0.022359633818268776,-0.015807803720235825,0.025305939838290215,-0.005102220922708511,0.002261861227452755,0.013083480298519135,0.011643961071968079,0.023234108462929726,0.02879038266837597,-0.016117233783006668,0.0093972347676754,0.00861020851880312,-0.023852966725826263,0.008832190185785294,0.020112907513976097,0.001081321039237082,-0.05688118934631348,0.02919398620724678,0.003302822122350335,-0.03191158547997475,0.02287086471915245,-0.02199639193713665,-0.0019053448922932148,-0.041275184601545334,-0.01867338828742504,0.009121439419686794,-0.029651403427124023,0.06037908419966698,-0.02502341754734516,-0.01777200773358345,0.03376815840601921,-0.020260896533727646,-0.017206963151693344,-0.02537320740520954,0.03094293549656868,-0.03403722867369652,0.01964203640818596,-0.006319758016616106,-0.010022819973528385,-0.031104376539587975,0.014637353830039501,0.013218014501035213,-0.020489605143666267,-0.02211747132241726,0.0115834204480052,-0.005505824461579323,0.043777525424957275,0.004540539346635342,-0.02264215610921383,0.0056336321868002415,-0.010594592429697514],"index":0,"object":"embedding"}],"object":"list","usage":{"completion_tokens":0,"prompt_tokens":4,"total_tokens":4,"completion_tokens_details":null,"prompt_tokens_details":null}}' + recorded_at: Sun, 06 Apr 2025 06:32:50 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/client_embedding_generation_generates_embeddings_with_custom_dimensions.yml b/spec/fixtures/vcr_cassettes/client_embedding_generation_generates_embeddings_with_custom_dimensions.yml new file mode 100644 index 0000000..a66a757 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_embedding_generation_generates_embeddings_with_custom_dimensions.yml @@ -0,0 +1,121 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/embeddings + body: + encoding: UTF-8 + string: '{"input":"Hello, world!","model":"text-embedding-3-small","dimensions":256}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - 7544a591-3fed-4047-b4c8-9ae235f17873 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:49 GMT + Server: + - uvicorn + Content-Length: + - '5583' + Content-Type: + - application/json + X-Litellm-Call-Id: + - 632088cc-7dcf-421d-93f1-58e082d20d8a + X-Litellm-Model-Id: + - 4a7f0868c5473e06a5f20ae08390f921cbf173866984f81d99f3a3501adf13e2 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - 8e-08 + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '686.484' + X-Litellm-Overhead-Duration-Ms: + - '2.684' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '1000000' + X-Ratelimit-Remaining-Tokens: + - '999997' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:50 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Allow-Origin: + - "*" + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Model: + - text-embedding-3-small + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '74' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Via: + - envoy-router-755cb696bc-42588 + Llm-Provider-X-Envoy-Upstream-Service-Time: + - '65' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '1000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '999997' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_709033530f18b86c6b744bbde7c18569 + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf40122869f9f8-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - text-embedding-3-small + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"model":"text-embedding-3-small","data":[{"embedding":[-0.0375906340777874,-0.04953211918473244,-0.0033692517317831516,0.036931611597537994,-0.06621856242418289,-0.038592349737882614,-0.04104391112923622,0.1010676696896553,-0.06294981390237808,-0.05952289700508118,-0.004204562399536371,-0.05678136646747589,-0.004847109317779541,-0.061684492975473404,0.02024516649544239,0.0364571176469326,-0.09041786938905716,0.08124427497386932,0.0008657905855216086,0.08076977729797363,0.10517996549606323,0.003670754376798868,0.0089495237916708,0.019638866186141968,0.09379205852746964,0.004313301295042038,-0.01926981285214424,0.07539215683937073,0.0017480567330494523,-0.10212210565805435,0.10022412240505219,-0.0637933611869812,-0.027494411915540695,-0.02475287951529026,0.02600502222776413,0.036378033459186554,0.003148479387164116,-0.0016038956819102168,-0.024990128353238106,-0.058204855769872665,-0.008705684915184975,-0.03002505749464035,0.05027022585272789,0.017846325412392616,-0.07222884893417358,0.039831310510635376,-0.07976806163787842,-0.005137079395353794,0.06954003870487213,0.09505738317966461,-0.06600768119096756,-0.00478450208902359,0.03382102772593498,0.1488863229751587,0.0018090163357555866,-0.08361675590276718,0.016422836109995842,0.14899177849292755,-0.09263218194246292,0.02955056168138981,0.027916187420487404,0.04839860275387764,0.01998155750334263,-0.0019177549984306097,0.027019916102290154,-0.019797030836343765,-0.04056941717863083,-0.003000199329108,-0.02296033874154091,0.09669175744056702,0.0021434701047837734,0.07412683218717575,-0.03788060322403908,0.011473579332232475,-0.09068147838115692,-0.008903391659259796,-0.04381180554628372,0.017147760838270187,-0.05206276476383209,-0.1066034585237503,-0.08667462319135666,0.03788060322403908,-0.060577332973480225,-0.1183076947927475,-0.03701069578528404,0.008567290380597115,-0.04681694880127907,-0.02356663905084133,-0.03252934291958809,0.004313301295042038,-0.015724273398518562,0.029972337186336517,-0.029313314706087112,0.0244101881980896,0.028417043387889862,-0.054250720888376236,-0.04465535283088684,0.11103208363056183,0.11957301199436188,-0.09658631682395935,0.028627930209040642,-0.0535389743745327,0.025965480133891106,-0.040253084152936935,0.05852118507027626,0.0441017746925354,0.016066964715719223,-0.07971534132957458,-0.05208912491798401,0.008883621543645859,-0.244418203830719,0.01845262572169304,0.06231715530157089,-0.06089366599917412,0.011368135921657085,0.06041916832327843,0.10517996549606323,-0.07750102877616882,0.0458943173289299,-0.10533813387155533,0.017015956342220306,-0.022578105330467224,0.03827601671218872,-0.08198238164186478,-0.08451302349567413,-0.08419669419527054,0.011466989293694496,0.11271918565034866,-0.061684492975473404,0.039014123380184174,0.0772901400923729,0.07802824676036835,0.022090429440140724,-0.0005585214239545166,-0.08925798535346985,0.0036575740668922663,-0.07966262102127075,-0.02634771354496479,-0.09621725976467133,0.09263218194246292,0.11061031371355057,-0.09257946163415909,-0.021339144557714462,-0.019520241767168045,-0.011611973866820335,-0.0807170569896698,-0.017226845026016235,0.05111377313733101,-0.01949388161301613,-0.012257815338671207,0.05952289700508118,0.11883491277694702,-0.10038228332996368,0.050507474690675735,0.007400820963084698,-0.005137079395353794,0.04802954941987991,-0.03295111656188965,-0.054514329880476,0.029497839510440826,0.10797422379255295,0.07755374908447266,-0.08693823218345642,-0.015473844483494759,-0.015961522236466408,0.016673265025019646,-0.02301306091248989,0.004754846449941397,-0.08546201884746552,-0.00440556462854147,0.046975113451480865,0.041017550975084305,-0.04138660430908203,-0.0883617177605629,-0.03766971826553345,0.051614630967378616,0.045947037637233734,-0.09716625511646271,-0.031791239976882935,-0.04945303872227669,0.05588509514927864,0.08899437636137009,0.004491237457841635,0.037406109273433685,-0.05208912491798401,-0.02190590277314186,-0.008764997124671936,-0.013332022354006767,-0.023342572152614594,0.0016780357109382749,-0.06463690847158432,0.11018853634595871,0.045999761670827866,0.0038552808109670877,0.008837489411234856,-0.07170163094997406,0.13127724826335907,0.010517996735870838,-0.04225651174783707,0.04755505174398422,-0.0007640540134161711,0.0248978640884161,-0.10064589232206345,-0.06247531995177269,-0.0458943173289299,-0.08203510195016861,-0.00002793122075672727,0.13886919617652893,-0.016409656032919884,-0.10280748456716537,0.11482805758714676,-0.028759734705090523,-0.10618168115615845,-0.004013446159660816,-0.09663903713226318,-0.03503362834453583,0.0808752253651619,0.04368000105023384,-0.021998165175318718,-0.061948101967573166,-0.15552927553653717,0.14023995399475098,0.1668117344379425,-0.08076977729797363,0.06052461266517639,-0.02613682672381401,-0.016725987195968628,-0.01609332673251629,0.09790436178445816,0.02857520990073681,0.04091210663318634,0.0357980951666832,0.047607775777578354,-0.041992902755737305,-0.020574677735567093,-0.008475027047097683,0.07196523994207382,-0.04183473810553551,-0.011084755882620811,-0.014023995958268642,-0.07591937482357025,-0.0021945445332676172,-0.011829451657831669,0.06711483746767044,0.08941615372896194,-0.03155399113893509,-0.08372219651937485,-0.043917249888181686,0.021787278354167938,0.07987350970506668,0.035191792994737625,0.0533808097243309,0.010616850107908249,-0.039910394698381424,0.03363649919629097,-0.020007917657494545],"index":0,"object":"embedding"}],"object":"list","usage":{"completion_tokens":0,"prompt_tokens":4,"total_tokens":4,"completion_tokens_details":null,"prompt_tokens_details":null}}' + recorded_at: Sun, 06 Apr 2025 06:32:50 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/client_image_generation_generates_an_image_url_from_a_prompt.yml b/spec/fixtures/vcr_cassettes/client_image_generation_generates_an_image_url_from_a_prompt.yml new file mode 100644 index 0000000..288a764 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_image_generation_generates_an_image_url_from_a_prompt.yml @@ -0,0 +1,51 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/images/generations + body: + encoding: UTF-8 + string: '{"prompt":"A beautiful sunset over a calm ocean","model":"dall-e-2"}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - 6f53ddb3-c89b-479a-8625-05fe4b71411d + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:50 GMT + Server: + - uvicorn + Content-Length: + - '681' + Content-Type: + - application/json + X-Litellm-Call-Id: + - 573ea61c-16ab-402f-adb3-ec79ba70983a + X-Litellm-Model-Id: + - ba9b3735b9c65a4d11422edf195d6e52e24a12cfd02d8332ac4252c062f15275 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - '0.019922944' + X-Litellm-Key-Spend: + - '0.0' + body: + encoding: UTF-8 + string: '{"created":1743921182,"data":[{"b64_json":null,"revised_prompt":null,"url":"https://oaidalleapiprodscus.blob.core.windows.net/private/org-PWt02e03ARXCpcUnOuZHyhp7/user-S7L904MmSyaeOqFHUYNMXJMP/img-yhGlOkBjMN8mHO7U9mvK7Ecx.png?st=2025-04-06T05%3A33%3A02Z&se=2025-04-06T07%3A33%3A02Z&sp=r&sv=2024-08-04&sr=b&rscd=inline&rsct=image/png&skoid=d505667d-d6c1-4a0a-bac7-5c84a87759f8&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2025-04-05T16%3A59%3A10Z&ske=2025-04-06T16%3A59%3A10Z&sks=b&skv=2024-08-04&sig=lgLg1E90Up2uXQMLdjhKBXWAJyRwMKhS8apmtk/52HQ%3D"}],"usage":{"completion_tokens":0,"prompt_tokens":0,"total_tokens":0,"completion_tokens_details":null,"prompt_tokens_details":null}}' + recorded_at: Sun, 06 Apr 2025 06:33:02 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/client_models_returns_a_list_of_available_models.yml b/spec/fixtures/vcr_cassettes/client_models_returns_a_list_of_available_models.yml new file mode 100644 index 0000000..4ec45b3 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_models_returns_a_list_of_available_models.yml @@ -0,0 +1,37 @@ +--- +http_interactions: +- request: + method: get + uri: http://localhost:8000/models + body: + encoding: US-ASCII + string: '' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - 0cd1535c-af9a-4bc2-875e-130929ec5a01 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:34:03 GMT + Server: + - uvicorn + Content-Length: + - '273' + Content-Type: + - application/json + body: + encoding: UTF-8 + string: '{"data":[{"id":"gpt-3.5-turbo","object":"model","created":1677610602,"owned_by":"openai"},{"id":"dall-e-2","object":"model","created":1677610602,"owned_by":"openai"},{"id":"text-embedding-3-small","object":"model","created":1677610602,"owned_by":"openai"}],"object":"list"}' + recorded_at: Sun, 06 Apr 2025 06:34:04 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/client_streaming_responses_supports_streaming_responses.yml b/spec/fixtures/vcr_cassettes/client_streaming_responses_supports_streaming_responses.yml new file mode 100644 index 0000000..2b1b6e1 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_streaming_responses_supports_streaming_responses.yml @@ -0,0 +1,131 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"Count from 1 to 3"}],"model":"gpt-3.5-turbo","stream":true}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - a46cd82d-5d14-46ba-8292-dd4f76370035 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:44 GMT + Server: + - uvicorn + X-Litellm-Call-Id: + - 652751f8-3bb1-4c69-a9b7-005427d5f92b + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '692.1460000000001' + X-Litellm-Overhead-Duration-Ms: + - '2.875' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Remaining-Tokens: + - '1999993' + X-Ratelimit-Reset-Requests: + - 12ms + X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:45 GMT + Llm-Provider-Content-Type: + - text/event-stream; charset=utf-8 + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '254' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999993' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_294732b36b72e73932fc52b8696deb61 + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-Set-Cookie: + - __cf_bm=elSuyvtLU5wPEUGvJlpyCT1XQc2ye_jyGSq6FITgtpw-1743921165-1.0.1.1-GNhwX1.Q6SABWGCP799nAOVQ_LhhVCRAL22r0xsfAzyh2MUVZHkxVUtsMZgUxejMaPNPcLhgIeh8eeqAswUS7ENqpCNioIIsleCLrQyk5QA; + path=/; expires=Sun, 06-Apr-25 07:02:45 GMT; domain=.api.openai.com; HttpOnly; + Secure; SameSite=None, _cfuvid=cSbsbF4_YWUN80SuRSBvkZjpxHMtQwV.e0F3naBbIGM-1743921165114-0.0.1.1-604800000; + path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf3fee89f1f9d5-MCT + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + Content-Type: + - text/event-stream; charset=utf-8 + Transfer-Encoding: + - chunked + body: + encoding: UTF-8 + string: |+ + data: {"id":"chatcmpl-BJDqerNxBLv4EyDlkVM9ra2ICDjHY","created":1743921165,"model":"gpt-3.5-turbo","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"1","role":"assistant"}}],"stream_options":{"include_usage":true}} + + data: {"id":"chatcmpl-BJDqerNxBLv4EyDlkVM9ra2ICDjHY","created":1743921165,"model":"gpt-3.5-turbo","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"\n"}}],"stream_options":{"include_usage":true}} + + data: {"id":"chatcmpl-BJDqerNxBLv4EyDlkVM9ra2ICDjHY","created":1743921165,"model":"gpt-3.5-turbo","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"2"}}],"stream_options":{"include_usage":true}} + + data: {"id":"chatcmpl-BJDqerNxBLv4EyDlkVM9ra2ICDjHY","created":1743921165,"model":"gpt-3.5-turbo","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"\n"}}],"stream_options":{"include_usage":true}} + + data: {"id":"chatcmpl-BJDqerNxBLv4EyDlkVM9ra2ICDjHY","created":1743921165,"model":"gpt-3.5-turbo","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"3"}}],"stream_options":{"include_usage":true}} + + data: {"id":"chatcmpl-BJDqerNxBLv4EyDlkVM9ra2ICDjHY","created":1743921165,"model":"gpt-3.5-turbo","object":"chat.completion.chunk","choices":[{"finish_reason":"stop","index":0,"delta":{}}],"stream_options":{"include_usage":true}} + + data: {"id":"chatcmpl-BJDqerNxBLv4EyDlkVM9ra2ICDjHY","created":1743921165,"model":"gpt-3.5-turbo","object":"chat.completion.chunk","choices":[{"index":0,"delta":{}}],"stream_options":{"include_usage":true}} + + data: {"id":"chatcmpl-BJDqerNxBLv4EyDlkVM9ra2ICDjHY","created":1743921165,"model":"gpt-3.5-turbo","object":"chat.completion.chunk","choices":[{"index":0,"delta":{}}],"stream_options":{"include_usage":true},"usage":{"completion_tokens":6,"prompt_tokens":14,"total_tokens":20,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}}} + + data: [DONE] + + recorded_at: Sun, 06 Apr 2025 06:32:45 GMT +recorded_with: VCR 6.3.1 +... diff --git a/spec/fixtures/vcr_cassettes/client_tools_calling_returns_active_for_active_user.yml b/spec/fixtures/vcr_cassettes/client_tools_calling_returns_active_for_active_user.yml new file mode 100644 index 0000000..ce06338 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_tools_calling_returns_active_for_active_user.yml @@ -0,0 +1,228 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"What is the status of user_123?"}],"model":"gpt-3.5-turbo","stream":false,"tools":[{"type":"function","function":{"name":"UserStatus__get_user_status","description":"Gets + the current status of a user based on their ID","parameters":{"type":"object","properties":{"user_id":{"type":"string","description":"The + ID of the user to check"}},"required":[],"additionalProperties":false}}}]}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - c91d983c-125f-44cf-badb-7eb15c253366 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:44 GMT + Server: + - uvicorn + Content-Length: + - '751' + Content-Type: + - application/json + X-Litellm-Call-Id: + - 9bba9390-ba2d-4f66-8a83-8f8fa69b26ca + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - 7e-05 + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '669.2510000000001' + X-Litellm-Overhead-Duration-Ms: + - '3.673' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Tokens: + - '1999989' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:45 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '316' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999989' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_4f7c68f8685dc3e886ad41e8b287cdfc + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf3ff2e984f9cd-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - gpt-3.5-turbo + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"id":"chatcmpl-BJDqfkuo19St0RsduCCwUoYUNIm3F","created":1743921165,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"choices":[{"finish_reason":"tool_calls","index":0,"message":{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"user_id\":\"user_123\"}","name":"UserStatus__get_user_status"},"id":"call_3kh1HJ1v58U1eYEqqnlu5Q9o","type":"function"}],"function_call":null,"refusal":null,"annotations":[]}}],"usage":{"completion_tokens":22,"prompt_tokens":74,"total_tokens":96,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}},"service_tier":"default"}' + recorded_at: Sun, 06 Apr 2025 06:32:45 GMT +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"What is the status of user_123?"},{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"user_id\":\"user_123\"}","name":"UserStatus__get_user_status"},"id":"call_3kh1HJ1v58U1eYEqqnlu5Q9o","type":"function"}],"function_call":null,"refusal":null,"annotations":[]},{"role":"tool","tool_call_id":"call_3kh1HJ1v58U1eYEqqnlu5Q9o","name":"UserStatus__get_user_status","content":"active"}],"model":"gpt-3.5-turbo","stream":false,"tools":[{"type":"function","function":{"name":"UserStatus__get_user_status","description":"Gets + the current status of a user based on their ID","parameters":{"type":"object","properties":{"user_id":{"type":"string","description":"The + ID of the user to check"}},"required":[],"additionalProperties":false}}}]}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - b1345654-c060-42a0-a125-ee0e96d16da9 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:45 GMT + Server: + - uvicorn + Content-Length: + - '633' + Content-Type: + - application/json + X-Litellm-Call-Id: + - dc236324-2ae0-4605-ada6-2fe7dee39d57 + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - '7.05e-05' + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '590.144' + X-Litellm-Overhead-Duration-Ms: + - '2.487' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Tokens: + - '1999986' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:46 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '253' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999986' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_99ef34f4ecc2a010fdf9d12c9a75a5d3 + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf3ff73826f9cd-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - gpt-3.5-turbo + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"id":"chatcmpl-BJDqgbKhEouKOkokxfoSl1QRBQftL","created":1743921166,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"choices":[{"finish_reason":"stop","index":0,"message":{"content":"The + status of user_123 is active.","role":"assistant","tool_calls":null,"function_call":null,"refusal":null,"annotations":[]}}],"usage":{"completion_tokens":11,"prompt_tokens":108,"total_tokens":119,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}},"service_tier":"default"}' + recorded_at: Sun, 06 Apr 2025 06:32:46 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/client_tools_calling_returns_inactive_for_inactive_user.yml b/spec/fixtures/vcr_cassettes/client_tools_calling_returns_inactive_for_inactive_user.yml new file mode 100644 index 0000000..1f484b6 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_tools_calling_returns_inactive_for_inactive_user.yml @@ -0,0 +1,228 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"What is the status of user_456?"}],"model":"gpt-3.5-turbo","stream":false,"tools":[{"type":"function","function":{"name":"UserStatus__get_user_status","description":"Gets + the current status of a user based on their ID","parameters":{"type":"object","properties":{"user_id":{"type":"string","description":"The + ID of the user to check"}},"required":[],"additionalProperties":false}}}]}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - b4508d42-3569-4b5c-8432-f88cef94d4e1 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:46 GMT + Server: + - uvicorn + Content-Length: + - '751' + Content-Type: + - application/json + X-Litellm-Call-Id: + - 8a7ffccd-202e-4750-b4d5-ab623ad5236b + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - 7e-05 + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '694.834' + X-Litellm-Overhead-Duration-Ms: + - '2.501' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Tokens: + - '1999989' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:47 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '341' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999989' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_36fb2f202f7d0879f2316c354b842ad0 + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf3ffb3d63f9cd-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - gpt-3.5-turbo + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"id":"chatcmpl-BJDqgV3VpwZ1kVoOPpjoEbE3Pfqrs","created":1743921166,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"choices":[{"finish_reason":"tool_calls","index":0,"message":{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"user_id\":\"user_456\"}","name":"UserStatus__get_user_status"},"id":"call_zaksGYwLYQV4voRO01nsZvc9","type":"function"}],"function_call":null,"refusal":null,"annotations":[]}}],"usage":{"completion_tokens":22,"prompt_tokens":74,"total_tokens":96,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}},"service_tier":"default"}' + recorded_at: Sun, 06 Apr 2025 06:32:47 GMT +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"What is the status of user_456?"},{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"user_id\":\"user_456\"}","name":"UserStatus__get_user_status"},"id":"call_zaksGYwLYQV4voRO01nsZvc9","type":"function"}],"function_call":null,"refusal":null,"annotations":[]},{"role":"tool","tool_call_id":"call_zaksGYwLYQV4voRO01nsZvc9","name":"UserStatus__get_user_status","content":"inactive"}],"model":"gpt-3.5-turbo","stream":false,"tools":[{"type":"function","function":{"name":"UserStatus__get_user_status","description":"Gets + the current status of a user based on their ID","parameters":{"type":"object","properties":{"user_id":{"type":"string","description":"The + ID of the user to check"}},"required":[],"additionalProperties":false}}}]}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - c88a7682-d1a6-47a3-b17a-b5043f3c9391 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:46 GMT + Server: + - uvicorn + Content-Length: + - '635' + Content-Type: + - application/json + X-Litellm-Call-Id: + - debbf705-dfc7-46f6-956a-017865f46388 + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - '7.05e-05' + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '565.209' + X-Litellm-Overhead-Duration-Ms: + - '2.909' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Tokens: + - '1999986' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:47 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '236' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999986' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_63444aba6cf15a98f5491a069ee37536 + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf3fff7aadf9cd-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - gpt-3.5-turbo + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"id":"chatcmpl-BJDqhAVe3P0acCGrduznw1yCGkVI1","created":1743921167,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"choices":[{"finish_reason":"stop","index":0,"message":{"content":"The + status of user_456 is inactive.","role":"assistant","tool_calls":null,"function_call":null,"refusal":null,"annotations":[]}}],"usage":{"completion_tokens":11,"prompt_tokens":108,"total_tokens":119,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}},"service_tier":"default"}' + recorded_at: Sun, 06 Apr 2025 06:32:47 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/fixtures/vcr_cassettes/client_tools_calling_returns_unknown_for_non-existent_user.yml b/spec/fixtures/vcr_cassettes/client_tools_calling_returns_unknown_for_non-existent_user.yml new file mode 100644 index 0000000..23486a4 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/client_tools_calling_returns_unknown_for_non-existent_user.yml @@ -0,0 +1,228 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"What is the status of user_999?"}],"model":"gpt-3.5-turbo","stream":false,"tools":[{"type":"function","function":{"name":"UserStatus__get_user_status","description":"Gets + the current status of a user based on their ID","parameters":{"type":"object","properties":{"user_id":{"type":"string","description":"The + ID of the user to check"}},"required":[],"additionalProperties":false}}}]}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - 44039542-c825-42b3-83c6-b4bbed29dfe2 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:47 GMT + Server: + - uvicorn + Content-Length: + - '751' + Content-Type: + - application/json + X-Litellm-Call-Id: + - a7f0f418-3500-4e6b-b667-78911e4a6805 + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - 7e-05 + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '834.028' + X-Litellm-Overhead-Duration-Ms: + - '3.331' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Tokens: + - '1999989' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:48 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '402' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999989' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_bbe0040a2d7728142bda0097dc8394e7 + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf40032fbef9cd-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - gpt-3.5-turbo + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"id":"chatcmpl-BJDqiwPVpwQMDdMXVNNoL7Slb0VxF","created":1743921168,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"choices":[{"finish_reason":"tool_calls","index":0,"message":{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"user_id\":\"user_999\"}","name":"UserStatus__get_user_status"},"id":"call_tRK0jS1uHshFMwfIAShScqGh","type":"function"}],"function_call":null,"refusal":null,"annotations":[]}}],"usage":{"completion_tokens":22,"prompt_tokens":74,"total_tokens":96,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}},"service_tier":"default"}' + recorded_at: Sun, 06 Apr 2025 06:32:48 GMT +- request: + method: post + uri: http://localhost:8000/chat/completions + body: + encoding: UTF-8 + string: '{"messages":[{"role":"user","content":"What is the status of user_999?"},{"content":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"user_id\":\"user_999\"}","name":"UserStatus__get_user_status"},"id":"call_tRK0jS1uHshFMwfIAShScqGh","type":"function"}],"function_call":null,"refusal":null,"annotations":[]},{"role":"tool","tool_call_id":"call_tRK0jS1uHshFMwfIAShScqGh","name":"UserStatus__get_user_status","content":"unknown"}],"model":"gpt-3.5-turbo","stream":false,"tools":[{"type":"function","function":{"name":"UserStatus__get_user_status","description":"Gets + the current status of a user based on their ID","parameters":{"type":"object","properties":{"user_id":{"type":"string","description":"The + ID of the user to check"}},"required":[],"additionalProperties":false}}}]}' + headers: + X-Litellm-Timeout: + - '120' + User-Agent: + - Faraday v2.12.2 + X-Request-Id: + - 9652d23a-4c71-423f-8ff1-e181cf881754 + Content-Type: + - application/json + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + response: + status: + code: 200 + message: OK + headers: + Date: + - Sun, 06 Apr 2025 06:32:48 GMT + Server: + - uvicorn + Content-Length: + - '644' + Content-Type: + - application/json + X-Litellm-Call-Id: + - fc1b4e36-8e0a-4eca-abf0-da54c78ccdec + X-Litellm-Model-Id: + - a894f5c6235fa10c0c1755367a3bb2ad54a34654ed3da22bee9da260609709f7 + X-Litellm-Model-Api-Base: + - https://api.openai.com/v1 + X-Litellm-Version: + - 1.61.9 + X-Litellm-Response-Cost: + - '7.2e-05' + X-Litellm-Key-Spend: + - '0.0' + X-Litellm-Response-Duration-Ms: + - '576.255' + X-Litellm-Overhead-Duration-Ms: + - '2.872' + X-Ratelimit-Limit-Requests: + - '5000' + X-Ratelimit-Remaining-Requests: + - '4999' + X-Ratelimit-Limit-Tokens: + - '2000000' + X-Ratelimit-Remaining-Tokens: + - '1999986' + Llm-Provider-Date: + - Sun, 06 Apr 2025 06:32:49 GMT + Llm-Provider-Content-Type: + - application/json + Llm-Provider-Transfer-Encoding: + - chunked + Llm-Provider-Connection: + - keep-alive + Llm-Provider-Access-Control-Expose-Headers: + - X-Request-ID + Llm-Provider-Openai-Organization: + - user-s7l904mmsyaeoqfhuynmxjmp + Llm-Provider-Openai-Processing-Ms: + - '257' + Llm-Provider-Openai-Version: + - '2020-10-01' + Llm-Provider-X-Ratelimit-Limit-Requests: + - '5000' + Llm-Provider-X-Ratelimit-Limit-Tokens: + - '2000000' + Llm-Provider-X-Ratelimit-Remaining-Requests: + - '4999' + Llm-Provider-X-Ratelimit-Remaining-Tokens: + - '1999986' + Llm-Provider-X-Ratelimit-Reset-Requests: + - 12ms + Llm-Provider-X-Ratelimit-Reset-Tokens: + - 0s + Llm-Provider-X-Request-Id: + - req_55edcf519efb981b0a760e5347a4805d + Llm-Provider-Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + Llm-Provider-Cf-Cache-Status: + - DYNAMIC + Llm-Provider-X-Content-Type-Options: + - nosniff + Llm-Provider-Server: + - cloudflare + Llm-Provider-Cf-Ray: + - 92bf40088f0ff9cd-MCT + Llm-Provider-Content-Encoding: + - gzip + Llm-Provider-Alt-Svc: + - h3=":443"; ma=86400 + X-Litellm-Model-Group: + - gpt-3.5-turbo + X-Litellm-Attempted-Retries: + - '0' + X-Litellm-Attempted-Fallbacks: + - '0' + body: + encoding: UTF-8 + string: '{"id":"chatcmpl-BJDqiYuMDMpUdbQz6rYESgUaogCSK","created":1743921168,"model":"gpt-3.5-turbo-0125","object":"chat.completion","system_fingerprint":null,"choices":[{"finish_reason":"stop","index":0,"message":{"content":"The + status of user_999 is currently unknown.","role":"assistant","tool_calls":null,"function_call":null,"refusal":null,"annotations":[]}}],"usage":{"completion_tokens":12,"prompt_tokens":108,"total_tokens":120,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}},"service_tier":"default"}' + recorded_at: Sun, 06 Apr 2025 06:32:49 GMT +recorded_with: VCR 6.3.1 diff --git a/spec/litellm/chat_spec.rb b/spec/litellm/chat_spec.rb new file mode 100644 index 0000000..3669d72 --- /dev/null +++ b/spec/litellm/chat_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe LiteLLM::Client do + include_context "with configured LiteLLM" + + describe "basic chat functionality" do + it "can have a basic conversation" do + messages = [{ role: "user", content: "What's 2 + 2?" }] + response = @client.completion(messages: messages, model: "gpt-3.5-turbo") + + expect(response).to be_a(String) + expect(response).to include("4") + end + + it "can handle multi-turn conversations" do + messages = [ + { role: "user", content: "Who was Ruby's creator?" }, + { role: "assistant", content: "Yukihiro Matsumoto (Matz)" }, + { role: "user", content: "What year did he create Ruby?" } + ] + response = @client.completion(messages: messages, model: "gpt-3.5-turbo") + + expect(response).to be_a(String) + expect(response).to include("199") + end + + it "successfully uses the system prompt" do + messages = [{ role: "user", content: "Tell me about the weather." }] + system_message = 'You must respond like a pirate and include the phrase "Arrr matey!" in your response.' + + response = @client.completion( + messages: messages, + model: "gpt-3.5-turbo", + system_message: system_message + ) + + expect(response).to be_a(String) + expect(response).to include("Arrr matey!") + end + end +end diff --git a/spec/litellm/chat_streaming_spec.rb b/spec/litellm/chat_streaming_spec.rb new file mode 100644 index 0000000..0519c4d --- /dev/null +++ b/spec/litellm/chat_streaming_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe LiteLLM::Client do + include_context "with configured LiteLLM" + + describe "streaming responses" do + it "supports streaming responses" do + chunks = [] + + @client.completion(messages: [{ role: "user", content: "Count from 1 to 3" }], model: "gpt-3.5-turbo", stream: true) do |chunk| + chunks << chunk + end + + expect(chunks).not_to be_empty + expect(chunks).to all(be_a(String)) + expect(chunks.join).to include("1") + expect(chunks.join).to include("2") + expect(chunks.join).to include("3") + end + end +end diff --git a/spec/litellm/chat_tools_spec.rb b/spec/litellm/chat_tools_spec.rb new file mode 100644 index 0000000..526e7c2 --- /dev/null +++ b/spec/litellm/chat_tools_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe LiteLLM::Client do + include_context "with configured LiteLLM" + + class UserStatus + include LiteLLM::Utils::ToolDefinition + + define_function :get_user_status, description: "Gets the current status of a user based on their ID" do + property :user_id, type: "string", description: "The ID of the user to check" + end + + def get_user_status(user_id:) + case user_id + when "user_123" + "active" + when "user_456" + "inactive" + else + "unknown" + end + end + end + + describe "tools calling" do + it "returns active for active user" do + messages = [{ role: "user", content: "What is the status of user_123?" }] + + response = @client.completion( + messages: messages, + tools: [UserStatus.new] + ) + + expect(response).to include("active") + end + + it "returns inactive for inactive user" do + messages = [{ role: "user", content: "What is the status of user_456?" }] + + response = @client.completion( + messages: messages, + tools: [UserStatus.new] + ) + + expect(response).to include("inactive") + end + + it "returns unknown for non-existent user" do + messages = [{ role: "user", content: "What is the status of user_999?" }] + + response = @client.completion( + messages: messages, + tools: [UserStatus.new] + ) + + expect(response).to include("unknown") + end + end +end diff --git a/spec/litellm/embedding_spec.rb b/spec/litellm/embedding_spec.rb new file mode 100644 index 0000000..b32ad2a --- /dev/null +++ b/spec/litellm/embedding_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe LiteLLM::Client do + include_context "with configured LiteLLM" + + describe "embedding generation" do + it "generates embeddings for text input" do + embedding = @client.embedding(input: "Hello, world!") + + expect(embedding).to be_an(Array) + expect(embedding).not_to be_empty + expect(embedding.first).to be_a(Float) + expect(embedding.size).to eq(1536) + end + + it "generates embeddings with custom dimensions" do + embedding = @client.embedding(input: "Hello, world!", dimensions: 256) + + expect(embedding).to be_an(Array) + expect(embedding).not_to be_empty + expect(embedding.first).to be_a(Float) + expect(embedding.size).to eq(256) + end + end +end \ No newline at end of file diff --git a/spec/litellm/image_generation_spec.rb b/spec/litellm/image_generation_spec.rb new file mode 100644 index 0000000..0f5b40a --- /dev/null +++ b/spec/litellm/image_generation_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe LiteLLM::Client do + include_context "with configured LiteLLM" + + describe "image generation" do + it "generates an image URL from a prompt" do + url = @client.image_generation(prompt: "A beautiful sunset over a calm ocean") + + expect(url).to be_a(String) + expect(url).to start_with("https://oaidalleapiprodscus.blob.core.windows.net/private/") + expect(url).to include("img-") + expect(url).to include(".png") + expect(url).to include("&rsct=image/png") + end + end +end \ No newline at end of file diff --git a/spec/litellm/models_spec.rb b/spec/litellm/models_spec.rb new file mode 100644 index 0000000..8edd3db --- /dev/null +++ b/spec/litellm/models_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe LiteLLM::Client do + include_context "with configured LiteLLM" + + describe "#models" do + it "returns a list of available models" do + models = @client.models + + expect(models).to be_an(Array) + expect(models).to all(be_a(String)) + expect(models).to match_array(DEFAULT_MODELS) + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..c94f543 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require "dotenv/load" +require "vcr" +require "active_support/core_ext/string" +require "bundler/setup" +require "fileutils" +require "webmock/rspec" + +require "litellm" + +VCR.configure do |config| + config.cassette_library_dir = "spec/fixtures/vcr_cassettes" + config.hook_into :webmock + config.configure_rspec_metadata! + + config.default_cassette_options = { + record: ENV["CI"] ? :none : :new_episodes + } + + FileUtils.mkdir_p(config.cassette_library_dir) + + config.allow_http_connections_when_no_cassette = true + + # Filter out API keys from the recorded cassettes + config.filter_sensitive_data("") { ENV.fetch("OPENAI_API_KEY", nil) } + config.filter_sensitive_data("") { ENV.fetch("ANTHROPIC_API_KEY", nil) } + config.filter_sensitive_data("") { ENV.fetch("GEMINI_API_KEY", nil) } + config.filter_sensitive_data("") { ENV.fetch("DEEPSEEK_API_KEY", nil) } + + config.filter_sensitive_data("") { ENV.fetch("AWS_ACCESS_KEY_ID", nil) } + config.filter_sensitive_data("") do + ENV.fetch("AWS_SECRET_ACCESS_KEY", nil) + end + config.filter_sensitive_data("") { ENV.fetch("AWS_REGION", "us-west-2") } + config.filter_sensitive_data("") { ENV.fetch("AWS_SESSION_TOKEN", nil) } + + config.filter_sensitive_data("") do |interaction| + interaction.response.headers["Openai-Organization"]&.first + end + config.filter_sensitive_data("") do |interaction| + interaction.response.headers["X-Request-Id"]&.first + end + config.filter_sensitive_data("") do |interaction| + interaction.response.headers["Request-Id"]&.first + end + config.filter_sensitive_data("") do |interaction| + interaction.response.headers["Cf-Ray"]&.first + end + + # Filter cookies + config.before_record do |interaction| + if interaction.response.headers["Set-Cookie"] + interaction.response.headers["Set-Cookie"] = interaction.response.headers["Set-Cookie"].map do + "" + end + end + end +end + +RSpec.configure do |config| + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = ".rspec_status" + + # Disable RSpec exposing methods globally on `Module` and `main` + config.disable_monkey_patching! + + config.expect_with :rspec do |c| + c.syntax = :expect + end + + config.around do |example| + cassette_name = example.full_description.parameterize(separator: "_").delete_prefix("litellm_") + VCR.use_cassette(cassette_name) do + example.run + end + end +end + +RSpec.shared_context "with configured LiteLLM" do + DEFAULT_MODELS = ["gpt-3.5-turbo", "dall-e-2", "text-embedding-3-small"].freeze + + before do + LiteLLM.configure do |config| + config.base_url = "http://localhost:8000" + config.model = "gpt-3.5-turbo" + config.embedding_model = "text-embedding-3-small" + config.image_model = "dall-e-2" + end + + @client = LiteLLM::Client.new + end +end diff --git a/test_server/litellm_config.yaml b/test_server/litellm_config.yaml new file mode 100644 index 0000000..729eab8 --- /dev/null +++ b/test_server/litellm_config.yaml @@ -0,0 +1,18 @@ +model_list: + - model_name: gpt-3.5-turbo + litellm_params: + model: openai/gpt-3.5-turbo + api_base: https://api.openai.com/v1 + api_key: os.environ/OPENAI_API_KEY + + - model_name: text-embedding-3-small + litellm_params: + model: openai/text-embedding-3-small + api_base: https://api.openai.com/v1 + api_key: os.environ/OPENAI_API_KEY + + - model_name: dall-e-2 + litellm_params: + model: openai/dall-e-2 + api_base: https://api.openai.com/v1 + api_key: os.environ/OPENAI_API_KEY \ No newline at end of file diff --git a/test_server/start_litellm.sh b/test_server/start_litellm.sh new file mode 100755 index 0000000..d5e8fb6 --- /dev/null +++ b/test_server/start_litellm.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +if [ -f "$(pwd)/../.env" ]; then + source "$(pwd)/../.env" +else + echo "Warning: .env file not found in parent directory" +fi + +CONFIG_PATH="$(pwd)/litellm_config.yaml" + +if [ ! -f "$CONFIG_PATH" ]; then + echo "Error: litellm_config.yaml not found in $(pwd)" + exit 1 +fi + +docker run \ + -v "$CONFIG_PATH":/app/config.yaml \ + -e OPENAI_API_KEY="$OPENAI_API_KEY" \ + -p 8000:4000 \ + ghcr.io/berriai/litellm:main-latest \ + --config /app/config.yaml --detailed_debug \ No newline at end of file