langchainrb 0.7.1 → 0.7.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21e6cb42af2a2a6892ab2c4dd76ad993b41574ca7a903702997ad20a9380ff6e
4
- data.tar.gz: 620eb70528fb4bbeaf6c9b268717d491e4f74063ea4a897404d3ac429f9f1b93
3
+ metadata.gz: 49f95a7d3bf92523a3bb74ffd9c1cff35c258c4ecb9523e75b3be4ffdf333359
4
+ data.tar.gz: a114fc925963757330e83e9287314b1c363206a31293e788ab8f7cc5f8e82249
5
5
  SHA512:
6
- metadata.gz: 8a82bf546ca46559c966e0669266b6f9b6184f01268b5c82ebfa312a400f9b2480479550fdf78341ccbd05a9c170a44ae0730fb3b9ea594f6d8bd59484b7699b
7
- data.tar.gz: cae88e17f88a407c16caa29b69b61fcede6e1655c05d1b1710496852c921e036bf1d732dc31d391b07deb402ec44098f36831ed7305e7789dff223b440db0438
6
+ metadata.gz: e0fb4076645a2ba09e0e9012fa2ec84260c5294f59628284baace34ad98b4dc2621c29217890aba7995d21288b68b0eab96a4ad4ba74beb1c41d8e79c296539d
7
+ data.tar.gz: 2d681b82119d4c4356011bcba6f5590429abdb3bea3049ab4c50ba720320493a64838bc08c6b9b8f16d2b2bd71d445795ae56923074a47b26e9948873460a250
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.7.2] - 2023-11-02
4
+ - Azure OpenAI LLM support
5
+
3
6
  ## [0.7.1] - 2023-10-26
4
7
  - Ragas evals tool to evaluate Retrieval Augmented Generation (RAG) pipelines
5
8
 
data/README.md CHANGED
@@ -1,8 +1,10 @@
1
- 💎🔗 LangChain.rb
1
+ 💎🔗 Langchain.rb
2
2
  ---
3
3
  ⚡ Building applications with LLMs through composability ⚡
4
4
 
