roseflow 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|