langchainrb 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
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