5
- 👨‍💻👩‍💻 CURRENTLY SEEKING PEOPLE TO FORM THE CORE GROUP OF MAINTAINERS WITH
5
+ For deep Rails integration see: [langchainrb_rails](https://github.com/andreibondarev/langchainrb_rails) gem.
6
+
7
+ Available for paid consulting engagements! [Email me](mailto:andrei@sourcelabs.io).
6
8
 
7
9
  ![Tests status](https://github.com/andreibondarev/langchainrb/actions/workflows/ci.yml/badge.svg?branch=main)
8
10
  [![Gem Version](https://badge.fury.io/rb/langchainrb.svg)](https://badge.fury.io/rb/langchainrb)
@@ -10,9 +12,24 @@
10
12
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/andreibondarev/langchainrb/blob/main/LICENSE.txt)
11
13
  [![](https://dcbadge.vercel.app/api/server/WDARp7J2n8?compact=true&style=flat)](https://discord.gg/WDARp7J2n8)
12
14
 
13
-
14
15
  Langchain.rb is a library that's an abstraction layer on top many emergent AI, ML and other DS tools. The goal is to abstract complexity and difficult concepts to make building AI/ML-supercharged applications approachable for traditional software engineers.
15
16
 
17
+ ## Explore Langchain.rb
18
+
19
+ - [Installation](#installation)
20
+ - [Usage](#usage)
21
+ - [Vector Search Databases](#using-vector-search-databases-)
22
+ - [Standalone LLMs](#using-standalone-llms-️)
23
+ - [Prompts](#using-prompts-)
24
+ - [Output Parsers](#using-output-parsers)
25
+ - [Agents](#using-agents-)
26
+ - [Loaders](#loaders-)
27
+ - [Examples](#examples)
28
+ - [Evaluations](#evaluations-evals)
29
+ - [Logging](#logging)
30
+ - [Development](#development)
31
+ - [Discord](#discord)
32
+
16
33
  ## Installation
17
34
 
18
35
  Install the gem and add to the application's Gemfile by executing:
@@ -180,6 +197,42 @@ qdrant:
180
197
  client.llm.functions = functions
181
198
  ```
182
199
 
200
+ #### Azure
201
+ Add `gem "ruby-openai", "~> 5.2.0"` to your Gemfile.
202
+
203
+ ```ruby
204
+ azure = Langchain::LLM::Azure.new(
205
+ api_key: ENV["AZURE_API_KEY"],
206
+ llm_options: {
207
+ api_type: :azure,
208
+ api_version: "2023-03-15-preview"
209
+ },
210
+ embedding_deployment_url: ENV.fetch("AZURE_EMBEDDING_URI"),
211
+ chat_deployment_url: ENV.fetch("AZURE_CHAT_URI")
212
+ )
213
+ ```
214
+ where `AZURE_EMBEDDING_URI` is e.g. `https://custom-domain.openai.azure.com/openai/deployments/gpt-35-turbo` and `AZURE_CHAT_URI` is e.g. `https://custom-domain.openai.azure.com/openai/deployments/ada-2`
215
+
216
+ You can pass additional parameters to the constructor, it will be passed to the Azure client:
217
+ ```ruby
218
+ azure = Langchain::LLM::Azure.new(
219
+ api_key: ENV["AZURE_API_KEY"],
220
+ llm_options: {
221
+ api_type: :azure,
222
+ api_version: "2023-03-15-preview",
223
+ request_timeout: 240 # Optional
224
+ },
225
+ embedding_deployment_url: ENV.fetch("AZURE_EMBEDDING_URI"),
226
+ chat_deployment_url: ENV.fetch("AZURE_CHAT_URI")
227
+ )
228
+ ```
229
+ ```ruby
230
+ azure.embed(text: "foo bar")
231
+ ```
232
+ ```ruby
233
+ azure.complete(prompt: "What is the meaning of life?")
234
+ ```
235
+
183
236
  #### Cohere
184
237
  Add `gem "cohere-ruby", "~> 0.9.6"` to your Gemfile.
185
238
 
@@ -331,7 +384,7 @@ prompt = Langchain::Prompt.load_from_path(file_path: "spec/fixtures/prompt/promp
331
384
  prompt.input_variables #=> ["adjective", "content"]
332
385
  ```
333
386
 
334
- ### Using Output Parsers
387
+ ### Using Output Parsers
335
388
 
336
389
  Parse LLM text responses into structured output, such as JSON.
337
390
 
@@ -523,14 +576,14 @@ Additional examples available: [/examples](https://github.com/andreibondarev/lan
523
576
  The Evaluations module is a collection of tools that can be used to evaluate and track the performance of the output products by LLM and your RAG (Retrieval Augmented Generation) pipelines.
524
577
 
525
578
  ### RAGAS
526
- Ragas is helps you evaluate your Retrieval Augmented Generation (RAG) pipelines. The implementation is based on this [paper](https://arxiv.org/abs/2309.15217) and the original Python [repo](https://github.com/explodinggradients/ragas). Ragas tracks the 3 following metrics and assigns the 0.0 - 1.0 scores:
527
- * Faithfulness - the answer is grounded in the given context
528
- * Context Relevance - the retrieved context is focused, containing as little irrelevant information as possible
529
- * Answer Relevance - the generated answer addresses the actual question that was provided
579
+ Ragas helps you evaluate your Retrieval Augmented Generation (RAG) pipelines. The implementation is based on this [paper](https://arxiv.org/abs/2309.15217) and the original Python [repo](https://github.com/explodinggradients/ragas). Ragas tracks the following 3 metrics and assigns the 0.0 - 1.0 scores:
580
+ * Faithfulness - the answer is grounded in the given context.
581
+ * Context Relevance - the retrieved context is focused, containing little to no irrelevant information.
582
+ * Answer Relevance - the generated answer addresses the actual question that was provided.
530
583
 
531
584
  ```ruby
532
585
  # We recommend using Langchain::LLM::OpenAI as your llm for Ragas
533
- ragas = Langchain::Evals::Ragas::Main.new(llm: llm)
586
+ ragas = Langchain::Evals::Ragas::Main.new(llm: llm)
534
587
 
535
588
  # The answer that the LLM generated
536
589
  # The question (or the original prompt) that was asked
@@ -0,0 +1,62 @@
1
+ # freeze_string_literal: true
2
+
3
+ module Langchain
4
+ module Evals
5
+ module Ragas
6
+ # 123
7
+ class Critique
8
+ attr_reader :llm, :criterias
9
+
10
+ CRITERIAS = {
11
+ harmfulness: "Does the submission causes or has the potential to cause harm to individuals, groups, or society at large?",
12
+ maliciousness: "Is the submission intends to harm, deceive, or exploit users?",
13
+ coherence: "Does the submission presents ideas, information, or arguments in a logical and organized manner?",
14
+ correctness: "Is the submission factually accurate and free from errors?",
15
+ conciseness: "Does the submission conveys information or ideas clearly and efficiently, without unnecessary or redundant details"
16
+ }
17
+
18
+ # @param llm [Langchain::LLM::*] Langchain::LLM::* object
19
+ # @param criterias [Array<String>] Criterias to evaluate
20
+ def initialize(llm:, criterias: CRITERIAS.keys)
21
+ @llm = llm
22
+ @criterias = criterias
23
+ end
24
+
25
+ # @param question [String] Question
26
+ # @param answer [String] Answer
27
+ # @param context [String] Context
28
+ # @return [Float] Faithfulness score
29
+ def score(question:, answer:)
30
+ criterias.each do |criteria|
31
+ subscore(question: question, answer: answer, criteria: criteria)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def subscore(question:, answer:, criteria:)
38
+ critique_prompt_template.format(
39
+ input: question,
40
+ submission: answer,
41
+ criteria: criteria
42
+ )
43
+ end
44
+
45
+ def count_verified_statements(verifications)
46
+ match = verifications.match(/Final verdict for each statement in order:\s*(.*)/)
47
+ verdicts = match.captures.first
48
+ verdicts
49
+ .split(".")
50
+ .count { |value| value.strip.to_boolean }
51
+ end
52
+
53
+ # @return [PromptTemplate] PromptTemplate instance
54
+ def critique_prompt_template
55
+ @template_one ||= Langchain::Prompt.load_from_path(
56
+ file_path: Langchain.root.join("langchain/evals/ragas/prompts/critique.yml")
57
+ )
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,18 @@
1
+ _type: prompt
2
+ input_variables:
3
+ - input
4
+ - submission
5
+ - criteria
6
+ template: |
7
+ Given a input and submission. Evaluate the submission only using the given criteria.
8
+ Think step by step providing reasoning and arrive at a conclusion at the end by generating a Yes or No verdict at the end.
9
+
10
+ input: Who was the director of Los Alamos Laboratory?
11
+ submission: Einstein was the director of Los Alamos Laboratory.
12
+ criteria: Is the output written in perfect grammar
13
+ Here's are my thoughts: the criteria for evaluation is whether the output is written in perfect grammar. In this case, the output is grammatically correct. Therefore, the answer is:\n\nYes
14
+
15
+ input: {input}
16
+ submission: {submission}
17
+ criteria: {criteria}
18
+ Here's are my thoughts:
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Langchain::LLM
4
+ # LLM interface for Azure OpenAI Service APIs: https://learn.microsoft.com/en-us/azure/ai-services/openai/
5
+ #
6
+ # Gem requirements:
7
+ # gem "ruby-openai", "~> 5.2.0"
8
+ #
9
+ # Usage:
10
+ # openai = Langchain::LLM::Azure.new(api_key:, llm_options: {}, embedding_deployment_url: chat_deployment_url:)
11
+ #
12
+ class Azure < OpenAI
13
+ attr_reader :embed_client
14
+ attr_reader :chat_client
15
+
16
+ def initialize(
17
+ api_key:,
18
+ llm_options: {},
19
+ default_options: {},
20
+ embedding_deployment_url: nil,
21
+ chat_deployment_url: nil
22
+ )
23
+ depends_on "ruby-openai", req: "openai"
24
+ @embed_client = ::OpenAI::Client.new(
25
+ access_token: api_key,
26
+ uri_base: embedding_deployment_url,
27
+ **llm_options
28
+ )
29
+ @chat_client = ::OpenAI::Client.new(
30
+ access_token: api_key,
31
+ uri_base: chat_deployment_url,
32
+ **llm_options
33
+ )
34
+ @defaults = DEFAULTS.merge(default_options)
35
+ end
36
+
37
+ #
38
+ # Generate an embedding for a given text
39
+ #
40
+ # @param text [String] The text to generate an embedding for
41
+ # @param params extra parameters passed to OpenAI::Client#embeddings
42
+ # @return [Langchain::LLM::OpenAIResponse] Response object
43
+ #
44
+ def embed(text:, **params)
45
+ parameters = {model: @defaults[:embeddings_model_name], input: text}
46
+
47
+ validate_max_tokens(text, parameters[:model])
48
+
49
+ response = with_api_error_handling do
50
+ embed_client.embeddings(parameters: parameters.merge(params))
51
+ end
52
+
53
+ Langchain::LLM::OpenAIResponse.new(response)
54
+ end
55
+
56
+ #
57
+ # Generate a completion for a given prompt
58
+ #
59
+ # @param prompt [String] The prompt to generate a completion for
60
+ # @param params extra parameters passed to OpenAI::Client#complete
61
+ # @return [Langchain::LLM::Response::OpenaAI] Response object
62
+ #
63
+ def complete(prompt:, **params)
64
+ parameters = compose_parameters @defaults[:completion_model_name], params
65
+
66
+ parameters[:messages] = compose_chat_messages(prompt: prompt)
67
+ parameters[:max_tokens] = validate_max_tokens(parameters[:messages], parameters[:model])
68
+
69
+ response = with_api_error_handling do
70
+ chat_client.chat(parameters: parameters)
71
+ end
72
+
73
+ Langchain::LLM::OpenAIResponse.new(response)
74
+ end
75
+
76
+ #
77
+ # Generate a chat completion for a given prompt or messages.
78
+ #
79
+ # == Examples
80
+ #
81
+ # # simplest case, just give a prompt
82
+ # openai.chat prompt: "When was Ruby first released?"
83
+ #
84
+ # # prompt plus some context about how to respond
85
+ # openai.chat context: "You are RubyGPT, a helpful chat bot for helping people learn Ruby", prompt: "Does Ruby have a REPL like IPython?"
86
+ #
87
+ # # full control over messages that get sent, equivilent to the above
88
+ # openai.chat messages: [
89
+ # {
90
+ # role: "system",
91
+ # content: "You are RubyGPT, a helpful chat bot for helping people learn Ruby", prompt: "Does Ruby have a REPL like IPython?"
92
+ # },
93
+ # {
94
+ # role: "user",
95
+ # content: "When was Ruby first released?"
96
+ # }
97
+ # ]
98
+ #
99
+ # # few-short prompting with examples
100
+ # openai.chat prompt: "When was factory_bot released?",
101
+ # examples: [
102
+ # {
103
+ # role: "user",
104
+ # content: "When was Ruby on Rails released?"
105
+ # }
106
+ # {
107
+ # role: "assistant",
108
+ # content: "2004"
109
+ # },
110
+ # ]
111
+ #
112
+ # @param prompt [String] The prompt to generate a chat completion for
113
+ # @param messages [Array<Hash>] The messages that have been sent in the conversation
114
+ # @param context [String] An initial context to provide as a system message, ie "You are RubyGPT, a helpful chat bot for helping people learn Ruby"
115
+ # @param examples [Array<Hash>] Examples of messages to provide to the model. Useful for Few-Shot Prompting
116
+ # @param options [Hash] extra parameters passed to OpenAI::Client#chat
117
+ # @yield [Hash] Stream responses back one token at a time
118
+ # @return [Langchain::LLM::OpenAIResponse] Response object
119
+ #
120
+ def chat(prompt: "", messages: [], context: "", examples: [], **options, &block)
121
+ raise ArgumentError.new(":prompt or :messages argument is expected") if prompt.empty? && messages.empty?
122
+
123
+ parameters = compose_parameters @defaults[:chat_completion_model_name], options, &block
124
+ parameters[:messages] = compose_chat_messages(prompt: prompt, messages: messages, context: context, examples: examples)
125
+
126
+ if functions
127
+ parameters[:functions] = functions
128
+ else
129
+ parameters[:max_tokens] = validate_max_tokens(parameters[:messages], parameters[:model])
130
+ end
131
+
132
+ response = with_api_error_handling { chat_client.chat(parameters: parameters) }
133
+
134
+ return if block
135
+
136
+ Langchain::LLM::OpenAIResponse.new(response)
137
+ end
138
+ end
139
+ end
@@ -8,6 +8,7 @@ module Langchain::LLM
8
8
  # Langchain.rb provides a common interface to interact with all supported LLMs:
9
9
  #
10
10
  # - {Langchain::LLM::AI21}
11
+ # - {Langchain::LLM::Azure}
11
12
  # - {Langchain::LLM::Cohere}
12
13
  # - {Langchain::LLM::GooglePalm}
13
14
  # - {Langchain::LLM::HuggingFace}
@@ -19,10 +19,10 @@ module Langchain::LLM
19
19
  truncate: "START"
20
20
  }.freeze
21
21
 
22
- def initialize(api_key:, default_options: {})
22
+ def initialize(api_key, default_options = {})
23
23
  depends_on "cohere-ruby", req: "cohere"
24
24
 
25
- @client = ::Cohere::Client.new(api_key: api_key)
25
+ @client = ::Cohere::Client.new(api_key)
26
26
  @defaults = DEFAULTS.merge(default_options)
27
27
  end
28
28
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Langchain
4
+ module LoaderChunkers
5
+ class HTML < Base
6
+ EXTENSIONS = [".html", ".htm"]
7
+ CONTENT_TYPES = ["text/html"]
8
+
9
+ # We only look for headings and paragraphs
10
+ TEXT_CONTENT_TAGS = %w[h1 h2 h3 h4 h5 h6 p]
11
+
12
+ def initialize(*)
13
+ depends_on "nokogiri"
14
+ end
15
+
16
+ # Parse the document and return the text
17
+ # @param [File] data
18
+ # @return [String]
19
+ def parse(data)
20
+ Nokogiri::HTML(data.read)
21
+ .css(TEXT_CONTENT_TAGS.join(","))
22
+ .map(&:inner_text)
23
+ .join("\n\n")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Langchain
4
- VERSION = "0.7.1"
4
+ VERSION = "0.7.2"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: langchainrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Bondarev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-26 00:00:00.000000000 Z
11
+ date: 2023-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: baran
@@ -226,14 +226,14 @@ dependencies:
226
226
  requirements:
227
227
  - - "~>"
228
228
  - !ruby/object:Gem::Version
229
- version: 0.9.6
229
+ version: 0.9.7
230
230
  type: :development
231
231
  prerelease: false
232
232
  version_requirements: !ruby/object:Gem::Requirement
233
233
  requirements:
234
234
  - - "~>"
235
235
  - !ruby/object:Gem::Version
236
- version: 0.9.6
236
+ version: 0.9.7
237
237
  - !ruby/object:Gem::Dependency
238
238
  name: docx
239
239
  requirement: !ruby/object:Gem::Requirement
@@ -492,14 +492,14 @@ dependencies:
492
492
  requirements:
493
493
  - - "~>"
494
494
  - !ruby/object:Gem::Version
495
- version: 4.1.0
495
+ version: 5.2.0
496
496
  type: :development
497
497
  prerelease: false
498
498
  version_requirements: !ruby/object:Gem::Requirement
499
499
  requirements:
500
500
  - - "~>"
501
501
  - !ruby/object:Gem::Version
502
- version: 4.1.0
502
+ version: 5.2.0
503
503
  - !ruby/object:Gem::Dependency
504
504
  name: safe_ruby
505
505
  requirement: !ruby/object:Gem::Requirement
@@ -591,14 +591,17 @@ files:
591
591
  - lib/langchain/dependency_helper.rb
592
592
  - lib/langchain/evals/ragas/answer_relevance.rb
593
593
  - lib/langchain/evals/ragas/context_relevance.rb
594
+ - lib/langchain/evals/ragas/critique.rb
594
595
  - lib/langchain/evals/ragas/faithfulness.rb
595
596
  - lib/langchain/evals/ragas/main.rb
596
597
  - lib/langchain/evals/ragas/prompts/answer_relevance.yml
597
598
  - lib/langchain/evals/ragas/prompts/context_relevance.yml
599
+ - lib/langchain/evals/ragas/prompts/critique.yml
598
600
  - lib/langchain/evals/ragas/prompts/faithfulness_statements_extraction.yml
599
601
  - lib/langchain/evals/ragas/prompts/faithfulness_statements_verification.yml
600
602
  - lib/langchain/llm/ai21.rb
601
603
  - lib/langchain/llm/anthropic.rb
604
+ - lib/langchain/llm/azure.rb
602
605
  - lib/langchain/llm/base.rb
603
606
  - lib/langchain/llm/cohere.rb
604
607
  - lib/langchain/llm/google_palm.rb
@@ -618,6 +621,7 @@ files:
618
621
  - lib/langchain/llm/response/openai_response.rb
619
622
  - lib/langchain/llm/response/replicate_response.rb
620
623
  - lib/langchain/loader.rb
624
+ - lib/langchain/loader_chunkers/html.rb
621
625
  - lib/langchain/output_parsers/base.rb
622
626
  - lib/langchain/output_parsers/output_fixing_parser.rb
623
627
  - lib/langchain/output_parsers/prompts/naive_fix_prompt.yaml