BxBuilderChain

This gem / building block allows builder apps to use open ai. The following features are included:

  • OpenAi completion with GPT 3.5 and GPT 4
  • Q&A / additional prompt context with a users private documents
  • Documents can be stored on a global and user/group level

Installation

Install the gem and add to the application's Gemfile by executing:

$ bundle add bx_builder_chain

followed by

$ bundle install

If bundler is not being used to manage dependencies, install the gem by executing:

$ gem install bx_builder_chain

Setup

generate the endpoints & Active admin contollers for Builder Chain along with the DB migrations

$ rails generate builder_chain:install

this will add the following endpoint controllers

  • File upload
  • List files
  • Delete file
  • OpenAi ask / completion
  • ActiveAdmin documents controller

It will also add a test view / controller for testing the endpoints. ensure this is removed prior to production release

Usage

require "bx_builder_chain"

edit the initializer config 'bx_builder_chain.rb' setup the api keys and db credentials

BxBuilderChain.configure do |config|
  config.openai_api_key = ENV['OPENAI_API_KEY']

  # for db use this
  config.pg_url = ENV['DB_URL'] || nil # eg 'postgres://postgres:password@localhost:5432/my_db'

  # or this - pg_url with take preference
  config.database_host = ENV['DB_HOSTNAME'] || 'localhost'
  config.database_name = ENV['DB_NAME']
  config.database_user = ENV['DB_USER']
  config.database_password = ENV['DB_PASSWORD']
  config.database_port = ENV['DB_PORT'] || '5432' # Defaulting to 5432 if not set

  config.public_namespace = "public"
  config.threshold = 0.25
  config.default_prompt_template = "Context information is below
  --------------------
  %{context}
  --------------------
  Given the context information and not prior knowledge
  answer the question: %{question}"
end

create the llm and client

client = BxBuilderChain::Vectorsearch::Pgvector.new(
      llm: BxBuilderChain::Llm::OpenAi.new,
      namespace: user_id # default is nil, nil assumes global public documents
    )

Add documents to the Vector Store

# Store plain texts in your vector search database
client.add_texts(
    texts: [
        "Begin by preheating your oven to 375°F (190°C). Prepare four boneless, skinless chicken breasts by cutting a pocket into the side of each breast, being careful not to cut all the way through. Season the chicken with salt and pepper to taste. In a large skillet, melt 2 tablespoons of unsalted butter over medium heat. Add 1 small diced onion and 2 minced garlic cloves, and cook until softened, about 3-4 minutes. Add 8 ounces of fresh spinach and cook until wilted, about 3 minutes. Remove the skillet from heat and let the mixture cool slightly.",
        "In a bowl, combine the spinach mixture with 4 ounces of softened cream cheese, 1/4 cup of grated Parmesan cheese, 1/4 cup of shredded mozzarella cheese, and 1/4 teaspoon of red pepper flakes. Mix until well combined. Stuff each chicken breast pocket with an equal amount of the spinach mixture. Seal the pocket with a toothpick if necessary. In the same skillet, heat 1 tablespoon of olive oil over medium-high heat. Add the stuffed chicken breasts and sear on each side for 3-4 minutes, or until golden brown."
    ]
)
# Store the contents of your files in your vector search database
my_pdf = "path/to/my.pdf"
my_text = "path/to/my.txt"
my_docx = "path/to/my.docx"

client.add_data(paths: [my_pdf, my_text, my_docx])

Or via the service object

my_pdf = "path/to/my.pdf"
my_text = "path/to/my.txt"
my_docx = "path/to/my.docx"

service = DocumentUploadService.new(
    files: [my_pdf, my_text, my_docx],
    user_groups: current_user_document_groups, # optional defaults to ['public'] an uses the first value to store the docs
    client_class_name: CLIENT_CLASS_NAME, # optional defaults to 'BxBuilderChain::Vectorsearch::Pgvector'
    llm_class_name: LLM_CLASS_NAME # optional defaults to 'BxBuilderChain::Llm::OpenAi'
)

result = service.upload_and_process

Then ask the question

client.ask(question: "What is Frogger?")