Project

gigachat

0.0
The project is in a healthy, maintained state
GigaChat
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

Ruby GigaChat

Gem Version GitHub license

Installation

Bundler

Add this line to your application's Gemfile:

gem "gigachat"

And then execute:

$ bundle install

Gem install

Or install with:

$ gem install gigachat

and require with:

require "gigachat"

Usage

Get your API key from developers.sber.ru.

Quickstart

For a quick test you can pass your token directly to a new client:

client = GigaChat::Client.new(
  api_type: "GIGACHAT_API_CORP", # or GIGACHAT_API_PERS, GIGACHAT_API_B2B
  client_base64: "Yjgy...VhYw==" # your authorization data
)

With Config

For a more robust setup, you can configure the gem with your API keys, for example in an gigachat.rb initializer file. Never hardcode secrets into your codebase - instead use something like dotenv to pass the keys safely into your environments.

GigaChat.configure do |config|
  config.api_type = "GIGACHAT_API_CORP" # or GIGACHAT_API_PERS, GIGACHAT_API_B2B
  config.client_base64 = ENV.fetch("GIGACHAT_CLIENT_KEY")
end

Then you can create a client like this:

client = GigaChat::Client.new

You can still override the config defaults when making new clients; any options not included will fall back to any global config set with GigaChat.configure. e.g. in this example the api_type, etc. will fallback to any set globally using GigaChat.configure, with only the client_base64 overridden:

client = GigaChat::Client.new(client_base64: "secret_token_goes_here")

Custom timeout or base URI

The default timeout for any request using this library is 120 seconds. You can change that by passing a number of seconds to the request_timeout when initializing the client. You can also change the base URI used for all requests, eg. to use observability tools like Helicone, and add arbitrary other headers:

client = GigaChat::Client.new(
    client_base64: "secret_token_goes_here",
    uri_base: "https://oai.hconeai.com/",
    uri_auth: "https://localhost:5362/",
    request_timeout: 240,
    extra_headers: {
      "X-Proxy-TTL" => "43200",
      "X-Proxy-Refresh": "true",
    }
)

or when configuring the gem:

GigaChat.configure do |config|
    config.client_base64 = ENV.fetch("GIGACHAT_CLIENT_KEY")
    config.log_errors = true # Optional
    config.uri_base = "https://oai.hconeai.com/" # Optional
    config.request_timeout = 240 # Optional
    config.extra_headers = {
      "X-Proxy-TTL" => "43200",
      "X-Proxy-Refresh": "true"
    } # Optional
end

Extra Headers per Client

You can dynamically pass headers per client object, which will be merged with any headers set globally with GigaChat.configure:

client = GigaChat::Client.new(client_base64: "secret_token_goes_here")
client.add_headers("X-Proxy-TTL" => "43200")

Logging

Errors

By default, gigachat does not log any Faraday::Errors encountered while executing a network request to avoid leaking data (e.g. 400s, 500s, SSL errors and more - see here for a complete list of subclasses of Faraday::Error and what can cause them).

If you would like to enable this functionality, you can set log_errors to true when configuring the client:

  client = GigaChat::Client.new(log_errors: true)
Faraday middleware

You can pass Faraday middleware to the client in a block, eg. to enable verbose logging with Ruby's Logger:

  client = GigaChat::Client.new do |f|
    f.response :logger, Logger.new($stdout), bodies: true
  end

Counting Tokens

GigaChat parses prompt text into tokens, which are words or portions of words. Counting tokens can help you estimate your costs. It can also help you ensure your prompt text size is within the max-token limits of your model's context window, and choose an appropriate max_tokens completion parameter so your response will fit as well.

To estimate the token-count of your text:

GigaChat.rough_token_count("Your text")

If you need a more accurate count, try tiktoken_ruby.

Models

There are different models that can be used to generate text. For a full list and to retrieve information about a single model:

client.models.list
client.models.retrieve(id: "GigaChat-Pro")

Chat

GigaChat is a model that can be used to generate text in a conversational style. You can use it to generate a response to a sequence of messages:

response = client.chat(
    parameters: {
        model: "GigaChat-Pro", # Required.
        messages: [{ role: "user", content: "Hello!"}], # Required.
        temperature: 0.7,
    })
puts response.dig("choices", 0, "message", "content")
# => "Hello! How may I assist you today?"

Streaming Chat

You can stream from the API in realtime, which can be much faster and used to create a more engaging user experience. Pass a Proc (or any object with a #call method) to the stream parameter to receive the stream of completion chunks as they are generated. Each time one or more chunks is received, the proc will be called once with each chunk, parsed as a Hash. If GigaChat returns an error, gigachat will raise a Faraday error.

client.chat(
    parameters: {
        model: "GigaChat-Pro", # Required.
        messages: [{ role: "user", content: "Describe a character called Anna!"}], # Required.
        temperature: 0.7,
        update_interval: 1,
        stream: proc do |chunk, _bytesize|
            print chunk.dig("choices", 0, "delta", "content")
        end
    })
# => "Anna is a young woman in her mid-twenties, with wavy chestnut hair that falls to her shoulders..."

Functions

You can describe and pass in functions and the model will intelligently choose to output a JSON object containing arguments to call them - eg., to use your method get_current_weather to get the weather in a given location.

def get_current_weather(location:, unit: "fahrenheit")
  # Here you could use a weather api to fetch the weather.
  "The weather in #{location} is nice 🌞 #{unit}"
end

messages = [
  {
    "role": "user",
    "content": "What is the weather like in San Francisco?",
  },
]

response =
  client.chat(
    parameters: {
      model: "GigaChat-Pro",
      messages: messages,  # Defined above because we'll use it again
      tools: [
        {
          type: "function",
          function: {
            name: "get_current_weather",
            description: "Get the current weather in a given location",
            parameters: {  # Format: https://json-schema.org/understanding-json-schema
              type: :object,
              properties: {
                location: {
                  type: :string,
                  description: "The city and state, e.g. San Francisco, CA",
                },
                unit: {
                  type: "string",
                  enum: %w[celsius fahrenheit],
                },
              },
              required: ["location"],
            },
          },
        }
      ],
      function_call: "none"  # Optional, defaults to "auto"
                               # Can also put "none" or specific functions, see docs
    },
  )

You can learn more at this link.

Embeddings

You can use the embeddings endpoint to get a vector of numbers representing an input. You can then compare these vectors for different inputs to efficiently check how similar the inputs are.

response = client.embeddings(
    parameters: {
        model: "GigaChat",
        input: "The food was delicious and the waiter..."
    }
)

puts response.dig("data", 0, "embedding")
# => Vector representation of your embedding

Image Generation

GigaChat API will return an image if the #chat method receives an appropriate message, for example, "Draw a pink cat". Images are generated in binary form in JPG format using the built-in text2image function.

In response, GigaChat returns the identifier of the created image, which can be downloaded using the POST /files/:file_id/content request.

To create an image, the request must include the "function_call": "auto" parameter, which allows the model to determine the need to call the text2image function. When creating images using the built-in function, the model returns a response with the result "finish_reason": "stop".

You can learn more at this link.

Errors

HTTP errors can be caught like this:

  begin
    GigaChat::Client.new.models.retrieve(id: "GigaChat")
  rescue Faraday::Error => e
    raise "Got a Faraday error: #{e}"
  end

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/neonix20b/gigachat. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Ruby OpenAI project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.