langchainrb 0.6.10 → 0.6.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +5 -7
  4. data/lib/langchain/agent/base.rb +1 -0
  5. data/lib/langchain/agent/{react_agent/react_agent.rb → react_agent.rb} +12 -11
  6. data/lib/langchain/ai_message.rb +9 -0
  7. data/lib/langchain/conversation.rb +11 -11
  8. data/lib/langchain/conversation_memory.rb +3 -7
  9. data/lib/langchain/human_message.rb +9 -0
  10. data/lib/langchain/llm/anthropic.rb +3 -2
  11. data/lib/langchain/llm/cohere.rb +2 -1
  12. data/lib/langchain/llm/google_palm.rb +15 -10
  13. data/lib/langchain/llm/llama_cpp.rb +5 -5
  14. data/lib/langchain/llm/openai.rb +24 -25
  15. data/lib/langchain/llm/replicate.rb +2 -1
  16. data/lib/langchain/loader.rb +2 -2
  17. data/lib/langchain/message.rb +35 -0
  18. data/lib/langchain/output_parsers/base.rb +5 -4
  19. data/lib/langchain/output_parsers/{fix.rb → output_fixing_parser.rb} +3 -1
  20. data/lib/langchain/prompt/loading.rb +73 -67
  21. data/lib/langchain/prompt.rb +5 -0
  22. data/lib/langchain/system_message.rb +9 -0
  23. data/lib/langchain/tool/base.rb +14 -14
  24. data/lib/langchain/vectorsearch/milvus.rb +46 -5
  25. data/lib/langchain/vectorsearch/pgvector.rb +7 -5
  26. data/lib/langchain/version.rb +1 -1
  27. data/lib/langchain.rb +19 -97
  28. metadata +37 -38
  29. data/.env.example +0 -21
  30. data/.rspec +0 -3
  31. data/.rubocop.yml +0 -11
  32. data/.tool-versions +0 -1
  33. data/Gemfile +0 -14
  34. data/Gemfile.lock +0 -360
  35. data/Rakefile +0 -17
  36. data/examples/conversation_with_openai.rb +0 -52
  37. data/examples/create_and_manage_few_shot_prompt_templates.rb +0 -36
  38. data/examples/create_and_manage_prompt_templates.rb +0 -25
  39. data/examples/create_and_manage_prompt_templates_using_structured_output_parser.rb +0 -116
  40. data/examples/llama_cpp.rb +0 -24
  41. data/examples/open_ai_function_calls.rb +0 -41
  42. data/examples/open_ai_qdrant_function_calls.rb +0 -43
  43. data/examples/pdf_store_and_query_with_chroma.rb +0 -40
  44. data/examples/store_and_query_with_pinecone.rb +0 -46
  45. data/examples/store_and_query_with_qdrant.rb +0 -37
  46. data/examples/store_and_query_with_weaviate.rb +0 -32
  47. data/lefthook.yml +0 -5
  48. data/sig/langchain.rbs +0 -4
  49. /data/lib/langchain/agent/{sql_query_agent/sql_query_agent.rb → sql_query_agent.rb} +0 -0
  50. /data/lib/langchain/output_parsers/{structured.rb → structured_output_parser.rb} +0 -0
