⚡ Ruby で LLM を利用したアプリケーションを構築する ⚡
Rails との深い統合については、langchainrb_rails gem を参照してください。
有料コンサルティングも承ります!メールしてください。
以下を実行して gem をインストールし、アプリケーションの Gemfile に追加します。
bundle add langchainrb
依存関係の管理にバンドラーが使用されていない場合は、以下を実行して gem をインストールします。
gem install langchainrb
追加の宝石が必要になる場合があります。これらはデフォルトでは含まれていないため、必要なものだけを含めることができます。
require "langchain"
Langchain::LLM
モジュールは、さまざまな大規模言語モデル (LLM) プロバイダーと対話するための統合インターフェイスを提供します。この抽象化により、アプリケーション コードを変更せずに、異なる LLM バックエンド間を簡単に切り替えることができます。
すべての LLM クラスはLangchain::LLM::Base
を継承し、一般的な操作に一貫したインターフェイスを提供します。
ほとんどの LLM クラスは、API キーとオプションのデフォルト オプションを使用して初期化できます。
llm = Langchain :: LLM :: OpenAI . new (
api_key : ENV [ "OPENAI_API_KEY" ] ,
default_options : { temperature : 0.7 , chat_model : "gpt-4o" }
)
embed
メソッドを使用して、指定されたテキストの埋め込みを生成します。
response = llm . embed ( text : "Hello, world!" )
embedding = response . embedding
embed()
で受け入れられるパラメータtext
: (必須) 埋め込む入力テキスト。model
: (オプション) 使用するモデル名またはデフォルトの埋め込みモデルが使用されます。complete
メソッドを使用して、特定のプロンプトの補完を生成します。
response = llm . complete ( prompt : "Once upon a time" )
completion = response . completion
complete()
で受け入れられるパラメータprompt
: (必須) 完了のための入力プロンプト。max_tokens
: (オプション) 生成するトークンの最大数。temperature
: (オプション) 生成時のランダム性を制御します。値が大きいほど (0.8 など)、出力はよりランダムになり、値が小さいほど (0.2 など)、出力はより決定的になります。top_p
: (オプション) 温度の代わりに、生成されるトークンの多様性を制御します。n
: (オプション) 各プロンプトに対して生成する補完の数。stop
: (オプション) API がさらなるトークンの生成を停止するシーケンス。presence_penalty
: (オプション) これまでのテキスト内の存在に基づいて、新しいトークンにペナルティを与えます。frequency_penalty
: (オプション) これまでのテキスト内の頻度に基づいて、新しいトークンにペナルティを与えます。chat
メソッドを使用してチャット完了を生成します。
messages = [
{ role : "system" , content : "You are a helpful assistant." } ,
{ role : "user" , content : "What's the weather like today?" }
# Google Gemini and Google VertexAI expect messages in a different format:
# { role: "user", parts: [{ text: "why is the sky blue?" }]}
]
response = llm . chat ( messages : messages )
chat_completion = response . chat_completion
chat()
で受け入れられるパラメータmessages
: (必須) 会話履歴を表すメッセージ オブジェクトの配列。model
: (オプション) 使用する特定のチャット モデル。temperature
: (オプション) 生成時のランダム性を制御します。top_p
: (オプション) 温度の代わりに、生成されるトークンの多様性を制御します。n
: (オプション) 生成するチャット完了の選択肢の数。max_tokens
: (オプション) チャット完了で生成するトークンの最大数。stop
: (オプション) API がさらなるトークンの生成を停止するシーケンス。presence_penalty
: (オプション) これまでのテキスト内の存在に基づいて、新しいトークンにペナルティを与えます。frequency_penalty
: (オプション) これまでのテキスト内の頻度に基づいて、新しいトークンにペナルティを与えます。logit_bias
: (オプション) 指定されたトークンが補完に表示される可能性を変更します。user
: (オプション) エンドユーザーを表す一意の識別子。tools
: (オプション) モデルが呼び出すことができるツールのリスト。tool_choice
: (オプション) モデルが関数を呼び出す方法を制御します。 統合インターフェイスのおかげで、インスタンス化するクラスを変更することで、異なる LLM プロバイダーを簡単に切り替えることができます。
# Using Anthropic
anthropic_llm = Langchain :: LLM :: Anthropic . new ( api_key : ENV [ "ANTHROPIC_API_KEY" ] )
# Using Google Gemini
gemini_llm = Langchain :: LLM :: GoogleGemini . new ( api_key : ENV [ "GOOGLE_GEMINI_API_KEY" ] )
# Using OpenAI
openai_llm = Langchain :: LLM :: OpenAI . new ( api_key : ENV [ "OPENAI_API_KEY" ] )
各 LLM メソッドは、結果にアクセスするための一貫したインターフェイスを提供する応答オブジェクトを返します。
embedding
: 埋め込みベクトルを返します。completion
: 生成されたテキスト補完を返します。chat_completion
: 生成されたチャット完了を返します。tool_calls
: LLM によって行われたツール呼び出しを返します。prompt_tokens
: プロンプト内のトークンの数を返します。completion_tokens
: コンプリーション内のトークンの数を返します。total_tokens
: 使用されたトークンの合計数を返します。 注記
コア インターフェイスはプロバイダー間で一貫していますが、一部の LLM は追加の機能やパラメーターを提供する場合があります。プロバイダー固有の機能とオプションについては、各 LLM クラスのドキュメントを参照してください。
入力変数を使用してプロンプトを作成します。
prompt = Langchain :: Prompt :: PromptTemplate . new ( template : "Tell me a {adjective} joke about {content}." , input_variables : [ "adjective" , "content" ] )
prompt . format ( adjective : "funny" , content : "chickens" ) # "Tell me a funny joke about chickens."
input_variables を使用せずにプロンプトのみを使用して PromptTemplate を作成します。
prompt = Langchain :: Prompt :: PromptTemplate . from_template ( "Tell me a funny joke about chickens." )
prompt . input_variables # []
prompt . format # "Tell me a funny joke about chickens."
プロンプト テンプレートを JSON ファイルに保存します。
prompt . save ( file_path : "spec/fixtures/prompt/prompt_template.json" )
JSON ファイルを使用して新しいプロンプト テンプレートをロードします。
prompt = Langchain :: Prompt . load_from_path ( file_path : "spec/fixtures/prompt/prompt_template.json" )
prompt . input_variables # ["adjective", "content"]
いくつかのショットの例を含むプロンプトを作成します。
prompt = Langchain :: Prompt :: FewShotPromptTemplate . new (
prefix : "Write antonyms for the following words." ,
suffix : "Input: {adjective} n Output:" ,
example_prompt : Langchain :: Prompt :: PromptTemplate . new (
input_variables : [ "input" , "output" ] ,
template : "Input: {input} n Output: {output}"
) ,
examples : [
{ "input" : "happy" , "output" : "sad" } ,
{ "input" : "tall" , "output" : "short" }
] ,
input_variables : [ "adjective" ]
)
prompt . format ( adjective : "good" )
# Write antonyms for the following words.
#
# Input: happy
# Output: sad
#
# Input: tall
# Output: short
#
# Input: good
# Output:
プロンプト テンプレートを JSON ファイルに保存します。
prompt . save ( file_path : "spec/fixtures/prompt/few_shot_prompt_template.json" )
JSON ファイルを使用して新しいプロンプト テンプレートをロードします。
prompt = Langchain :: Prompt . load_from_path ( file_path : "spec/fixtures/prompt/few_shot_prompt_template.json" )
prompt . prefix # "Write antonyms for the following words."
YAML ファイルを使用して新しいプロンプト テンプレートをロードします。
prompt = Langchain :: Prompt . load_from_path ( file_path : "spec/fixtures/prompt/prompt_template.yaml" )
prompt . input_variables #=> ["adjective", "content"]
LLM テキスト応答を解析して、JSON などの構造化出力を生成します。
StructuredOutputParser
使用して、特定の JSON スキーマに準拠した JSON 応答を提供するように LLM に指示するプロンプトを生成できます。
json_schema = {
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
}
parser = Langchain :: OutputParsers :: StructuredOutputParser . from_json_schema ( json_schema )
prompt = Langchain :: Prompt :: PromptTemplate . new ( template : "Generate details of a fictional character. n {format_instructions} n Character description: {description}" , input_variables : [ "description" , "format_instructions" ] )
prompt_text = prompt . format ( description : "Korean chemistry student" , format_instructions : parser . get_format_instructions )
# Generate details of a fictional character.
# You must format your output as a JSON value that adheres to a given "JSON Schema" instance.
# ...
次に、llm 応答を解析します。
llm = Langchain :: LLM :: OpenAI . new ( api_key : ENV [ "OPENAI_API_KEY" ] )
llm_response = llm . chat ( messages : [ { role : "user" , content : prompt_text } ] ) . completion
parser . parse ( llm_response )
# {
# "name" => "Kim Ji-hyun",
# "age" => 22,
# "interests" => [
# {
# "interest" => "Organic Chemistry",
# "levelOfInterest" => 85
# },
# ...
# ]
# }
パーサーが LLM 応答の解析に失敗した場合は、 OutputFixingParser
使用できます。エラー メッセージ、以前の出力、および元のプロンプト テキストを LLM に送信し、「修正された」応答を求めます。
begin
parser . parse ( llm_response )
rescue Langchain :: OutputParsers :: OutputParserException => e
fix_parser = Langchain :: OutputParsers :: OutputFixingParser . from_llm (
llm : llm ,
parser : parser
)
fix_parser . parse ( llm_response )
end
あるいは、 OutputParserException
を処理する必要がない場合は、コードを簡素化することもできます。
# we already have the `OutputFixingParser`:
# parser = Langchain::OutputParsers::StructuredOutputParser.from_json_schema(json_schema)
fix_parser = Langchain :: OutputParsers :: OutputFixingParser . from_llm (
llm : llm ,
parser : parser
)
fix_parser . parse ( llm_response )
具体例はこちらをご覧ください
RAG は、LLM が正確で最新の情報を生成するのを支援する方法論です。一般的な RAG ワークフローは、次の 3 つのステップに従います。
Langchain.rb は、サポートされている Vectorsearch データベース上に便利な統合インターフェイスを提供し、インデックスの構成、データの追加、クエリとデータベースからの取得を簡単にします。
データベース | オープンソース | クラウドサービス |
---|---|---|
彩度 | ✅ | ✅ |
エプシラ | ✅ | ✅ |
ハンスリブ | ✅ | |
ミルバス | ✅ | ✅ ジリズクラウド |
松ぼっくり | ✅ | |
PGベクター | ✅ | ✅ |
クドラント | ✅ | ✅ |
ウィアビエイト | ✅ | ✅ |
エラスティックサーチ | ✅ | ✅ |
使用するベクトル検索データベースを選択し、gem の依存関係を追加して、クライアントをインスタンス化します。
gem "weaviate-ruby" , "~> 0.8.9"
埋め込みの生成に使用する LLM プロバイダーを選択してインスタンス化します。
llm = Langchain :: LLM :: OpenAI . new ( api_key : ENV [ "OPENAI_API_KEY" ] )
client = Langchain :: Vectorsearch :: Weaviate . new (
url : ENV [ "WEAVIATE_URL" ] ,
api_key : ENV [ "WEAVIATE_API_KEY" ] ,
index_name : "Documents" ,
llm : llm
)
サポートされている他のベクトル検索データベースをインスタンス化できます。
client = Langchain :: Vectorsearch :: Chroma . new ( ... ) # `gem "chroma-db", "~> 0.6.0"`
client = Langchain :: Vectorsearch :: Epsilla . new ( ... ) # `gem "epsilla-ruby", "~> 0.0.3"`
client = Langchain :: Vectorsearch :: Hnswlib . new ( ... ) # `gem "hnswlib", "~> 0.8.1"`
client = Langchain :: Vectorsearch :: Milvus . new ( ... ) # `gem "milvus", "~> 0.9.3"`
client = Langchain :: Vectorsearch :: Pinecone . new ( ... ) # `gem "pinecone", "~> 0.1.6"`
client = Langchain :: Vectorsearch :: Pgvector . new ( ... ) # `gem "pgvector", "~> 0.2"`
client = Langchain :: Vectorsearch :: Qdrant . new ( ... ) # `gem "qdrant-ruby", "~> 0.9.3"`
client = Langchain :: Vectorsearch :: Elasticsearch . new ( ... ) # `gem "elasticsearch", "~> 8.2.0"`
デフォルトのスキーマを作成します。
client . create_default_schema
プレーン テキスト データをベクトル検索データベースに追加します。
client . add_texts (
texts : [
"Begin by preheating your oven to 375°F (190°C). Prepare four boneless, skinless chicken breasts by cutting a pocket into the side of each breast, being careful not to cut all the way through. Season the chicken with salt and pepper to taste. In a large skillet, melt 2 tablespoons of unsalted butter over medium heat. Add 1 small diced onion and 2 minced garlic cloves, and cook until softened, about 3-4 minutes. Add 8 ounces of fresh spinach and cook until wilted, about 3 minutes. Remove the skillet from heat and let the mixture cool slightly." ,
"In a bowl, combine the spinach mixture with 4 ounces of softened cream cheese, 1/4 cup of grated Parmesan cheese, 1/4 cup of shredded mozzarella cheese, and 1/4 teaspoon of red pepper flakes. Mix until well combined. Stuff each chicken breast pocket with an equal amount of the spinach mixture. Seal the pocket with a toothpick if necessary. In the same skillet, heat 1 tablespoon of olive oil over medium-high heat. Add the stuffed chicken breasts and sear on each side for 3-4 minutes, or until golden brown."
]
)
または、ファイル パーサーを使用して、データをデータベースにロード、解析、インデックス付けします。
my_pdf = Langchain . root . join ( "path/to/my.pdf" )
my_text = Langchain . root . join ( "path/to/my.txt" )
my_docx = Langchain . root . join ( "path/to/my.docx" )
client . add_data ( paths : [ my_pdf , my_text , my_docx ] )
サポートされているファイル形式: docx、html、pdf、text、json、jsonl、csv、xlsx、eml、pptx。
渡されたクエリ文字列に基づいて類似のドキュメントを取得します。
client . similarity_search (
query : ,
k : # number of results to be retrieved
)
HyDE 手法を介して渡されたクエリ文字列に基づいて、同様のドキュメントを取得します。
client . similarity_search_with_hyde ( )
渡された埋め込みに基づいて類似のドキュメントを取得します。
client . similarity_search_by_vector (
embedding : ,
k : # number of results to be retrieved
)
RAG ベースのクエリ
client . ask ( question : "..." )
Langchain::Assistant
大規模言語モデル (LLM)、ツール、会話管理を組み合わせて、インテリジェントで対話型のアシスタントを作成する強力で柔軟なクラスです。複雑な会話を処理し、ツールを実行し、対話のコンテキストに基づいて一貫した応答を提供するように設計されています。
llm = Langchain :: LLM :: OpenAI . new ( api_key : ENV [ "OPENAI_API_KEY" ] )
assistant = Langchain :: Assistant . new (
llm : llm ,
instructions : "You're a helpful AI assistant" ,
tools : [ Langchain :: Tool :: NewsRetriever . new ( api_key : ENV [ "NEWS_API_KEY" ] ) ]
)
# Add a user message and run the assistant
assistant . add_message_and_run! ( content : "What's the latest news about AI?" )
# Supply an image to the assistant
assistant . add_message_and_run! (
content : "Show me a picture of a cat" ,
image_url : "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
)
# Access the conversation thread
messages = assistant . messages
# Run the assistant with automatic tool execution
assistant . run ( auto_tool_execution : true )
# If you want to stream the response, you can add a response handler
assistant = Langchain :: Assistant . new (
llm : llm ,
instructions : "You're a helpful AI assistant" ,
tools : [ Langchain :: Tool :: NewsRetriever . new ( api_key : ENV [ "NEWS_API_KEY" ] ) ]
) do | response_chunk |
# ...handle the response stream
# print(response_chunk.inspect)
end
assistant . add_message ( content : "Hello" )
assistant . run ( auto_tool_execution : true )
現在、ストリーミングはすべての LLM でサポートされているわけではないことに注意してください。
llm
: 使用する LLM インスタンス (必須)tools
: ツール インスタンスの配列 (オプション)instructions
: アシスタント用のシステム指示 (オプション)tool_choice
: ツールの選択方法を指定します。デフォルト:「自動」。特定のツール関数名を渡すことができます。これにより、アシスタントは常にこの機能を使用するようになります。parallel_tool_calls
: 複数の並列ツール呼び出しを行うかどうか。デフォルト: trueadd_message_callback
: メッセージが会話に追加されたときに呼び出されるコールバック関数 (proc、lambda) (オプション) assistant . add_message_callback = -> ( message ) { puts "New message: #{ message } " }
tool_execution_callback
: ツールが実行される直前に呼び出されるコールバック関数 (proc、lambda) (オプション) assistant . tool_execution_callback = -> ( tool_call_id , tool_name , method_name , tool_arguments ) { puts "Executing tool_call_id: #{ tool_call_id } , tool_name: #{ tool_name } , method_name: #{ method_name } , tool_arguments: #{ tool_arguments } " }
add_message
: ユーザーメッセージをメッセージ配列に追加しますrun!
: 会話を処理し、応答を生成します。add_message_and_run!
: メッセージの追加とアシスタントの実行を組み合わせますsubmit_tool_output
: 出力をツール呼び出しに手動で送信しますmessages
: 進行中のメッセージのリストを返します。Langchain::Tool::Calculator
: 数式の評価に役立ちます。 gem "eqn"
が必要です。Langchain::Tool::Database
: SQL データベースに接続します。 gem "sequel"
が必要です。Langchain::Tool::FileSystem
: ファイル システムと対話します (読み取りと書き込み)。Langchain::Tool::RubyCodeInterpreter
: 生成された Ruby コードを評価するのに役立ちます。 gem "safe_ruby"
が必要です (より良いソリューションが必要です)。Langchain::Tool::NewsRetriever
: ニュース記事を取得するための NewsApi.org のラッパー。Langchain::Tool::Tavily
: Tavily AI のラッパー。Langchain::Tool::Weather
: Open Weather API を呼び出して現在の天気を取得します。Langchain::Tool::Wikipedia
: Wikipedia API を呼び出します。Langchain::Assistant はextend Langchain::ToolDefinition
、必要なメソッドを実装するクラスを作成することで、カスタム ツールで簡単に拡張できます。
class MovieInfoTool
extend Langchain :: ToolDefinition
define_function :search_movie , description : "MovieInfoTool: Search for a movie by title" do
property :query , type : "string" , description : "The movie title to search for" , required : true
end
define_function :get_movie_details , description : "MovieInfoTool: Get detailed information about a specific movie" do
property :movie_id , type : "integer" , description : "The TMDb ID of the movie" , required : true
end
def initialize ( api_key : )
@api_key = api_key
end
def search_movie ( query : )
...
end
def get_movie_details ( movie_id : )
...
end
end
movie_tool = MovieInfoTool . new ( api_key : "..." )
assistant = Langchain :: Assistant . new (
llm : llm ,
instructions : "You're a helpful AI assistant that can provide movie information" ,
tools : [ movie_tool ]
)
assistant . add_message_and_run ( content : "Can you tell me about the movie 'Inception'?" )
# Check the response in the last message in the conversation
assistant . messages . last
アシスタントには、無効な入力、サポートされていない LLM タイプ、ツール実行の失敗に対するエラー処理が含まれています。ステート マシンを使用して会話フローを管理し、さまざまなシナリオを適切に処理します。
評価モジュールは、LLM および RAG (検索拡張生成) パイプラインによる出力製品のパフォーマンスを評価および追跡するために使用できるツールのコレクションです。
Ragas は、検索拡張生成 (RAG) パイプラインの評価に役立ちます。実装はこの論文とオリジナルの Python リポジトリに基づいています。 Ragas は次の 3 つの指標を追跡し、0.0 ~ 1.0 のスコアを割り当てます。
# We recommend using Langchain::LLM::OpenAI as your llm for Ragas
ragas = Langchain :: Evals :: Ragas :: Main . new ( llm : llm )
# The answer that the LLM generated
# The question (or the original prompt) that was asked
# The context that was retrieved (usually from a vectorsearch database)
ragas . score ( answer : "" , question : "" , context : "" )
# =>
# {
# ragas_score: 0.6601257446503674,
# answer_relevance_score: 0.9573145866787608,
# context_relevance_score: 0.6666666666666666,
# faithfulness_score: 0.5
# }
利用可能な追加の例: /examples
Langchain.rb は標準の Ruby Logger メカニズムを使用し、デフォルトは同じlevel
値 (現在はLogger::DEBUG
) です。
すべてのログ メッセージを表示するには:
Langchain . logger . level = Logger :: DEBUG
ロガーはデフォルトでSTDOUT
にログを記録します。ログの宛先を設定するには (ファイルへのログなど)、次の手順を実行します。
Langchain . logger = Logger . new ( "path/to/file" , ** Langchain :: LOGGER_OPTIONS )
pragmatic_segmenter
に必要なunicode
gem のインストールで問題が発生した場合は、次のコマンドを実行してみてください。
gem install unicode -- --with-cflags= " -Wno-incompatible-function-pointer-types "
git clone https://github.com/andreibondarev/langchainrb.git
cp .env.example .env
、次に.env
に環境変数を入力します。bundle exec rake
bin/console
使用して REPL セッションで gem をロードします。 LLM、ツール、エージェントなどの独自のインスタンスを自由に追加して、試してみてください。gem install lefthook && lefthook install -f
Langchain.rb Discord サーバーに参加してください。
バグレポートとプルリクエストは、GitHub (https://github.com/andreibondarev/langchainrb) で受け付けています。
この gem は、MIT ライセンスの条件に基づいてオープン ソースとして利用できます。