【LangChain】RetrievalQAは中でどんなことをしている?
[自分用のメモです。]
RetrievalQAを使うと良いチャットボットが簡単に作れます。
なぜこんなことができるのか、RetrievalQAのbase.pyをchatGPTに解説させました。
以下、chatGPTの回答。
このコードは、質問応答(QA)システムを実装したPythonのクラス定義です。このシステムは、質問に対して関連するドキュメントを検索し、それらのドキュメントから回答を抽出することができます。主要なクラスは以下の通りです。
BaseRetrievalQA: この抽象クラスは、質問応答の基本的な機能を定義しています。具体的には、質問を受け取り、関連するドキュメントを検索し、それらのドキュメントを組み合わせて回答を生成する機能があります。また、このクラスには非同期の処理も定義されています。
RetrievalQA: このクラスは BaseRetrievalQA を継承し、具体的なドキュメントの検索方法を提供します。この場合、BaseRetriever インターフェースを実装したオブジェクトを使って、質問に関連するドキュメントを検索します。
VectorDBQA: このクラスは BaseRetrievalQA を継承し、ベクトルデータベースを使用したドキュメントの検索方法を提供します。similarity や mmr のような検索方法をサポートしています。
各クラスは、質問を入力として受け取り、関連するドキュメントを検索し、それらのドキュメントを組み合わせて回答を生成する責任があります。これらのクラスは、異なる検索戦略やドキュメントの組み合わせ方法を実装することができるため、柔軟に質問応答システムを構築することができます。
chainsのbase.pyを継承しているので、こちらも解説させました。
以下、chatGPTの回答
このコードは、Pythonで書かれたオブジェクト指向のソフトウェアです。具体的には、Pydanticというライブラリを使ったChainという名前の抽象基底クラス(ABC)が定義されています。このクラスは、一連の処理(チェーン)を抽象化したもので、その具体的な実装はサブクラスによって定義されます。
以下、各部分の詳細について説明します。
_get_verbosity関数: langchain.verboseの値を返す関数です。これはどれだけ詳細な情報を出力するかを制御するための設定値で、Chainクラスのインスタンス生成時にデフォルト値として利用されます。
Chainクラス: 一連の処理を表す抽象クラスです。各インスタンスは以下のフィールドを持ちます。
memory: 入力と出力の情報を保存するためのメモリ。BaseMemoryのインスタンスかNone。
callbacks: コールバック関数のリスト。特定のイベント(例えばチェーンの開始や終了)時に呼び出されます。
callback_manager: コールバックマネージャ。コールバック関数を管理しますが、このフィールドは非推奨であり、callbacksフィールドを代わりに使うべきです。
verbose: どれだけ詳細な情報を出力するかを制御するブール値。デフォルト値は_get_verbosity関数によって決定されます。
raise_deprecationメソッド: callback_managerフィールドが使われている場合、非推奨警告を出力します。
set_verboseメソッド: verboseフィールドがNoneの場合、_get_verbosity関数を呼び出して値を設定します。
input_keys, output_keysプロパティ: 入力と出力のキーを表す抽象メソッド。具体的な実装はサブクラスによって定義されます。
_validate_inputs, _validate_outputsメソッド: 入力と出力のバリデーションを行います。必要なキーが欠けている場合、エラーを発生させます。
_call, _acallメソッド: チェーンの実際の処理を行う抽象メソッド。具体的な実装はサブクラスによって定義されます。_acallは非同期
_call, _acallメソッド: チェーンの実際の処理を行う抽象メソッドです。具体的な実装はサブクラスによって定義されます。_acallは非同期処理をサポートしていますが、サポートしないチェーンタイプの場合は実装されていません。
__call__メソッドとacallメソッド: これらはChainクラスのインスタンスが関数のように呼び出されたときに実行されます。これらは入力を準備し、コールバックマネージャを設定し、チェーンのロジックを実行(_callまたは_acallを呼び出す)し、出力を準備します。acallメソッドは非同期処理をサポートしています。
prep_outputs, prep_inputsメソッド: これらは出力と入力の準備を行います。出力はバリデーション後、メモリに保存されます。入力は適切な形式に変換され、必要ならメモリから値をロードし、バリデーションを行います。
applyメソッド: リスト内のすべての入力に対してチェーンを実行します。
runとarunメソッド: チェーンを実行し、唯一の出力キーに対応する値を返します。arunメソッドは非同期処理をサポートしています。
dictメソッド: チェーンの辞書表現を返します。
saveメソッド: チェーンをファイルに保存します。ファイル形式はJSONまたはYAMLである必要があります。
このChainクラスの目的は、一連の処理を抽象化し、それを再利用可能な部品として取り扱えるようにすることです。具体的な処理内容はサブクラスによって定義され、この基底クラスはその枠組みを提供します。
まだ何をしているか分からないので、関係のありそうな、retrieval.pyを読んでみます。
このコードは、質問応答(Question-Answering)のシステムにおいて、特定の情報源(sources)を用いて質問に対する答えを探索(retrieval)するための処理を担当するクラスを定義しています。このクラスはBaseQAWithSourcesChainを継承しており、基本的な質問応答の処理フローを持つ一方で、情報源からの文書の取得とその量の制御に特化した機能を追加しています。
具体的には、以下のような要素が含まれています:
retriever: BaseRetriever型のオブジェクトで、特定の情報源(例えば、テキストデータベースやウェブページなど)から質問に関連する文書を取得するためのインターフェースを提供します。このフィールドはexclude=Trueとされているため、このクラスの辞書表現からは除外されます。
reduce_k_below_max_tokens: ブール値のフィールドで、文書取得時のトークン数の上限を設けるかどうかを制御します。これがTrueに設定されている場合、取得する文書のトークン数がmax_tokens_limitを超えないように制限します。
max_tokens_limit: 取得する文書のトークン数の上限を指定する整数値です。reduce_k_below_max_tokensがTrueの場合にのみ適用されます。
_reduce_tokens_below_limitメソッド: 与えられた文書リストからトークン数の上限を超えないように文書を選択します。reduce_k_below_max_tokensがTrueで、かつcombine_documents_chainがStuffDocumentsChainのインスタンスである場合、トークン数がmax_tokens_limitを超えないように文書を削除します。
_get_docsメソッド: 質問を入力として受け取り、それに関連する文書を取得します。取得した文書は_reduce_tokens_below_limitメソッドを通じてトークン数が制限内に収まるように選択されます。
_aget_docsメソッド: 非同期版の_get_docsメソッドです。非同期処理をサポートするretrieverを用いて文書を取得し、その結果を_reduce_tokens_below_limitメソッドで制御します。
このクラスは、具体的な情報源からの文書取得と、その量を制御するための機能を提供します。これにより、情報源から取得した文書の量が多すぎて処理に負荷がかかる、または不要な情報が混在して結果の品質が下がるといった問題を避けることができます。
このクラスが具体的にどのように動作するか詳しく見ていきましょう:
_reduce_tokens_below_limitメソッドでは、まず入力として与えられた文書のリストから文書の数を取得します。次に、reduce_k_below_max_tokensがTrueであり、かつcombine_documents_chainがStuffDocumentsChainのインスタンスであるかどうかをチェックします。これらの条件が満たされている場合、各文書のトークン数を取得し、トークンの総数がmax_tokens_limitを超えていないかどうかを確認します。トークンの総数が上限を超えている場合、トークンの総数が上限以下になるまで、文書のリストの最後から文書を削除します。
_get_docsメソッドでは、まず入力の質問を取得します。この質問をretrieverに渡して関連する文書を取得し、その結果を_reduce_tokens_below_limitメソッドに渡してトークン数の制限を適用します。
_aget_docsメソッドは_get_docsメソッドの非同期版で、質問を非同期に処理し、関連する文書を非同期に取得します。その後、取得した文書に_reduce_tokens_below_limitメソッドを適用してトークン数の制限を行います。
このように、このクラスは質問に対する関連文書の取得とその量の制御を行うことで、効率的かつ効果的な質問応答処理を支えています。
retrieverに渡して関連する文書を取得、というところがよく分からないので、関連していそうなcombine_documentsのbase.pyを読んでみます。
このコードでは、まず関数format_documentとその後に3つのクラスBaseCombineDocumentsChain、AnalyzeDocumentChainが定義されています。それぞれの役割について詳しく見ていきましょう。
format_document関数:
この関数は、指定されたプロンプトテンプレートに基づいて、Documentオブジェクトを文字列にフォーマットするためのものです。入力されたDocumentから基本情報(ページの内容とメタデータ)を取得し、プロンプトテンプレートの入力変数と比較します。もし必要なメタデータが不足していれば、エラーを返します。全ての必要なメタデータが揃っていれば、それらを用いてプロンプトをフォーマットし、文字列として返します。
BaseCombineDocumentsChainクラス:
このクラスは、複数の文書を組み合わせるチェインの基本インターフェースを提供します。入力として文書のリストを受け取り、これを1つの文字列に組み合わせるメソッド(combine_docsとacombine_docs)を定義しています。また、入力キーと出力キーを定義し、これらをプロパティとして取得するメソッドも提供しています。
AnalyzeDocumentChainクラス:
このクラスは、文書を分割し、それぞれの部分を解析するチェインを表します。入力として1つの文書を受け取り、TextSplitterを用いて文書を分割します。その後、分割した文書をBaseCombineDocumentsChainに渡し、それらを組み合わせて1つの文字列にします。
このように、これらのコードは文書の整形、組み合わせ、解析といった一連の処理を実現しています。
他にも関係していそうなstuff.pyを読んでいきます。
このコードは、複数のドキュメントを組み合わせて一つのプロンプトを作成し、そのプロンプトを元にLLM(大言語モデル)で予測を行う、StuffDocumentsChainというクラスを定義しています。
まず、_get_default_document_promptという関数はデフォルトのプロンプトテンプレートを返すものです。このテンプレートはpage_contentという変数を入力として受け取り、そのまま出力するシンプルなものとなっています。
次に、StuffDocumentsChainクラスですが、このクラスはBaseCombineDocumentsChainという基底クラスを継承しており、複数のドキュメントを組み合わせて一つの文字列を作成するためのメソッドが定義されています。
このクラスでは、ドキュメントのフォーマット、結合、そしてLLMへの予測の3つの主要なステップを行っています。
ドキュメントのフォーマット:
_get_inputsメソッドでは、各ドキュメントをdocument_promptに従ってフォーマットし、その結果をdoc_stringsとして保持します。
ドキュメントの結合:
フォーマットした各ドキュメントをdocument_separatorで結合し、それをLLMのプロンプトの一部としています。
LLMへの予測:
フォーマットと結合を経たプロンプトを元に、llm_chainを通じてLLMでの予測を行っています。この結果が最終的な出力となります。
また、このクラスにはprompt_lengthというメソッドもあり、これはプロンプトの長さ(トークン数)を取得するためのものです。これは、LLMが処理できるトークン数に制限があるため、プロンプトの長さを事前に計算して適切に調整するために使用されます。
最後に、このクラスにはcombine_docsとacombine_docsという2つのメソッドがあり、これらはそれぞれ同期的、非同期的にドキュメントの組み合わせとLLMでの予測を行うためのものです。
以上がこのコードの主要な機能となります。このようなクラスは、大量のドキュメントを一つのプロンプトに組み合わせてLLMでの予測を行う、というタスクを効率的に処理するために使用されます。
これはLLMの選択に使うからあんまり関係なかったです。
map_reduce.pyを読んでいきます。こっちの方が関係しているかな。
このコードは、複数のドキュメントを組み合わせるためのマップ・リデュース方式を実装したものです。特に、異なるドキュメントからの情報を一つのコンテキストに統合するために使われます。
まずはじめに、CombineDocsProtocolというプロトコルを定義しています。これは、複数のドキュメントを組み合わせるメソッドのインターフェースを提供します。引数としてドキュメントのリストとその他のキーワード引数を取り、結合後のドキュメントを返します。
次に_split_list_of_docsという関数が定義されています。これは、ドキュメントのリスト、長さを計算する関数、トークンの最大数を引数に取り、リストのリストを返します。この関数は、ドキュメントをその長さに基づいて適切に分割します。この分割は、結果となるドキュメントが指定された最大のトークン数を超えないように行われます。
_collapse_docs関数は、ドキュメントを結合する関数として定義されています。これはドキュメントのリストとドキュメントを結合するための関数を引数に取り、結果として結合されたドキュメントを返します。この関数は、各ドキュメントのメタデータも考慮に入れて結合を行います。
最後に、MapReduceDocumentsChainというクラスが定義されています。このクラスは、ドキュメントをマップ・リデュース方式で組み合わせるためのものです。このクラスは、各ドキュメントに対して独立に適用されるチェーン(llm_chain)、ドキュメントの結果を組み合わせるためのチェーン(combine_document_chain)、中間結果を処理するためのオプショナルなチェーン(collapse_document_chain)などを属性として持ちます。
このクラスのcombine_docsメソッドは、マップ・リデュース方式でドキュメントを組み合わせる処理を行います。このメソッドは、まず各ドキュメントにllm_chainを適用し、その結果を組み合わせるためにcombine_document_chainを使用します。結果のドキュメントが指定された最大トークン数を超える場合、ドキュメントは_split_list_of_docs関数で分割され、その後_collapse_docs関数で結合されます。このプロセスは、全てのドキュメントがトークンの最大数以下になるまで再帰的に続けられます。また、return_intermediate_stepsプロパティがTrueに設定されている場合、このメソッドはマップステップの結果も返します。
非同期メソッドacombine_docsも提供されており、こちらは同様のマップ・リデュース処理を非同期で行います。
また、MapReduceDocumentsChainクラスにはいくつかのバリデータとプロパティが定義されています。get_return_intermediate_stepsとget_default_document_variable_nameはrootバリデータで、オブジェクトの作成前に特定の値の整合性を確認します。また、_collapse_chainプロパティは、collapse_document_chainがNoneの場合にcombine_document_chainを返す便利なショートカットです。
このクラスは、多数のドキュメントを効率的に組み合わせるためのツールとして設計されています。それぞれのドキュメントは、マップフェーズで独立に処理され、次にリデュースフェーズで結果が結合されます。これにより、大量のドキュメントを一つのコンテキストに統合することが可能になります。
schema.pyを読んでみます。
このソースコードは、チャットボットや対話型AIの開発に関連するクラスや関数を含んでいます。以下に、それぞれの部分の詳細について説明します。
get_buffer_string関数: これは、チャットボットが取り扱うメッセージ(人間からのメッセージ、AIからのメッセージ、システムメッセージなど)のリストを受け取り、それぞれのメッセージのロール(人間、AI、システムなど)と内容を結合して文字列化します。最終的に、すべてのメッセージを改行で連結して返します。
AgentActionとAgentFinish: これらは名前付きタプルで、エージェントの行動とその結果を表現します。ツール名、ツールの入力、ログなどが含まれています。
Generationクラス: これはAIの生成結果を表すクラスで、生成されたテキストとその他の情報(生成情報、ログ確率など)を格納します。
BaseMessage、HumanMessage、AIMessage、SystemMessage、ChatMessageクラス: これらはチャットボットが取り扱うメッセージの型を定義しています。BaseMessageは基底クラスで、他のクラスはそれを継承しています。各クラスはメッセージの内容とその他の属性(例えば、メッセージが例示用であるかどうかを示すexample属性)を持っています。
_message_to_dict、messages_to_dict、_message_from_dict、messages_from_dict関数: これらはメッセージオブジェクトと辞書の間の変換を行います。これにより、メッセージの保存や読み込み、ネットワーク経由での送受信が容易になります。
ChatGeneration、ChatResult、LLMResultクラス: これらはチャットや言語モデルの生成結果を表現するためのクラスです。
PromptValueクラス: これは抽象基底クラスで、プロンプト(AIに与える指示)の値を表現します。具体的なプロンプトクラスは、このクラスを継承してto_stringメソッドとto_messagesメソッドを実装する必要があります。
BaseMemoryクラス: これはメモリインターフェイスを表す抽象基底クラスです。具体的なメモリクラスは、このクラスを継承して、メモリ変数のロード、保存、クリア等の操作を実装する必要があります。
BaseChatMessageHistoryクラス: これはチャットメッセージの履歴を管理するための抽象基底クラスです。具体的な履歴クラスは、このクラスを継承してユーザーからのメッセージの追加、AIからのメッセージの追加、メッセージのクリアなどの操作を実装する必要があります。
Documentクラス: これはドキュメントを表現するクラスです。ページの内容とメタデータを持ちます。
BaseRetrieverクラス: これは情報検索器の基底クラスで、クエリに関連するドキュメントを取得するメソッドを定義しています。具体的な情報検索器クラスは、このクラスを継承してメソッドを実装する必要があります。
BaseOutputParserクラス: これは言語モデルの出力を解析するための抽象基底クラスです。具体的な出力パーサクラスは、このクラスを継承してparseメソッドを実装する必要があります。
BaseDocumentTransformerクラス: これはドキュメントの変換を行う抽象基底クラスです。具体的なドキュメント変換クラスは、このクラスを継承してドキュメントの変換メソッドを実装する必要があります。
このように、このソースコードは対話型AIやチャットボットの開発に関連する多数のクラスと関数を提供しています。これらは基本的に、メッセージの管理、エージェントの行動、生成結果の表現、メモリの管理、ドキュメントの取得と変換、出力の解析など、対話型AIの制作に必要な機能をカバーしています。
最後にvectorestoresのbase.pyを読んでいきます。
このコードは、テキストやドキュメントをベクトルストアに追加し、特定の検索タイプを使用して類似度や最大限度の関連性を基にクエリに最も類似したドキュメントを返すための抽象基底クラス (ABC)、VectorStoreを定義しています。
主なメソッドは以下の通りです:
add_textsとaadd_texts: これらのメソッドは、テキストを取り込み、それをベクトルストアに追加します。非同期版のメソッドも提供されています。
add_documentsとaadd_documents: これらのメソッドは、ドキュメントを取り込み、それをベクトルストアに追加します。非同期版のメソッドも提供されています。
searchとasearch: これらのメソッドは、指定した検索タイプ(類似性または最大限度の関連性)を使用してクエリに最も類似したドキュメントを返します。非同期版のメソッドも提供されています。
similarity_search, asimilarity_search, similarity_search_with_relevance_scores, similarity_search_by_vector, asimilarity_search_by_vector: これらのメソッドは、クエリまたは埋め込みベクトルに最も類似したドキュメントを返します。関連性スコアとともにドキュメントを返すメソッドや、非同期版のメソッドも提供されています。
max_marginal_relevance_search, amax_marginal_relevance_search, max_marginal_relevance_search_by_vector, amax_marginal_relevance_search_by_vector: これらのメソッドは、最大限度の関連性を使用してドキュメントを選択し、返します。非同期版のメソッドも提供されています。
さらに、このクラスには、テキストと埋め込みからベクトルストアを初期化するfrom_textsとafrom_textsという抽象メソッドが含まれています。
VectorStoreRetrieverクラスは、VectorStoreをラップするためのクラスで、BaseRetrieverとBaseModelを継承しています。このクラスでは、get_relevant_documents、aget_relevant_documents、add_documents、aadd_documentsといったメソッドが提供されています。これらのメソッドは、VectorStoreのメソッドを呼び出すことで機能します。
chain_extra.pyを読みます。
このコードは、ドキュメントの圧縮(要約)を行うためのソフトウェアで、LLM(Language Learning Model)を用いています。具体的な機能としては、指定されたクエリ(質問)とドキュメントの内容を入力とし、それを基にドキュメントの圧縮版を生成します。以下に各部分の詳細を説明します。
default_get_input関数: この関数はクエリとドキュメントを受け取り、その内容をLLMに供給するための辞書型データを作成します。この辞書型データには、"question"キーでクエリの内容と、"context"キーでドキュメントの内容が格納されます。
NoOutputParserクラス: このクラスは出力文字列を解析するためのもので、特に"NO_OUTPUT"という文字列が出力された場合に空文字列に変換します。これはLLMからの出力が何らかの理由で存在しない場合の処理を意味します。
_get_default_chain_prompt関数: この関数はデフォルトのプロンプトテンプレートを生成します。テンプレートには"NO_OUTPUT"という文字列を含みます。このテンプレートは、LLMに質問とコンテキストを提示する際のフォーマットを提供します。
LLMChainExtractorクラス: このクラスはドキュメントの圧縮を実行する主要なクラスです。LLMチェーン(LLMChain)を使用して、ドキュメントの内容を圧縮します。
compress_documentsメソッド: このメソッドは、複数のドキュメントとクエリを受け取り、それらのドキュメントを圧縮します。各ドキュメントについて、クエリとドキュメントから入力を生成し、LLMチェーンを使って予測と解析を行います。出力が空でない場合、新たな圧縮されたドキュメントを作成し、そのリストを返します。
acompress_documentsメソッド: このメソッドはcompress_documentsメソッドの非同期版です。非同期プログラミングを使用して、同時に複数のドキュメントの圧縮を行います。
from_llmクラスメソッド: このメソッドはLLMからLLMChainExtractorインスタンスを初期化するために使います。LLM、プロンプトテンプレート、入力生成関数、LLMチェーンのキーワード引数を受け取り、新たなLLMChainExtractorインスタンスを生成します。プロンプトテンプレートと入力生成関数は指定されていない場合、デフォルトのものが用いられます。
全体として、このコードは指定されたクエリとドキュメントの内容を用いて、文書を圧縮(要約)する機能を提供しています。LLMを用いてドキュメントの内容を解析し、その結果を基に圧縮版のドキュメントを作成します。また、非同期処理を用いることで複数のドキュメントの圧縮を効率的に行うことができます。
refine.pyを読みます。
このコードは、複数のドキュメントを組み合わせて一つのテキストに変換するためのRefineDocumentsChainクラスを定義しています。
まず、RefineDocumentsChainクラスはBaseCombineDocumentsChainクラスを継承しています。このクラスは、初期のLLMチェイン(initial_llm_chain)と、その結果を精錬するためのLLMチェイン(refine_llm_chain)を持っています。
combine_docsメソッドとacombine_docsメソッドは、ドキュメントのリストを受け取り、それらを組み合わせるために使用されます。まず、_construct_initial_inputsメソッドを使用して初期のLLMチェインのための入力を構築します。次に、その結果を用いて、_construct_refine_inputsメソッドを使って精錬チェインのための入力を構築します。これをドキュメントがなくなるまで繰り返します。
_construct_initial_inputsメソッドは、最初のドキュメントからページの内容とそのメタデータを取得し、それらを初期チェインの入力として整形します。また、_construct_refine_inputsメソッドは、現在のドキュメントと前のステップの結果を用いて、精錬チェインのための入力を構築します。
最後に、_construct_resultメソッドは、中間ステップを含むかどうかによって、結果を構築します。このメソッドは、最終的な結果とともに、中間ステップの結果を返すこともできます。
root_validatorデコレータを使用したメソッドは、設定値の検証とデフォルト値の設定を行っています。get_return_intermediate_stepsメソッドは、return_refine_stepsが設定されている場合、それをreturn_intermediate_stepsに変換します。get_default_document_variable_nameメソッドは、document_variable_nameが設定されていない場合、デフォルト値を設定します。
このクラスは、与えられたドキュメントを組み合わせて、より洗練されたテキストを生成するためのツールとして使用されます。
Indexesのvectore.pyを読んでみます。
このコードは、文書データを扱うためのベクトルストアを作成し、そのベクトルストアを利用して質問に対する回答を検索するための機能を提供します。具体的には以下のようなクラスと関数が定義されています。
_get_default_text_splitter関数:
これは、TextSplitterのデフォルトのインスタンスを生成する関数です。ここではRecursiveCharacterTextSplitterが使われ、文字列を1000文字ごとに分割するように設定されています。
VectorStoreIndexWrapperクラス:
このクラスはベクトルストアへのアクセスを簡素化するためのラッパーです。ベクトルストアを使って質問に対する回答を検索するqueryメソッドと、回答と一緒にその情報源も返すquery_with_sourcesメソッドを提供します。
VectorStoreIndexCreatorクラス:
このクラスはベクトルストアのインデックスを作成するロジックを提供します。文書データローダーからベクトルストアのインデックスを作成するfrom_loadersメソッドと、文書データから直接インデックスを作成するfrom_documentsメソッドがあります。
具体的な動作は次のようになります。
VectorStoreIndexCreatorのfrom_loadersまたはfrom_documentsメソッドを使ってベクトルストアのインデックスを作成します。これには、文書データが含まれたローダーか、直接文書データが必要です。また、テキストを分割するためのTextSplitterや、ベクトルストアクラス、埋め込み方法なども設定できます。
作成したベクトルストアのインデックスはVectorStoreIndexWrapperにラップされ、そのまま使用することも、必要に応じて保存して後で使用することも可能です。
VectorStoreIndexWrapperのqueryメソッドやquery_with_sourcesメソッドを使って、質問に対する回答を検索します。これには、質問文と、オプションで言語モデルを指定することができます。
以上が、このコードの概要と動作です。
技術でお困りのことがある方はオンライン相談が可能です。
こちらから会社概要資料をDLできます!
お問い合わせ内容に「オンライン相談希望」とご記載ください。
株式会社piponでは定期的に技術勉強会を開催しています。
ChatGPT・AI・データサイエンスについてご興味がある方は是非、ご参加ください。
株式会社piponではChatGPT・AI・データサイエンスについて業界ごとの事例を紹介しています。ご興味ある方はこちらのオウンドメディアをご覧ください。
Discussion