@@ -1,25 +0,0 @@
1
- require "langchain"
2
-
3
- # Create a prompt with one input variable
4
- prompt = Langchain::Prompt::PromptTemplate.new(template: "Tell me a {adjective} joke.", input_variables: ["adjective"])
5
- prompt.format(adjective: "funny") # "Tell me a funny joke."
6
-
7
- # Create a prompt with multiple input variables
8
- prompt = Langchain::Prompt::PromptTemplate.new(template: "Tell me a {adjective} joke about {content}.", input_variables: ["adjective", "content"])
9
- prompt.format(adjective: "funny", content: "chickens") # "Tell me a funny joke about chickens."
10
-
11
- # Creating a PromptTemplate using just a prompt and no input_variables
12
- prompt = Langchain::Prompt::PromptTemplate.from_template("Tell me a {adjective} joke about {content}.")
13
- prompt.input_variables # ["adjective", "content"]
14
- prompt.format(adjective: "funny", content: "chickens") # "Tell me a funny joke about chickens."
15
-
16
- # Save prompt template to JSON file
17
- prompt.save(file_path: "spec/fixtures/prompt/prompt_template.json")
18
-
19
- # Loading a new prompt template using a JSON file
20
- prompt = Langchain::Prompt.load_from_path(file_path: "spec/fixtures/prompt/prompt_template.json")
21
- prompt.input_variables # ["adjective", "content"]
22
-
23
- # Loading a new prompt template using a YAML file
24
- prompt = Langchain::Prompt.load_from_path(file_path: "spec/fixtures/prompt/prompt_template.yaml")
25
- prompt.input_variables # ["adjective", "content"]
@@ -1,116 +0,0 @@
1
- require "langchain"
2
-
3
- # Generate a prompt that directs the LLM to provide a JSON response that adheres to a specific JSON schema.
4
- json_schema = {
5
- type: "object",
6
- properties: {
7
- name: {
8
- type: "string",
9
- description: "Persons name"
10
- },
11
- age: {
12
- type: "number",
13
- description: "Persons age"
14
- },
15
- interests: {
16
- type: "array",
17
- items: {
18
- type: "object",
19
- properties: {
20
- interest: {
21
- type: "string",
22
- description: "A topic of interest"
23
- },
24
- levelOfInterest: {
25
- type: "number",
26
- description: "A value between 0 and 100 of how interested the person is in this interest"
27
- }
28
- },
29
- required: ["interest", "levelOfInterest"],
30
- additionalProperties: false
31
- },
32
- minItems: 1,
33
- maxItems: 3,
34
- description: "A list of the person's interests"
35
- }
36
- },
37
- required: ["name", "age", "interests"],
38
- additionalProperties: false
39
- }
40
- parser = Langchain::OutputParsers::StructuredOutputParser.from_json_schema(json_schema)
41
- prompt = Langchain::Prompt::PromptTemplate.new(template: "Generate details of a fictional character.\n{format_instructions}\nCharacter description: {description}", input_variables: ["description", "format_instructions"])
42
- prompt.format(description: "Korean chemistry student", format_instructions: parser.get_format_instructions)
43
- # Generate details of a fictional character.
44
- # You must format your output as a JSON value that adheres to a given "JSON Schema" instance.
45
-
46
- # "JSON Schema" is a declarative language that allows you to annotate and validate JSON documents.
47
-
48
- # For example, the example "JSON Schema" instance {"properties": {"foo": {"description": "a list of test words", "type": "array", "items": {"type": "string"}}, "required": ["foo"]}
49
- # would match an object with one required property, "foo". The "type" property specifies "foo" must be an "array", and the "description" property semantically describes it as "a list of test words". The items within "foo" must be strings.
50
- # Thus, the object {"foo": ["bar", "baz"]} is a well-formatted instance of this example "JSON Schema". The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.
51
-
52
- # Your output will be parsed and type-checked according to the provided schema instance, so make sure all fields in your output match the schema exactly and there are no trailing commas!
53
-
54
- # Here is the JSON Schema instance your output must adhere to. Include the enclosing markdown codeblock:
55
- # ```json
56
- # {"type":"object","properties":{"name":{"type":"string","description":"Persons name"},"age":{"type":"number","description":"Persons age"},"interests":{"type":"array","items":{"type":"object","properties":{"interest":{"type":"string","description":"A topic of interest"},"levelOfInterest":{"type":"number","description":"A value between 0 and 100 of how interested the person is in this interest"},"required":["interest","levelOfInterest"],"additionalProperties":false},"minItems":1,"maxItems":3,"description":"A list of the person's interests"},"required":["name","age","interests"],"additionalProperties":false}
57
- # ```
58
-
59
- # Character description: Korean chemistry student
60
-
61
- llm = Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
62
- # llm_response = llm.chat(
63
- # prompt: prompt.format(description: "Korean chemistry student", format_instructions: parser.get_format_instructions)
64
- # )
65
-
66
- # LLM example response:
67
- llm_example_response = <<~RESPONSE
68
- Here is your character:
69
- ```json
70
- {
71
- "name": "Kim Ji-hyun",
72
- "age": 22,
73
- "interests": [
74
- {
75
- "interest": "Organic Chemistry",
76
- "levelOfInterest": 85
77
- },
78
- {
79
- "interest": "Biochemistry",
80
- "levelOfInterest": 70
81
- },
82
- {
83
- "interest": "Analytical Chemistry",
84
- "levelOfInterest": 60
85
- }
86
- ]
87
- }
88
- ```
89
- RESPONSE
90
-
91
- fix_parser = Langchain::OutputParsers::OutputFixingParser.from_llm(
92
- llm: llm,
93
- parser: parser
94
- )
95
- # The OutputFixingParser wraps the StructuredOutputParser such that if initial
96
- # LLM response does not conform to the schema, will call out the LLM to fix
97
- # the error
98
- fix_parser.parse(llm_example_response)
99
- # {
100
- # "name" => "Kim Ji-hyun",
101
- # "age" => 22,
102
- # "interests" => [
103
- # {
104
- # "interest" => "Organic Chemistry",
105
- # "levelOfInterest" => 85
106
- # },
107
- # {
108
- # "interest" => "Biochemistry",
109
- # "levelOfInterest" => 70
110
- # },
111
- # {
112
- # "interest" => "Analytical Chemistry",
113
- # "levelOfInterest" => 60
114
- # }
115
- # ]
116
- # }
@@ -1,24 +0,0 @@
1
- require "langchain"
2
-
3
- llm = Langchain::LLM::LlamaCpp.new(
4
- model_path: ENV["LLAMACPP_MODEL_PATH"],
5
- n_gpu_layers: Integer(ENV["LLAMACPP_N_GPU_LAYERS"]),
6
- n_threads: Integer(ENV["LLAMACPP_N_THREADS"])
7
- )
8
-
9
- instructions = [
10
- "Tell me about the creator of Ruby",
11
- "Write a story about a pony who goes to the store to buy some apples."
12
- ]
13
-
14
- template = Langchain::Prompt::PromptTemplate.new(
15
- template: "{instruction}\n\n### Response:",
16
- input_variables: %w[instruction]
17
- )
18
-
19
- instructions.each do |instruction|
20
- puts "USER: #{instruction}"
21
- prompt = template.format(instruction: instruction)
22
- response = llm.complete prompt: prompt, n_predict: 1024
23
- puts "ASSISTANT: #{response}"
24
- end
@@ -1,41 +0,0 @@
1
- require "langchain"
2
- require "dotenv/load"
3
-
4
- functions = [
5
- {
6
- name: "get_current_weather",
7
- description: "Get the current weather in a given location",
8
- parameters: {
9
- type: :object,
10
- properties: {
11
- location: {
12
- type: :string,
13
- description: "The city and state, e.g. San Francisco, CA"
14
- },
15
- unit: {
16
- type: "string",
17
- enum: %w[celsius fahrenheit]
18
- }
19
- },
20
- required: ["location"]
21
- }
22
- }
23
- ]
24
-
25
- openai = Langchain::LLM::OpenAI.new(
26
- api_key: ENV["OPENAI_API_KEY"],
27
- default_options: {
28
- chat_completion_model_name: "gpt-3.5-turbo-16k"
29
- }
30
- )
31
-
32
- chat = Langchain::Conversation.new(llm: openai)
33
-
34
- chat.set_context("You are the climate bot")
35
- chat.set_functions(functions)
36
-
37
- DONE = %w[done end eof exit].freeze
38
-
39
- user_message = "what's the weather in NYC?"
40
-
41
- puts chat.message(user_message)
@@ -1,43 +0,0 @@
1
- require "langchain"
2
- require "dotenv/load"
3
-
4
- functions = [
5
- {
6
- name: "create_rails_controller",
7
- description: "gives a command to create a rails controller",
8
- parameters: {
9
- type: :object,
10
- properties: {
11
- controller_name: {
12
- type: :string,
13
- description: "the controller name, e.g. users_controller"
14
- },
15
- unit: {
16
- type: "string",
17
- enum: %w[celsius fahrenheit]
18
- }
19
- },
20
- required: ["controller_name"]
21
- }
22
- }
23
- ]
24
-
25
- openai = Langchain::LLM::OpenAI.new(
26
- api_key: ENV["OPENAI_API_KEY"],
27
- default_options: {
28
- chat_completion_model_name: "gpt-3.5-turbo-16k"
29
- }
30
- )
31
-
32
- client = Langchain::Vectorsearch::Qdrant.new(
33
- url: ENV["QDRANT_URL"],
34
- api_key: ENV["QDRANT_API_KEY"],
35
- index_name: ENV["QDRANT_INDEX"],
36
- llm: openai
37
- )
38
-
39
- client.llm.functions = functions
40
- client.llm.complete_response = true
41
- chat = client.ask(question: "create a users_controller")
42
-
43
- puts chat
@@ -1,40 +0,0 @@
1
- require "langchain"
2
-
3
- # gem install chroma-db
4
- # or add `gem "chroma-db", "~> 0.3.0"` to your Gemfile
5
-
6
- # Instantiate the Chroma client
7
- chroma = Langchain::Vectorsearch::Chroma.new(
8
- url: ENV["CHROMA_URL"],
9
- index_name: "documents",
10
- llm: Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
11
- )
12
-
13
- # Create the default schema.
14
- chroma.create_default_schema
15
-
16
- # gem install these or add them to your Gemfile
17
- # Add `gem "pdf-reader", "~> 1.4"` to your Gemfile
18
- # Add `gem "docx", branch: "master", git: "https://github.com/ruby-docx/docx.git"` to your Gemfile
19
-
20
- # Set up an array of PDF and TXT documents
21
- docs = [
22
- Langchain.root.join("/docs/document.pdf"),
23
- Langchain.root.join("/docs/document.txt"),
24
- Langchain.root.join("/docs/document.docx")
25
- ]
26
-
27
- # Add data to the index. Weaviate will use OpenAI to generate embeddings behind the scene.
28
- chroma.add_data(
29
- paths: docs
30
- )
31
-
32
- # Query your data
33
- chroma.similarity_search(
34
- query: "..."
35
- )
36
-
37
- # Interact with your index through Q&A
38
- chroma.ask(
39
- question: "..."
40
- )
@@ -1,46 +0,0 @@
1
- require "langchain"
2
-
3
- # gem install pinecone
4
- # or add `gem "pinecone"` to your Gemfile
5
-
6
- # Instantiate the Pinecone client
7
- pinecone = Langchain::Vectorsearch::Pinecone.new(
8
- environment: ENV["PINECONE_ENVIRONMENT"],
9
- api_key: ENV["PINECONE_API_KEY"],
10
- index_name: "recipes",
11
- llm: Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
12
- )
13
-
14
- # Create the default schema.
15
- # If you are using the free Pinecone tier, ensure there is not an existing schema/index
16
- pinecone.create_default_schema
17
-
18
- # Set up an array of text strings
19
- recipes = [
20
- "Preheat oven to 400 degrees F (200 degrees C). Cut the top off the head of garlic. Arrange the garlic, carrots, celery, onion, pepper, and tomato on a large baking sheet in a single layer. Drizzle the olive oil over the vegetables; season with salt and pepper. Roast the vegetables in the preheated oven, turning every 20 minutes, until tender and browned, about 1 hour. Combine the water, thyme, parsley, and bay leaves in a large stock pot over medium-high heat. Squeeze the head of garlic into the stock pot, and discard the outer husk. Place the carrots, celery, onion, pepper, and tomato in the stock pot. Bring the water to a boil; reduce heat to low and simmer for 1 1/2 hours; strain and cool.",
21
- "Heat oven to 190C/fan 170C/gas 5. Heat 1 tbsp oil and the butter in a frying pan, then add the onion and fry for 5 mins until softened. Cool slightly. Tip the sausagemeat, lemon zest, breadcrumbs, apricots, chestnuts and thyme into a bowl. Add the onion and cranberries, and mix everything together with your hands, adding plenty of pepper and a little salt. Cut each chicken breast into three fillets lengthwise and season all over with salt and pepper. Heat the remaining oil in the frying pan, and fry the chicken fillets quickly until browned, about 6-8 mins. Roll out two-thirds of the pastry to line a 20-23cm springform or deep loose-based tart tin. Press in half the sausage mix and spread to level. Then add the chicken pieces in one layer and cover with the rest of the sausage. Press down lightly. Roll out the remaining pastry. Brush the edges of the pastry with beaten egg and cover with the pastry lid. Pinch the edges to seal, then trim. Brush the top of the pie with egg, then roll out the trimmings to make holly leaf shapes and berries. Decorate the pie and brush again with egg. Set the tin on a baking sheet and bake for 50-60 mins, then cool in the tin for 15 mins. Remove and leave to cool completely. Serve with a winter salad and pickles."
22
- ]
23
-
24
- # Add data to the index. Pinecone will use OpenAI to generate embeddings behind the scene.
25
- pinecone.add_texts(
26
- texts: recipes
27
- )
28
-
29
- # Query your data
30
- pinecone.similarity_search(
31
- query: "chicken",
32
- k: 1
33
- )
34
-
35
- # Interact with your index through Q&A
36
- pinecone.ask(
37
- question: "What is a good recipe for chicken?"
38
- )
39
-
40
- # Generate an embedding and search by it
41
- openai = Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
42
- embedding = openai.embed(text: "veggie")
43
-
44
- pinecone.similarity_search_by_vector(
45
- embedding: embedding
46
- )
@@ -1,37 +0,0 @@
1
- require "langchain"
2
-
3
- # gem install qdrant-ruby
4
- # or add `gem "qdrant-ruby"` to your Gemfile
5
-
6
- # Instantiate the Qdrant client
7
- qdrant = Langchain::Vectorsearch::Qdrant.new(
8
- url: ENV["QDRANT_URL"],
9
- api_key: ENV["QDRANT_API_KEY"],
10
- index_name: "recipes",
11
- llm: Langchain::LLM::Cohere.new(api_key: ENV["COHERE_API_KEY"])
12
- )
13
-
14
- # Create the default schema.
15
- qdrant.create_default_schema
16
-
17
- # Set up an array of text strings
18
- recipes = [
19
- "Preheat oven to 400 degrees F (200 degrees C). Cut the top off the head of garlic. Arrange the garlic, carrots, celery, onion, pepper, and tomato on a large baking sheet in a single layer. Drizzle the olive oil over the vegetables; season with salt and pepper. Roast the vegetables in the preheated oven, turning every 20 minutes, until tender and browned, about 1 hour. Combine the water, thyme, parsley, and bay leaves in a large stock pot over medium-high heat. Squeeze the head of garlic into the stock pot, and discard the outer husk. Place the carrots, celery, onion, pepper, and tomato in the stock pot. Bring the water to a boil; reduce heat to low and simmer for 1 1/2 hours; strain and cool.",
20
- "Heat oven to 190C/fan 170C/gas 5. Heat 1 tbsp oil and the butter in a frying pan, then add the onion and fry for 5 mins until softened. Cool slightly. Tip the sausagemeat, lemon zest, breadcrumbs, apricots, chestnuts and thyme into a bowl. Add the onion and cranberries, and mix everything together with your hands, adding plenty of pepper and a little salt. Cut each chicken breast into three fillets lengthwise and season all over with salt and pepper. Heat the remaining oil in the frying pan, and fry the chicken fillets quickly until browned, about 6-8 mins. Roll out two-thirds of the pastry to line a 20-23cm springform or deep loose-based tart tin. Press in half the sausage mix and spread to level. Then add the chicken pieces in one layer and cover with the rest of the sausage. Press down lightly. Roll out the remaining pastry. Brush the edges of the pastry with beaten egg and cover with the pastry lid. Pinch the edges to seal, then trim. Brush the top of the pie with egg, then roll out the trimmings to make holly leaf shapes and berries. Decorate the pie and brush again with egg. Set the tin on a baking sheet and bake for 50-60 mins, then cool in the tin for 15 mins. Remove and leave to cool completely. Serve with a winter salad and pickles."
21
- ]
22
-
23
- # Add data to the index. Weaviate will use OpenAI to generate embeddings behind the scene.
24
- qdrant.add_texts(
25
- texts: recipes
26
- )
27
-
28
- # Query your data
29
- qdrant.similarity_search(
30
- query: "chicken",
31
- k: 1
32
- )
33
-
34
- # Interact with your index through Q&A
35
- qdrant.ask(
36
- question: "What is the best recipe for chicken?"
37
- )
@@ -1,32 +0,0 @@
1
- require "langchain"
2
-
3
- # gem install weaviate-ruby
4
- # or add `gem "weaviate-ruby"` to your Gemfile
5
-
6
- # Instantiate the Weaviate client
7
- weaviate = Langchain::Vectorsearch::Weaviate.new(
8
- url: ENV["WEAVIATE_URL"],
9
- api_key: ENV["WEAVIATE_API_KEY"],
10
- index_name: "Recipes",
11
- llm: Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
12
- )
13
-
14
- # Create the default schema. A text field `content` will be used.
15
- weaviate.create_default_schema
16
-
17
- # Set up an array of text strings
18
- recipes = [
19
- "Preheat oven to 400 degrees F (200 degrees C). Cut the top off the head of garlic. Arrange the garlic, carrots, celery, onion, pepper, and tomato on a large baking sheet in a single layer. Drizzle the olive oil over the vegetables; season with salt and pepper. Roast the vegetables in the preheated oven, turning every 20 minutes, until tender and browned, about 1 hour. Combine the water, thyme, parsley, and bay leaves in a large stock pot over medium-high heat. Squeeze the head of garlic into the stock pot, and discard the outer husk. Place the carrots, celery, onion, pepper, and tomato in the stock pot. Bring the water to a boil; reduce heat to low and simmer for 1 1/2 hours; strain and cool.",
20
- "Heat oven to 190C/fan 170C/gas 5. Heat 1 tbsp oil and the butter in a frying pan, then add the onion and fry for 5 mins until softened. Cool slightly. Tip the sausagemeat, lemon zest, breadcrumbs, apricots, chestnuts and thyme into a bowl. Add the onion and cranberries, and mix everything together with your hands, adding plenty of pepper and a little salt. Cut each chicken breast into three fillets lengthwise and season all over with salt and pepper. Heat the remaining oil in the frying pan, and fry the chicken fillets quickly until browned, about 6-8 mins. Roll out two-thirds of the pastry to line a 20-23cm springform or deep loose-based tart tin. Press in half the sausage mix and spread to level. Then add the chicken pieces in one layer and cover with the rest of the sausage. Press down lightly. Roll out the remaining pastry. Brush the edges of the pastry with beaten egg and cover with the pastry lid. Pinch the edges to seal, then trim. Brush the top of the pie with egg, then roll out the trimmings to make holly leaf shapes and berries. Decorate the pie and brush again with egg. Set the tin on a baking sheet and bake for 50-60 mins, then cool in the tin for 15 mins. Remove and leave to cool completely. Serve with a winter salad and pickles."
21
- ]
22
-
23
- # Add data to the index. Weaviate will use OpenAI to generate embeddings behind the scene.
24
- weaviate.add_texts(
25
- texts: recipes
26
- )
27
-
28
- # Query your data
29
- weaviate.similarity_search(
30
- query: "chicken",
31
- k: 1
32
- )
data/lefthook.yml DELETED
@@ -1,5 +0,0 @@
1
- pre-commit:
2
- commands:
3
- lint:
4
- run: standardrb --fix
5
- stage_fixed: true
data/sig/langchain.rbs DELETED
@@ -1,4 +0,0 @@
1
- module Langchain
2
- VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- end