Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mariochavez/aoororachain
Aoororachain is Ruby chain tool to work with LLMs
https://github.com/mariochavez/aoororachain
artificial-intelligence large-language-models llm llm-inference
Last synced: 17 days ago
JSON representation
Aoororachain is Ruby chain tool to work with LLMs
- Host: GitHub
- URL: https://github.com/mariochavez/aoororachain
- Owner: mariochavez
- License: mit
- Created: 2023-06-25T23:20:13.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2023-07-12T22:45:43.000Z (over 1 year ago)
- Last Synced: 2024-12-22T13:22:20.177Z (29 days ago)
- Topics: artificial-intelligence, large-language-models, llm, llm-inference
- Language: Jupyter Notebook
- Homepage: https://mariochavez.io
- Size: 65.4 KB
- Stars: 33
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# Aoororachain
Aoororachain is Ruby chain tool to work with LLMs.
## Installation
Install the gem and add to the application’s Gemfile by executing:
```bash
$ bundle add aoororachain
```If bundler is not being used to manage dependencies, install the gem by executing:
```bash
$ gem install aoororachain
```## Requisites
Aoororachain was primarily created to work locally with private data and Open Source LLMs. If you are looking for a tool to integrate OpenAI or any other service, there are a handful of tools to do it in Ruby, Python, or Javascript in Github.
With this in mind, a few requisites are needed before you start working in a chain.
* Llama.cpp. First, you need to setup [llama.cpp](https://github.com/ggerganov/llama.cpp), an inference tool for the Llama model.
* LLM Server. [LLM Server](https://github.com/mariochavez/llm_server) is a Ruby server that exposes *llama.cpp* via an API interfase.
* Open Source LLM model. Refer to *llama.cpp* or *LLM Server* for options to download an Open Source model. Llama, Open Llama or Vicuna models are good models to start.
* Chroma DB. [Chroma DB]( [https://www.trychroma.com/](https://www.trychroma.com/) ) is an Open Source Vector database for document information retrieval.
* Python environment. Aoororachain uses Open Source embedding models. It uses by default any of `hkunlp/instructor-large`, `hkunlp/instructor-xl`, and `sentence-transformers/all-mpnet-base-v2`.### Python environment and Open Source embedding models.
You can install a Python environment using [miniconda](https://docs.conda.io/en/latest/miniconda.html). Here are the instructions for using it and installing additional dependencies and the Embedding models.
```bash
# This assumes installing miniconda on MacOS with Homebrew. If you use a different OS, follow the instructions on miniconda website.
$ brew install miniconda
# Initialize miniconda with your shell. Restart your shell for this to take effect.
$ conda init zsh
# After the shell restarts, create an environment and set Python version.
$ conda create -n llm python=3.9
# Now activate your new environment
$ conda activate llm
# Install Embedding models dependencies
$ pip -q install langchain sentence_transformers InstructorEmbedding
```The next step is to install the Embedding model or models you want to use. Here are the links to each model.
* [hkunlp/instructor-xl](https://huggingface.co/hkunlp/instructor-xl). 5Gb.
* [hkunlp/instructor-large](https://huggingface.co/hkunlp/instructor-large). 1.34Gb
* [sentence-transformers/all-mpnet-base-v2](https://huggingface.co/sentence-transformers/all-mpnet-base-v2). 438MbTo install any models, execute the following code in a Python repl. Replace *MODEL* with the name of the model. _Be aware that this will download the model from Internet._
```python
from InstructorEmbedding import INSTRUCTOR
from langchain.embeddings
import HuggingFaceInstructEmbeddingsinstructor_embeddings = HuggingFaceInstructEmbeddings(model_name="MODEL")
instructor_embeddings.embed_documents(list("Hello Ruby!"))
```You can skip this step, but Aoororachain will download the specified model on the first run.
## Usage
Aoororachain currently focused on QA Retrieval for your own documents. Hence, let's start with how to create embeddings for a set of documents.
### Document embeddings
Being able to QA your documents requires texts to be converted to numbers. These numbers are organized in vectors; they capture the word features and correlations in sentences. This is helpful when a question is asked and, through the vector, a program can find texts that are similar to the question asked.
The similar texts can then be sent to a Large Language Model (LLM) to make sense of them and produce a response in Natural Language Process (NLP).
Due to the context size limit of LLMs you can feed them a huge document for QA Retrieval, you need to chunk large texts into meaningful blocks. This process is part of the embedding creation process.
The process looks like the following:
1. Load documents—in this example, Ruby 3.2 documentation from 9,747 text files.
This is an example of one of the 9,747 text files:
```ruby
Object Array
Method collect
Method type instance_method
Call sequence ["array.map {|element| ... } -> new_array\narray.map -> new_enumerator"]
Source code 3.2:ruby-3.2.0/array.c:3825Calls the block, if given, with each element of self; returns a new Array whose elements are the return values from the block:
a = [:foo, 'bar', 2]
a1 = a.map {|element| element.class }
a1 # => [Symbol, String, Integer]Returns a new Enumerator if no block given:
a = [:foo, 'bar', 2]
a1 = a.map
a1 # => #Array#collect is an alias for Array#map.
Examples static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
}
return collect;
}
```2. Chunk texts into meaningful blocks.
3. Create embeddings for texts.
4. Store embeddings in a vector database.Aoororachain uses the Chroma vector database to store and query embeddings.
Here is an example for loading and creating the embeddings.
```ruby
require "aoororachain"# Setup logger.
Aoororachain.logger = Logger.new($stdout)
Aoororachain.log_level = Aoororachain::LEVEL_DEBUGchroma_host = "http://localhost:8000"
collection_name = "ruby-documentation"# You can define a custom Parser to clean data and maybe extract metadata.
# Here is the code of RubyDocParser that does exactly that.
class RubyDocParser
def self.parse(text)
name_match = text.match(/Name (\w+)/)
constant_match = text.match(/Constant (\w+)/)
object_match = text.match(/Object (\w+)/)
method_match = text.match(/Method ([\w\[\]\+\=\-\*\%\/]+)/)
metadata = {}
metadata[:name] = name_match[1] if name_match
metadata[:constant] = constant_match[1] if constant_match
metadata[:object] = object_match[1] if object_match
metadata[:method] = method_match[1] if method_match
metadata[:lang] = :ruby
metadata[:version] = "3.2"
text.gsub!(/\s+/, " ").strip!
[text, metadata]
end
end# A DirectoryLoader points to a path and sets the glob for the files you want to load.
# A loader is also specified. FileLoader just opens and reads the file content.
# The RubyDocParser is set as well. This is optional in case you data is very nice and needs no pre-processing.
directory_loader = Aoororachain::Loaders::DirectoryLoader.new(path: "./ruby-docs", glob: "**/*.txt", loader: Aoororachain::Loaders::FileLoader, parser: RubyDocParser)
files = directory_loader.load# With your data clean and ready, now it is time to chunk it. The chunk size depends of the context size of the LLMs that you want to use.
# 512 is a good number to start, don't go lower than that. An overlap can also be specified.
text_splitter = Aoororachain::RecursiveTextSplitter.new(size: 512, overlap: 0)texts = []
files.each do |file|
texts.concat(text_splitter.split_documents(file))
end# The final step is to create and store the embeddings.
# First, select an embedding model
model = Aoororachain::Embeddings::LocalPythonEmbedding::MODEL_INSTRUCTOR_L
# Create an instance of the embedder. device is optional. Possible options are:
# - cuda. If you have an external GPU
# - mps. If you have an Apple Sillicon chip (M1 to M2).
# - cpu or empty. It will use the CPU by default.
embedder = Aoororachain::Embeddings::LocalPythonEmbedding.new(model:, device: "mps")
# Configure your Vector database.
vector_database = Aoororachain::VectorStores::Chroma.new(embedder: embedder, options: {host: chroma_host})# Embbed your files. This can take a few minutes up to hours, depending on the size of your documents and the model used.
vector_database.from_documents(texts, index: collection_name)
```With embedding loaded in the database, you can use a tool like Chroma UI -**not yet released** - to query documents.
![chroma-ui](https://github.com/mariochavez/aoororachain/assets/59967/d65dea13-c6ef-452a-9774-8cf3b47c048f)Now you can query your embeddings with Aoororachain.
```ruby
# Define a retriever for the Vector database.
retriever = Aoororachain::VectorStores::Retriever.new(vector_database)# Query documents, results by default is 3.
documents = retriever.search("how can I use the Data class?", results: 4)# Print retrieved documents and their similarity distance from the question.
puts documents.map(&:document).join(" ")
puts documents.map(&:distance)
```### Query LLM with context.
With embeddings ready, it is time to create a _chain_ to perform QA Retrieval using the embedded documents as context.
```ruby
require "aoororachain"# Setup logger.
Aoororachain.logger = Logger.new($stdout)
Aoororachain.log_level = Aoororachain::LEVEL_DEBUGllm_host = "http://localhost:9292"
chroma_host = "http://localhost:8000"
collection_name = "ruby-documentation"model = Aoororachain::Embeddings::LocalPythonEmbedding::MODEL_INSTRUCTOR_L
embedder = Aoororachain::Embeddings::LocalPythonEmbedding.new(model:, device: "mps")
vector_database = Aoororachain::VectorStores::Chroma.new(embedder: embedder, options: {host: chroma_host, log_level: Chroma::LEVEL_DEBUG})
vector_database.from_index(collection_name)retriever = Aoororachain::VectorStores::Retriever.new(vector_database)
# Configure the LLM Server
llm = Aoororachain::Llms::LlamaServer.new(llm_host)# Create the chain to connect the Vector database retriever with the LLM.
chain = Aoororachain::Chains::RetrievalQA.new(llm, retriever)# Create a template for the LLM. Aoororachain does not include any templates because these are model specific. The following template is for the Vicuna model.
template = "A conversation between a human and an AI assistant. The assistant responds to a question using the context. Context: ===%{context}===. Question: %{prompt}"response = chain.complete(prompt: "given the following array [[1,3], [2,4]], how can I get a flatten and sorted array?", prompt_template: template)
```_response_ is a Hash with two keys: _response_ and _sources_.
```ruby
pp response
{:response=>
"User: Assistant: Assistant: To flatten the nested arrays in an array and sort it, you can use Ruby's built-in `sort` method along with the `flatten` method. Here is an example of how to do this for the given array [[1, 3], [2, 4]]:\n" +
"```ruby\n" +
"array = [[1, 3], [2, 4]]\n" +
"sorted_and_flattened_array = array.sort { |a, b| a[0] <=> b[0] }.flat_map(&:to_a)\n" +
"# Output: [1, 2, 3, 4]\n" +
"```\n",
:sources=>
[{"source"=>"./ruby-docs/hash-flatten.txt", "object"=>"Hash", "method"=>"flatten", "lang"=>"ruby", "version"=>"3.2"},
{"source"=>"./ruby-docs/array-flatten.txt", "object"=>"Array", "method"=>"flatten", "lang"=>"ruby", "version"=>"3.2"},
{"source"=>"./ruby-docs/array-flatten.txt", "object"=>"Array", "method"=>"flatten", "lang"=>"ruby", "version"=>"3.2"},
{"source"=>"./ruby-docs/array-flatten2.txt", "object"=>"Array", "method"=>"flatten", "lang"=>"ruby", "version"=>"3.2"}]}
```Where _response_ is tge generated response from the LLM and _sources_ is the list of text chunks that were sent to the LLM as context.
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/mariochavez/aoororachain. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/mariochavez/aoororachain/blob/main/CODE_OF_CONDUCT.md).
## License
The gem is available as open source under the terms of the [MIT License](https://github.com/mariochavez/aoororachain/blob/main/LICENSE.txt).
## Code of Conduct
Everyone interacting in the Aoororachain project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/mariochavez/aoororachain/blob/main/CODE_OF_CONDUCT.md).