Skip to content

Commit 4dd6e96

Browse files
Pinecone generator
1 parent daa3a9e commit 4dd6e96

File tree

8 files changed

+153
-8
lines changed

8 files changed

+153
-8
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,20 @@ If bundler is not being used to manage dependencies, install the gem by executin
3030
```ruby
3131
require "langchainrb_rails"
3232
```
33+
34+
## Generators
35+
36+
### Vectorsearch
37+
38+
#### Pinecone Generator
39+
40+
Command: `rails generate langchainrb_rails:pinecone --model=Product --llm=openai`
41+
42+
Available `--llm` options: `cohere`, `google_palm`, `hugging_face`, `llama_cpp`, `ollama`, `openai`, and `replicate`. The selected LLM will be used to generate embeddings and completions.
43+
44+
The `--model` option is used to specify which ActiveRecord model vectorsearch capabilities will be added to.
45+
46+
PineconeGenerator does the following:
47+
1. Creates the `langchainrb_rails.rb` initializer file
48+
2. Adds necessary code to the ActiveRecord model to enable vectorsearch
49+
3. Adds `pinecone` gem to the Gemfile

lib/langchainrb_rails.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,33 @@
33
require "langchain"
44
require_relative "langchainrb_rails/version"
55
require "langchainrb_rails/railtie"
6+
require "langchainrb_rails/config"
67

78
module LangchainrbRails
89
class Error < StandardError; end
910

1011
module ActiveRecord
1112
autoload :Hooks, "langchainrb_rails/active_record/hooks"
1213
end
14+
15+
module Generators
16+
autoload :PgvectorGenerator, "langchainrb_rails/generators/langchainrb_rails/pgvector_generator"
17+
end
18+
19+
class << self
20+
# Configures global settings for Langchain
21+
# LangchainrbRails.configure do |config|
22+
# config.vectorsearch = Langchain::Vectorsearch::Pgvector.new(
23+
# llm: Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
24+
# )
25+
# end
26+
def configure
27+
yield(config)
28+
end
29+
30+
# @return [Config] The global configuration object
31+
def config
32+
@_config ||= Config.new
33+
end
34+
end
1335
end

lib/langchainrb_rails/active_record/hooks.rb

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,7 @@ module ActiveRecord
99
#
1010
# Usage:
1111
# class Recipe < ActiveRecord::Base
12-
# vectorsearch provider: Langchain::Vectorsearch::Weaviate.new(
13-
# api_key: ENV["WEAVIATE_API_KEY"],
14-
# url: ENV["WEAVIATE_URL"],
15-
# index_name: "Recipes",
16-
# llm: Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
17-
# )
12+
# vectorsearch
1813
#
1914
# after_save :upsert_to_vectorsearch
2015
#
@@ -73,8 +68,8 @@ module ClassMethods
7368
# Set the vector search provider
7469
#
7570
# @param provider [Object] The `Langchain::Vectorsearch::*` instance
76-
def vectorsearch(provider:)
77-
class_variable_set(:@@provider, provider)
71+
def vectorsearch
72+
class_variable_set(:@@provider, LangchainrbRails.config.vectorsearch)
7873
end
7974

8075
# Search for similar texts

lib/langchainrb_rails/config.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
module LangchainrbRails
4+
class Config
5+
# This class is used to configure the Langchain.rb gem inside Rails apps, in the `config/initializers/langchain.rb` file.
6+
#
7+
# Langchain is configured in the following way:
8+
# Langchain.configure do |config|
9+
# config.vectorsearch = Langchain::Vectorsearch::Pgvector.new(
10+
# llm: Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
11+
# )
12+
# end
13+
attr_accessor :vectorsearch
14+
15+
def initialize
16+
# Define the defaults for future configuration here
17+
@vectorsearch = {}
18+
end
19+
end
20+
end
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
require "rails/generators/active_record"
2+
3+
module LangchainrbRails
4+
module Generators
5+
#
6+
# PineconeGenerator does the following:
7+
# 1. Creates the `langchainrb_rails.rb` initializer file
8+
# 2. Adds necessary code to the ActiveRecord model to enable vectorsearch
9+
# 3. Adds `pinecone` gem to the Gemfile
10+
#
11+
# Usage:
12+
# rails generate langchainrb_rails:pinecone --model=Product --llm=openai
13+
#
14+
class PineconeGenerator < Rails::Generators::Base
15+
desc "This generator adds Pinecone vectorsearch integration to your ActiveRecord model"
16+
17+
include ::ActiveRecord::Generators::Migration
18+
source_root File.join(__dir__, "templates")
19+
20+
class_option :model, type: :string, required: true, desc: "ActiveRecord Model to add vectorsearch to", aliases: "-m"
21+
class_option :llm, type: :string, required: true, desc: "LLM provider that will be used to generate embeddings and completions"
22+
23+
# Available LLM providers to be passed in as --llm option
24+
LLMS = {
25+
"cohere" => "Langchain::LLM::Cohere",
26+
"google_palm" => "Langchain::LLM::GooglePalm",
27+
"hugging_face" => "Langchain::LLM::HuggingFace",
28+
"llama_cpp" => "Langchain::LLM::LlamaCpp",
29+
"ollama" => "Langchain::LLM::Ollama",
30+
"openai" => "Langchain::LLM::OpenAI",
31+
"replicate" => "Langchain::LLM::Replicate"
32+
}
33+
34+
# Creates the `langchainrb_rails.rb` initializer file
35+
def create_initializer_file
36+
template "pinecone_initializer.rb", "config/initializers/langchainrb_rails.rb"
37+
end
38+
39+
# Adds `vectorsearch` class method to the model and `after_save` callback that calls `upsert_to_vectorsearch()`
40+
def add_to_model
41+
inject_into_class "app/models/#{model_name.downcase}.rb", model_name do
42+
" vectorsearch\n\n after_save :upsert_to_vectorsearch\n\n"
43+
end
44+
end
45+
46+
# Adds `pinecone` gem to the Gemfile
47+
# TODO: Can we automatically run `bundle install`?
48+
def add_to_gemfile
49+
gem "pinecone"
50+
end
51+
52+
private
53+
54+
# @return [String] Name of the model
55+
def model_name
56+
options["model"]
57+
end
58+
59+
# @return [String] LLM provider to use
60+
def llm
61+
options["llm"]
62+
end
63+
64+
# @return [Langchain::LLM::*] LLM class
65+
def llm_class
66+
Langchain::LLM.const_get(LLMS[llm])
67+
end
68+
end
69+
end
70+
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# frozen_string_literal: true
2+
3+
LangchainrbRails.configure do |config|
4+
config.vectorsearch = Langchain::Vectorsearch::Pinecone.new(
5+
llm: <%= llm_class %>.new(api_key: ENV["<%= llm.upcase %>_API_KEY"]),
6+
environment: "",
7+
api_key: ENV["PINECONE_API_KEY"],
8+
index_name: ""
9+
)
10+
end

lib/langchainrb_rails/railtie.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,9 @@ class Railtie < Rails::Railtie
77
::ActiveRecord::Base.include LangchainrbRails::ActiveRecord::Hooks
88
end
99
end
10+
11+
generators do
12+
require_relative "generators/langchainrb_rails/pinecone_generator"
13+
end
1014
end
1115
end

spec/config_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe LangchainrbRails::Config do
4+
it "has a vectorsearch property" do
5+
expect(subject).to respond_to(:vectorsearch)
6+
end
7+
end

0 commit comments

Comments
 (0)