roseflow 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.standard.yml +3 -1
- data/CHANGELOG.md +2 -2
- data/Gemfile +2 -0
- data/examples/github-repo-chat/lib/actions/clone_and_load_repository.rb +52 -0
- data/examples/github-repo-chat/lib/actions/create_prompt.rb +15 -0
- data/examples/github-repo-chat/lib/actions/embed_repository.rb +35 -0
- data/examples/github-repo-chat/lib/actions/initialize_vector_store.rb +40 -0
- data/examples/github-repo-chat/lib/actions/interact_with_model.rb +29 -0
- data/examples/github-repo-chat/lib/actions/load_documents_to_database.rb +0 -0
- data/examples/github-repo-chat/lib/actions/split_files_to_documents.rb +55 -0
- data/examples/github-repo-chat/lib/document_database.rb +0 -0
- data/examples/github-repo-chat/lib/github_chat_prompt.rb +24 -0
- data/examples/github-repo-chat/lib/github_repository_chat.rb +12 -0
- data/examples/github-repo-chat/lib/interactions/ask_llm.rb +31 -0
- data/examples/github-repo-chat/lib/interactions/github_repository_chat.rb +36 -0
- data/examples/github-repo-chat/lib/interactions/load_files_to_document_database.rb +18 -0
- data/examples/github-repo-chat/lib/interactions/load_repository.rb +20 -0
- data/examples/github-repo-chat/lib/interactions/prepare_vector_store.rb +21 -0
- data/examples/github-repo-chat/lib/repository.rb +9 -0
- data/examples/github-repo-chat/lib/repository_file.rb +31 -0
- data/examples/github-repo-chat/spec/actions/clone_and_load_repository_spec.rb +28 -0
- data/examples/github-repo-chat/spec/actions/embed_repository_spec.rb +24 -0
- data/examples/github-repo-chat/spec/actions/initialize_vector_store_spec.rb +20 -0
- data/examples/github-repo-chat/spec/actions/load_files_to_document_database_spec.rb +23 -0
- data/examples/github-repo-chat/spec/fixtures/ulid-ruby.zip +0 -0
- data/examples/github-repo-chat/spec/github_repository_chat_spec.rb +16 -0
- data/examples/github-repo-chat/spec/interactions/prepare_vector_store_spec.rb +4 -0
- data/examples/github-repo-chat/spec/spec_helper.rb +12 -0
- data/lib/roseflow/action.rb +13 -0
- data/lib/roseflow/actions/ai/resolve_model.rb +27 -0
- data/lib/roseflow/actions/ai/resolve_provider.rb +31 -0
- data/lib/roseflow/ai/model.rb +19 -0
- data/lib/roseflow/ai/provider.rb +30 -0
- data/lib/roseflow/chat/dialogue.rb +80 -0
- data/lib/roseflow/chat/exchange.rb +12 -0
- data/lib/roseflow/chat/message.rb +39 -0
- data/lib/roseflow/chat/personality.rb +10 -0
- data/lib/roseflow/embeddings/embedding.rb +26 -0
- data/lib/roseflow/finite_machine.rb +298 -0
- data/lib/roseflow/interaction/with_http_api.rb +10 -0
- data/lib/roseflow/interaction.rb +14 -0
- data/lib/roseflow/interaction_context.rb +10 -0
- data/lib/roseflow/interactions/ai/initialize_llm.rb +26 -0
- data/lib/roseflow/primitives/vector.rb +19 -0
- data/lib/roseflow/prompt.rb +17 -0
- data/lib/roseflow/text/completion.rb +16 -0
- data/lib/roseflow/text/recursive_character_splitter.rb +43 -0
- data/lib/roseflow/text/sentence_splitter.rb +42 -0
- data/lib/roseflow/text/splitter.rb +18 -0
- data/lib/roseflow/text/tokenized_text.rb +20 -0
- data/lib/roseflow/text/word_splitter.rb +14 -0
- data/lib/roseflow/tokenizer.rb +13 -0
- data/lib/roseflow/types.rb +9 -0
- data/lib/roseflow/vector_stores/base.rb +39 -0
- data/lib/roseflow/vector_stores/hnsw.proto +18 -0
- data/lib/roseflow/vector_stores/hnsw_memory_store.rb +442 -0
- data/lib/roseflow/vector_stores/hnsw_pb.rb +27 -0
- data/lib/roseflow/vector_stores/type/vector.rb +38 -0
- data/lib/roseflow/vector_stores/vector.rb +19 -0
- data/lib/roseflow/version.rb +12 -1
- data/lib/roseflow.rb +10 -1
- data/roseflow.gemspec +53 -0
- metadata +274 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8b7f5c7688debc9bb3b2e804dfcc45671ca670cc3114fabeb8ceff1169b5098
|
4
|
+
data.tar.gz: cb9d12161f611bf90738c2459e0700698e3443a8fe7b0d3f98c8d6268b315c0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcb00909e24bf283c2f901f680e86995bbe0fe5060eb9fb243e1e6435c1b1c39735ae918609eb89f81a40c48196861e4a2de8881f5c1c71b86e4fb996adff2af
|
7
|
+
data.tar.gz: 89415e4d06ef6b421da5be3a9a214752dfaa959258082ad09c9321d9f9d47703ea8d17ac7eaf26da9bb18ca4b291e1ca982c5f0a98b4c86b324f697b25446f20
|
data/.standard.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This class represents an action that clones and loads a repository from a
|
4
|
+
# given URL. The action expects a repository URL as input and returns a
|
5
|
+
# Repository object containing the repository's data.
|
6
|
+
#
|
7
|
+
# Example usage:
|
8
|
+
# repository = Actions::CloneAndLoadRepository.call(
|
9
|
+
# repository_url: "https://github.com/ljuti/roseflow.git"
|
10
|
+
# )
|
11
|
+
|
12
|
+
require "roseflow/action"
|
13
|
+
require "rugged"
|
14
|
+
require "tmpdir"
|
15
|
+
|
16
|
+
require_relative "../repository"
|
17
|
+
|
18
|
+
class Actions::CloneAndLoadRepository
|
19
|
+
extend Roseflow::Action
|
20
|
+
|
21
|
+
# Define the inputs and outputs of the action
|
22
|
+
expects :repository_url # Input: The URL of the repository to clone
|
23
|
+
promises :repository # Output: a Repository object
|
24
|
+
|
25
|
+
executed do |ctx|
|
26
|
+
ctx[:repository] = clone_repository(ctx.repository_url)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Clone a repository from a given URL, load its data, and create a Repository object.
|
30
|
+
#
|
31
|
+
# @param repository_url [String] The URL of the repository to clone
|
32
|
+
# @return [Repository] A Repository object containing the repository's data
|
33
|
+
def self.clone_repository(repository_url)
|
34
|
+
files = {}
|
35
|
+
Dir.mktmpdir do |dir|
|
36
|
+
# Clone the repository into a temporary directory
|
37
|
+
repository = Rugged::Repository.clone_at(repository_url, dir)
|
38
|
+
head_commit = repository.head.target
|
39
|
+
tree = repository.lookup(head_commit.tree.oid)
|
40
|
+
|
41
|
+
# Collect the content of each file in the repository
|
42
|
+
tree.walk_blobs(:preorder) do |root, entry|
|
43
|
+
file_path = "#{root}#{entry[:name]}"
|
44
|
+
files[file_path] = repository.lookup(entry[:oid]).content
|
45
|
+
end
|
46
|
+
|
47
|
+
# Extract the repository's name from the URL and create a Repository object
|
48
|
+
name = repository_url.split("/").last.gsub(".git", "")
|
49
|
+
return Repository.new(name, repository_url, files)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "roseflow/action"
|
4
|
+
require_relative "../github_chat_prompt"
|
5
|
+
|
6
|
+
class Actions::CreatePrompt
|
7
|
+
extend Roseflow::Action
|
8
|
+
|
9
|
+
expects :input
|
10
|
+
promises :prompt
|
11
|
+
|
12
|
+
executed do |ctx|
|
13
|
+
ctx[:prompt] = GithubChatPrompt.new(input)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "roseflow/action"
|
4
|
+
require "roseflow/vector_stores/base"
|
5
|
+
require_relative "../repository_file"
|
6
|
+
|
7
|
+
class Actions::EmbedRepository
|
8
|
+
extend Roseflow::Action
|
9
|
+
|
10
|
+
expects :repository
|
11
|
+
expects :vector_store
|
12
|
+
|
13
|
+
executed do |ctx|
|
14
|
+
# Check if the vector store already has embeddings for given repository
|
15
|
+
# If so, we can skip this action
|
16
|
+
next if ctx.vector_store.has_embeddings?(ctx.repository)
|
17
|
+
|
18
|
+
# Otherwise, we need to embed the repository
|
19
|
+
embed_repository(ctx.repository, ctx.vector_store)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.embed_repository(repository, vector_store)
|
23
|
+
repository.files.each do |file_path, content|
|
24
|
+
unless file_is_embedded?(vector_store, file_path, repository.name)
|
25
|
+
embedding = RepositoryFile.new(file_path, content)
|
26
|
+
vector = vector_store.build_vector(file_path.to_s, embedding.embedding.vector)
|
27
|
+
vector_store.create_vector("github", vector, namespace: repository.name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.file_is_embedded?(vector_store, file_path, repository_name)
|
33
|
+
vector_store.find("github", file_path.to_s, namespace: repository_name)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This class represents an action that initializes a vector store based on a
|
4
|
+
# given provider. The action expects a provider as input and returns a
|
5
|
+
# VectorStore object.
|
6
|
+
#
|
7
|
+
# Example usage:
|
8
|
+
# vector_store = Actions::InitializeVectorStore.execute(provider: :pinecone)
|
9
|
+
|
10
|
+
require "roseflow/action"
|
11
|
+
|
12
|
+
class Actions::InitializeVectorStore
|
13
|
+
# Make it a Roseflow action
|
14
|
+
extend Roseflow::Action
|
15
|
+
|
16
|
+
# Define the inputs and outputs of the action
|
17
|
+
expects :provider # Input: The vector store provider to use
|
18
|
+
promises :vector_store # Output: a VectorStore object
|
19
|
+
|
20
|
+
executed do |ctx|
|
21
|
+
ctx[:vector_store] = initialize_vector_store(ctx.provider)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Initialize a vector store based on the given provider.
|
25
|
+
#
|
26
|
+
# @param provider [Symbol] The symbol representing the vector store provider
|
27
|
+
# @return [Object] A VectorStore object corresponding to the given provider
|
28
|
+
# @raise [ArgumentError] If the provider is unknown
|
29
|
+
def self.initialize_vector_store(provider)
|
30
|
+
case provider
|
31
|
+
when :pinecone
|
32
|
+
# Initialize a Pinecone vector store
|
33
|
+
require "roseflow/pinecone/vector_store"
|
34
|
+
Roseflow::Pinecone::VectorStore.new
|
35
|
+
else
|
36
|
+
# Raise an error if the provider is unknown
|
37
|
+
raise ArgumentError, "Unknown provider: #{provider}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This class represents an action that interacts with a given model using a
|
4
|
+
# provided prompt. The action expects both a prompt and a model as input, and
|
5
|
+
# returns a response generated by the model.
|
6
|
+
#
|
7
|
+
# Example usage:
|
8
|
+
# response = Actions::InteractWithModel.execute(prompt: "What is the capital of France?", model: my_model)
|
9
|
+
|
10
|
+
require "roseflow/action"
|
11
|
+
|
12
|
+
class Actions::InteractWithModel
|
13
|
+
# Make it a Roseflow action
|
14
|
+
extend Roseflow::Action
|
15
|
+
|
16
|
+
# Define the inputs and outputs of the action
|
17
|
+
expects :prompt # Input: The prompt to use
|
18
|
+
expects :model # Input: The model to interact with
|
19
|
+
|
20
|
+
promises :response # Output: The response generated by the model
|
21
|
+
|
22
|
+
executed do |ctx|
|
23
|
+
# Interact with the model using the provided prompt
|
24
|
+
chat = ctx.model.chat(ctx.prompt)
|
25
|
+
|
26
|
+
# Store the response in the context
|
27
|
+
context[:response] = chat.response
|
28
|
+
end
|
29
|
+
end
|
File without changes
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This action splits the content of source code files into smaller chunks
|
4
|
+
# and tokenizing them into documents.
|
5
|
+
#
|
6
|
+
# It takes a repository as an input and returns an array of documents.
|
7
|
+
|
8
|
+
require "roseflow/action"
|
9
|
+
require "ulid"
|
10
|
+
|
11
|
+
class Actions::SplitFilesToDocuments
|
12
|
+
extend Roseflow::Action
|
13
|
+
|
14
|
+
# Define the inputs and outputs of the action
|
15
|
+
expects :repository # Input: a repository object containing file data
|
16
|
+
promises :documents # Output: Array of RepositoryFile objects representing documents
|
17
|
+
|
18
|
+
executed do |ctx|
|
19
|
+
# Initialize splitter and tokenizer instances
|
20
|
+
splitter = initialize_splitter
|
21
|
+
tokenizer = initialize_tokenizer(ctx)
|
22
|
+
|
23
|
+
# Iterate over each file in the repository, split and tokenize its content
|
24
|
+
ctx[:documents] = ctx.repository.files.each do |file_path, content|
|
25
|
+
chunks = splitter.split(content) # Split the content into chunks
|
26
|
+
tokenized = chunks.map { |chunk| tokenizer.encode(chunk) } # Tokenize each chunks
|
27
|
+
|
28
|
+
# Create a RepositoryFile object for each chunk-token pair
|
29
|
+
chunks.zip(tokenized).map do |chunk, tkn|
|
30
|
+
RepositoryFile.new(
|
31
|
+
name: file_path,
|
32
|
+
content: chunk,
|
33
|
+
tokens: tkn,
|
34
|
+
token_count: tkn.length
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Initialize a RecursiveCharacterSplitter instance with a chunk_size of 1000
|
41
|
+
# and no overlap between chunks.
|
42
|
+
#
|
43
|
+
# @return [Roseflow::Text::RecursiveCharacterSplitter]
|
44
|
+
def self.initialize_splitter
|
45
|
+
Roseflow::Text::RecursiveCharacterSplitter.new(chunk_size: 1000, chunk_overlap: 0)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Initialize a Tokenizer instance with the provided model from the context.
|
49
|
+
#
|
50
|
+
# @param ctx [Roseflow::Context] The context of the action execution
|
51
|
+
# @return [Roseflow::Tiktoken::Tokenizer]
|
52
|
+
def self.initialize_tokenizer(ctx)
|
53
|
+
Roseflow::Tiktoken::Tokenizer.new(model: ctx.model.name)
|
54
|
+
end
|
55
|
+
end
|
File without changes
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "roseflow/prompt"
|
4
|
+
|
5
|
+
class GithubChatPrompt < Roseflow::Prompt
|
6
|
+
def initialize(input)
|
7
|
+
@input = input
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :input
|
11
|
+
|
12
|
+
def template
|
13
|
+
plain_raw condensed(prompt_string)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def prompt_string
|
19
|
+
<<-PROMPT
|
20
|
+
|
21
|
+
Command: [#{input}]
|
22
|
+
PROMPT
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative "actions/clone_and_load_repository"
|
2
|
+
require_relative "actions/create_prompt"
|
3
|
+
require_relative "actions/embed_repository"
|
4
|
+
require_relative "actions/initialize_vector_store"
|
5
|
+
require_relative "actions/interact_with_model"
|
6
|
+
|
7
|
+
require_relative "interactions/ask_llm"
|
8
|
+
require_relative "interactions/github_repository_chat"
|
9
|
+
require_relative "interactions/load_repository"
|
10
|
+
require_relative "interactions/prepare_vector_store"
|
11
|
+
|
12
|
+
require_relative "github_chat_prompt"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This class represents an interaction that asks the LLM (Large Language Model)
|
4
|
+
# a question based on a given context. It orchestrates the required actions to
|
5
|
+
# initialize the LLM, create a prompt, and interact with the model.
|
6
|
+
#
|
7
|
+
# Example usage:
|
8
|
+
# result = Interactions::AskLLM.call(context)
|
9
|
+
|
10
|
+
require "roseflow"
|
11
|
+
require "roseflow/interactions/ai/initialize_llm"
|
12
|
+
|
13
|
+
require_relative "../actions/create_prompt"
|
14
|
+
|
15
|
+
class Interactions::AskLLM
|
16
|
+
extend Roseflow::Interaction
|
17
|
+
|
18
|
+
def self.call(context = {})
|
19
|
+
with(context).reduce(actions)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Define the sequence of actions (or interactions) to be performed
|
23
|
+
# by the interaction.
|
24
|
+
def self.actions
|
25
|
+
[
|
26
|
+
Roseflow::Interactions::AI::InitializeLlm, # Initialize the LLM
|
27
|
+
CreatePrompt, # Create a prompt for the LLM
|
28
|
+
InteractWithModel # Interact with the LLM
|
29
|
+
]
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This class represents an interaction that allows users to chat about
|
4
|
+
# a Github repository. It orchestrates the required actions to load
|
5
|
+
# the repository, prepare the vector store, and ask the LLM about the repository.
|
6
|
+
#
|
7
|
+
# Example usage:
|
8
|
+
# question = "What is the repository about?"
|
9
|
+
# response = Interactions::GithubRepositoryChat.call(
|
10
|
+
# question: question,
|
11
|
+
# repository_url: "https://github.com/ljuti/roseflow"
|
12
|
+
# )
|
13
|
+
|
14
|
+
require "roseflow/interaction"
|
15
|
+
|
16
|
+
require_relative "./ask_llm"
|
17
|
+
require_relative "./load_repository"
|
18
|
+
require_relative "./prepare_vector_store"
|
19
|
+
|
20
|
+
class Interactions::GithubRepositoryChat
|
21
|
+
extend Roseflow::Interaction
|
22
|
+
|
23
|
+
def self.call(context = {})
|
24
|
+
with(context).reduce(actions)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Define the sequence of actions (or interactions) to be performed
|
28
|
+
# by the interaction.
|
29
|
+
def self.actions
|
30
|
+
[
|
31
|
+
LoadRepository, # Load repository from Github and prepare it
|
32
|
+
PrepareVectorStore, # Prepare vector store for querying
|
33
|
+
AskLLM # Ask the LLM about the repository
|
34
|
+
]
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "roseflow/interaction"
|
4
|
+
|
5
|
+
class Interactions::LoadFilesToDocumentDatabase
|
6
|
+
extend Roseflow::Interaction
|
7
|
+
|
8
|
+
def self.call(ctx)
|
9
|
+
with(ctx).reduce(actions)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.actions
|
13
|
+
[
|
14
|
+
SplitFilesToDocuments,
|
15
|
+
LoadDocumentsToDatabase
|
16
|
+
]
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "roseflow/interaction"
|
4
|
+
|
5
|
+
require_relative "../actions/clone_and_load_repository"
|
6
|
+
|
7
|
+
class Interactions::LoadRepository
|
8
|
+
extend Roseflow::Interaction
|
9
|
+
|
10
|
+
def self.call(context = {})
|
11
|
+
with(context).reduce(actions)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.actions
|
15
|
+
[
|
16
|
+
CloneAndLoadRepository,
|
17
|
+
LoadFilesToDocumentDatabase
|
18
|
+
]
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "roseflow/interaction"
|
4
|
+
|
5
|
+
require_relative "../actions/initialize_vector_store"
|
6
|
+
require_relative "../actions/embed_repository"
|
7
|
+
|
8
|
+
class Interactions::PrepareVectorStore
|
9
|
+
extend Roseflow::Interaction
|
10
|
+
|
11
|
+
def self.call(context = {})
|
12
|
+
with(context).reduce(actions)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.actions
|
16
|
+
[
|
17
|
+
InitializeVectorStore,
|
18
|
+
reduce_if(->(ctx) { ctx.vector_store.has_embeddings? }, EmbedRepository)
|
19
|
+
]
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ulid"
|
4
|
+
|
5
|
+
class RepositoryFile < Roseflow::Embeddings::Base
|
6
|
+
def initialize(name:, content:, **kwargs)
|
7
|
+
@name = name
|
8
|
+
@content = content
|
9
|
+
@id = ULID.generate
|
10
|
+
@token_count = kwargs[:token_count]
|
11
|
+
@tokens = kwargs[:tokens]
|
12
|
+
end
|
13
|
+
|
14
|
+
def embedding
|
15
|
+
@embedding ||= create_embedding
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def create_embedding
|
21
|
+
provider.embedding(model: embedding_model, input: @content)
|
22
|
+
end
|
23
|
+
|
24
|
+
def provider
|
25
|
+
@provider ||= Roseflow::OpenAI::Provider.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def embedding_model
|
29
|
+
provider.models.embeddable.find { |model| model.name == "text-embedding-ada-002" } || openai.models.embeddable.first
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe Actions::CloneAndLoadRepository do
|
6
|
+
let(:repository_url) { "https://github.com/abachman/ulid-ruby.git" }
|
7
|
+
let(:ctx) do
|
8
|
+
Roseflow::InteractionContext.make(
|
9
|
+
repository_url: repository_url
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "cloning and loading the repository" do
|
14
|
+
let(:action) { described_class.execute(ctx) }
|
15
|
+
|
16
|
+
it "returns a repository" do
|
17
|
+
expect(action).to be_a_success
|
18
|
+
expect(action.repository).to be_a(Repository)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "sets repository attributes correctly" do
|
22
|
+
expect(action.repository).to be_a(Repository)
|
23
|
+
expect(action.repository.name).to eq "ulid-ruby"
|
24
|
+
expect(action.repository.url).to eq repository_url
|
25
|
+
expect(action.repository.files).not_to be_empty
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../spec_helper"
|
4
|
+
require "roseflow/pinecone"
|
5
|
+
require "roseflow/pinecone/vector_store"
|
6
|
+
|
7
|
+
RSpec.describe Actions::EmbedRepository do
|
8
|
+
let(:repository) { Repository.new("ulid-ruby", "https://github.com/abachman/ulid-ruby.git", {"ulid-ruby.gemspec": "This is a gemspec for the gem"}) }
|
9
|
+
let(:ctx) do
|
10
|
+
Roseflow::InteractionContext.make(
|
11
|
+
repository: repository,
|
12
|
+
vector_store: Roseflow::Pinecone::VectorStore.new
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "embedding a repository" do
|
17
|
+
let(:action) { described_class.execute(ctx) }
|
18
|
+
|
19
|
+
it "embeds the files of the repository to the vector store" do
|
20
|
+
expect(action).to be_a_success
|
21
|
+
expect(action.vector_store).to be_a(Roseflow::VectorStores::Base)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe Actions::InitializeVectorStore do
|
6
|
+
let(:ctx) do
|
7
|
+
Roseflow::InteractionContext.make(
|
8
|
+
provider: :pinecone
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "initializing the vector store" do
|
13
|
+
let(:action) { described_class.execute(ctx) }
|
14
|
+
|
15
|
+
it "returns a vector store" do
|
16
|
+
expect(action).to be_a_success
|
17
|
+
expect(action.vector_store).to be_a Roseflow::Pinecone::VectorStore
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe Actions::LoadFilesToDocumentDatabase do
|
6
|
+
let(:repository_url) { "https://github.com/abachman/ulid-ruby.git" }
|
7
|
+
let(:ctx) do
|
8
|
+
Roseflow::InteractionContext.make(
|
9
|
+
repository_url: repository_url
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
before do
|
14
|
+
@context = Actions::CloneAndLoadRepository.execute(ctx)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "loading files to document database" do
|
18
|
+
it "loads the files" do
|
19
|
+
expect(action).to be_a_success
|
20
|
+
expect(action.database.files.count).to be > 5
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
Binary file
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Interactions::GithubRepositoryChat do
|
4
|
+
let(:prompt) { GithubChatPrompt.new("Describe me how to use OpenAI models with Roseflow.") }
|
5
|
+
let(:ctx) do
|
6
|
+
Roseflow::InteractionContext.make(
|
7
|
+
provider: :openai,
|
8
|
+
model: "gpt-3.5-turbo",
|
9
|
+
repository_url: "https://github.com/roseflow-ai/roseflow-openai",
|
10
|
+
prompt: prompt
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "" do
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "roseflow/action"
|
4
|
+
require "roseflow/ai/model"
|
5
|
+
|
6
|
+
module Roseflow
|
7
|
+
module Actions
|
8
|
+
module AI
|
9
|
+
class ResolveModel
|
10
|
+
extend Roseflow::Action
|
11
|
+
|
12
|
+
expects :model
|
13
|
+
promises :llm
|
14
|
+
|
15
|
+
executed do |context|
|
16
|
+
model = context.provider.models.find(context[:model])
|
17
|
+
|
18
|
+
unless model
|
19
|
+
context.fail_and_return!("Model #{context[:model]} not found")
|
20
|
+
end
|
21
|
+
|
22
|
+
context[:llm] = Roseflow::AI::Model.new(name: model.name, provider: context.provider)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|