ラングチェーン付きのエッジデバイスでのセルフホスティングラグアプリケーション
導入
シリーズの第2部では、Raspberry PiにRAGアプリケーションの構築に関するもので、コアパイプラインを作成およびテストした最初の部分に敷設した基盤を拡張します。最初の部分では、コアパイプラインを作成し、テストして、すべてが期待どおりに機能するようにしました。ここで、ラグパイプラインを提供するためにFastAPIアプリケーションを構築し、ユーザーにシンプルでインタラクティブなアクセス方法を提供するReflexアプリを作成することにより、さらに一歩進めます。このパートでは、Fastapiバックエンドのセットアップ、反射でフロントエンドを設計し、Raspberry Piですべてを稼働させることを導きます。最後に、実際の使用の準備が整った完全な作業アプリケーションがあります。
学習目標
- FastAPIバックエンドをセットアップして、既存のRAGパイプラインとプロセスクエリと効率的に統合します。
- FastAPIバックエンドおよびRAGパイプラインと対話するためにReflexを使用して、ユーザーフレンドリーなインターフェイスを設計します。
- クエリのためのAPIエンドポイントを作成およびテストし、摂取を文書化し、FastAPIでスムーズな動作を確保します。
- Raspberry Piで完全なアプリケーションを展開およびテストし、バックエンドとフロントエンドの両方のコンポーネントがシームレスに機能するようにします。
- まとまりのあるRAGアプリケーションエクスペリエンスのために、FastapiとReflexの統合を理解してください。
- FastAPIおよびReflexコンポーネントを実装およびトラブルシューティングして、Raspberry PIに完全に動作するRAGアプリケーションを提供します。
前のエディションを逃した場合は、必ずここで確認してください。LangchainとOllamaを使用したエッジデバイスでの自己ホーストラグアプリケーション - パートI。
目次
- Python環境の作成
- Fastapiでバックエンドを開発します
- 反射でフロントエンドを設計します
- テストと展開
- よくある質問
この記事は、データサイエンスブログソンの一部として公開されました。
Python環境の作成
アプリケーションの作成を開始する前に、環境をセットアップする必要があります。環境を作成し、以下の依存関係をインストールします。
ディープレイク boto3 == 1.34.144 ボトコア== 1.34.144 Fastapi == 0.110.3 Gunicorn == 22.0.0 httpx == 0.27.0 Huggingface-hub == 0.23.4 langchain == 0.2.6 langchain-community == 0.2.6 langchain-core == 0.2.11 Langchain-Experimpal == 0.0.62 langchain-text-splitters == 0.2.2 langsmith == 0.1.83 Marshmallow == 3.21.3 numpy == 1.26.4 pandas == 2.2.2 Pydantic == 2.8.2 pydantic_core == 2.20.1 pymupdf == 1.24.7 pymupdfb == 1.24.6 python-dotenv == 1.0.1 pytz == 2024.1 pyyaml == 6.0.1 反射== 0.5.6 リクエスト== 2.32.3 反射== 0.5.6 Reflex-Hosting-Cli == 0.1.13
必要なパッケージがインストールされたら、デバイスに必要なモデルが存在する必要があります。オラマを使用してこれを行います。この記事のパート1の手順に従って、言語モデルと埋め込みモデルの両方をダウンロードします。最後に、バックエンドおよびフロントエンドアプリケーションの2つのディレクトリを作成します。
モデルがOllamaを使用して引っ張られたら、最終アプリケーションを構築する準備が整いました。
Fastapiでバックエンドを開発します
この記事のパート1では、摂取モジュールとQNAモジュールの両方を備えたRAGパイプラインを構築しました。いくつかのドキュメントを使用して両方のパイプラインをテストしましたが、それらは完全に機能していました。次に、消耗品APIを作成するには、PipelineをFastAPIでラップする必要があります。これにより、Streamlit、ChainLit、Gradio、Reflex、React、Angularなどのフロントエンドアプリケーションと統合することができます。まず、アプリケーション用の構造を構築することから始めましょう。構造に従うことは完全にオプションですが、別の構造に従ってアプリを作成する場合は、依存関係のインポートを確認してください。
以下は、私たちが従うツリー構造です。
バックエンド ├├。pot.py ├├)。要件。txt └└)rc ├├) config.py doc_loader │├│。-base_loader.py │├ク。__init__.py pdf_loader.py ├)ingestion.py ├├。。__init__.py └└リン大した
config.pyから始めましょう。このファイルには、Ollama URL、LLM名、Embeddingsモデル名など、アプリケーションのすべての構成可能なオプションが含まれます。以下は例です:
Language_model_name = "phi3" embeddings_model_name = "nomic-embed-text" ollama_url = "http:// localhost:11434"
base_loader.pyファイルには、子供のドキュメントローダーが継承する親文書ローダークラスが含まれています。このアプリケーションでは、PDFファイルのみを使用しているため、子供のpdfloaderクラスは
ベースローダークラスを継承する作成された作成。
以下は、base_loader.pyとpdf_loader.pyの内容です:
#base_loader.py ABCインポートABCから、AbstractMethod クラスベースローダー(ABC): def __init __(self、file_path:str) - >なし: self.file_path = file_path @AbstractMethod async def load_document(self): 合格 #pdf_loader.py OSをインポートします .base_loaderからBaseloaderをインポートします langchain.schemaインポートドキュメントから langchain.document_loaders.pdfからpymupdfloaderをインポートします langchain.text_splitterからImport charactesTextSplitterから クラスPDFLoader(Baseloader): def __init __(self、file_path:str) - >なし: super().__ init __(file_path) async def load_document(self): self.file_name = os.path.basename(self.file_path) loader = pymupdfloader(file_path = self.file_path) text_splitter = charateTextSplitter( セパレーター= "\ n"、 chunk_size = 1000、 chunk_overlap = 200、 )) Pages = await loader.aload() total_pages = len(ページ) チャンク= [] idxの場合、ページin Enumater(ページ): chunks.append( 書類( page_content = page.page_content、 メタデータ= dict( { 「file_name」:self.file_name、 「page_no」:str(idx 1)、 「Total_Pages」:str(total_pages)、 } )、、 )) )) final_chunks = text_splitter.split_documents(チャンク) final_chunksを返します
記事のパート1でPDF_Loaderの作業について説明しました。
次に、摂取クラスを構築しましょう。これは、この記事のパート1で作成したものと同じです。
摂取クラスのコード
OSをインポートします CFGとして構成をインポートします Pinecone Import Pineconeから langchain.vectorstores.deeplakeインポートディープレイクから langchain.embeddings.ollamaからOllamaembeddingsからインポート .doc_loaderからpdfloaderをインポートします クラスの摂取: "" "ドキュメント摂取パイプライン。" "" def __init __(self): 試す: self.embeddings = ollamaembedings( モデル= cfg.embeddings_model_name、 base_url = cfg.ollama_url、 show_progress = true、 )) self.vector_store = deeplake( dataset_path = "data/text_vectorstore"、 埋め込み= self.embeddings、 num_workers = 4、 verbose = false、 )) eとしての例外を除く: RuntimeErrorを上げる(f」摂取システムの初期化に失敗しました。エラー:{e} ") async def create_and_add_embeddings( 自己、 ファイル:str、 ): 試す: Loader = pdfloader( file_path = file、 )) chunks = await loader.load_document() サイズ= self.vector_store.aadd_documents(documents = chunks)を待っています レン(サイズ)を返す e:e:e: 例外を上げる(f "エラー:{e}")
摂取クラスをセットアップできるようになったので、QNAクラスの作成に進みます。これも、この記事のパート1で作成したものと同じです。
QNAクラスのコード
OSをインポートします CFGとして構成をインポートします Pinecone Import Pineconeから langchain.vectorstores.deeplakeインポートディープレイクから langchain.embeddings.ollamaからOllamaembeddingsからインポート langchain_community.llms.ollamaからオラマをインポートします .doc_loaderからpdfloaderをインポートします クラスQNA: "" "ドキュメント摂取パイプライン。" "" def __init __(self): 試す: self.embeddings = ollamaembedings( モデル= cfg.embeddings_model_name、 base_url = cfg.ollama_url、 show_progress = true、 )) self.model = ollama( モデル= cfg.language_model_name、 base_url = cfg.ollama_url、 verbose = true、 温度= 0.2、 )) self.vector_store = deeplake( dataset_path = "data/text_vectorstore"、 埋め込み= self.embeddings、 num_workers = 4、 verbose = false、 )) self.retriever = self.vector_store.as_retriever( search_type = "類似性"、 search_kwargs = { 「K」:10、 }、 )) eとしての例外を除く: RuntimeErrorを上げる(f」摂取システムの初期化に失敗しました。エラー:{e} ") def create_rag_chain(self): 試す: system_prompt = "" " \ n \ ncontext:{context}" "" " PROMP = ChatPromptTemplate.from_messages( [ ( "System"、System_prompt)、 ( "Human"、 "{input}")、 ] )) 質問 rag_chain = create_retrieval_chain(self.retriever、question_answer_chain) Rag_Chainを返します eとしての例外を除く: RuntimeErrorを上げる(f」検索チェーンの作成に失敗しました。エラー:{e} ")
これにより、RAGアプリのコード機能の作成が完了しました。それでは、Fastapiでアプリをラップしましょう。
FastAPIアプリケーションのコード
sysをインポートします OSをインポートします uvicornをインポートします srcからqna、摂取からインポート Fastapi Import Fastapi、request、file、uploadfileから Fastapi.responsesからImport StreamingResponseから app = fastapi() Ingestion = Ingestion() chatbot = qna() rag_chain = chatbot.create_rag_chain() @app.get( "/") def hello(): return {"message": "server 8089で実行されているapi} @app.post( "/query") async def ask_query(リクエスト:リクエスト): data = await request.json() 質問= data.get( "質問") async def event_generator(): rag_chain.pickのチャンク( "Answer")。ストリーム({"入力":質問}): 塊を獲得します return streamingResponse(event_generator()、media_type = "text/plain") @app.post( "/gest") async def gest_document(file:uploadfile = file(...)): 試す: os.makedirs( "files"、sext_ok = true) file_location = f "files/{file.filename}" file_objectとしてopen(file_location、 "wb"): file_object.write(file.file.read()) size = await gestion.create_and_add_embeddings(file = file_location) return {"message":f "file gested!document count:{size}"} eとしての例外を除く: return {"message":f "エラーが発生しました:{e}"} __name__ == "__main__"の場合: 試す: uvicorn.run(app、host = "0.0.0.0"、port = 8089) eとしてkeyboardinterruptを除く: print( "アプリが停止しました!")
各エンドポイントによってアプリを内訳しましょう。
- 最初に、Fastapiアプリ、摂取、QNAオブジェクトを初期化します。次に、QNAクラスのCreate_Rag_Chainメソッドを使用してRAGチェーンを作成します。
- 最初のエンドポイントは、簡単なGETメソッドです。これは、アプリが健康かどうかを知るのに役立ちます。 「Hello World」エンドポイントのように考えてください。
- 2番目はクエリエンドポイントです。これはPOSTメソッドであり、チェーンの実行に使用されます。リクエストパラメーターを取り入れ、そこからユーザーのクエリを抽出します。次に、チェーンの周りに非同期ラッパーとして機能する非同期メソッドを作成します。ストリーム関数呼び出し。これを行うには、FastapiがLLMのストリーム関数呼び出しを処理し、チャットインターフェイスでChatGPTのようなエクスペリエンスを取得する必要があります。次に、非同期メソッドをStreamingResponseクラスで包み、返します。
- 3番目のエンドポイントは、摂取エンドポイントです。また、ファイル全体を入力としてバイトとして取得する投稿メソッドでもあります。このファイルをローカルディレクトリに保存し、create_and_add_embeddingsの摂取クラスを使用して摂取します。
最後に、ホストとポートを使用して、Uvicornパッケージを使用してアプリを実行します。アプリをテストするには、次のコマンドを使用してアプリケーションを実行するだけです。
python app.py
アプリケーションをテストするために、郵便配達員、不眠症、ブルーノなどのAPIテストIDEを使用します。 Thunderクライアント拡張機能を使用して同じことをすることもできます。
摂取エンドポイントのテスト:
クエリエンドポイントのテスト:
反射でフロントエンドを設計します
RAGアプリケーションのバックエンド用のFastAPIアプリを正常に作成しました。フロントエンドを構築する時が来ました。これには、フロントエンドライブラリを選択できますが、この特定の記事では、反射を使用してフロントエンドを構築します。 Reflexは、純粋にPythonを使用してWebアプリケーションを構築するために作成されたPythonのみのフロントエンドライブラリです。計算機、画像生成、チャットボットなどの一般的なアプリケーションのテンプレートを証明します。ユーザーインターフェイスのスタートとして、ChatBotアプリケーションテンプレートを使用します。最終的なアプリには次の構造がありますので、参照のためにここにあります。
フロントエンドディレクトリ
これのためのフロントエンドディレクトリがあります:
フロントエンド ├アクセス。資産 pavicon.ico docs │└│ク ├├アクスバイ。チャット │├├。。components ││├├├。-chat.py ││├│。。 ││├│。ですか?__init__.py ││├││。-loading_icon.py │││││。py.py ││││。-navbar.py │├ク。__init__.py │├├。-chat.py │└│。-state.py ├├)。要件。txt ├├アクティブ └)ruaded_files
最終アプリの手順
手順に従って、最終的なアプリの接地を準備します。
ステップ1:フロントエンドディレクトリのチャットテンプレートリポジトリをクローンします
git clone https://github.com/reflex-dev/reflex-chat.git。
ステップ2:次のコマンドを実行して、ディレクトリを反射アプリとして初期化します
反射Init
これにより、Reflexアプリがセットアップされ、実行して開発する準備が整います。
ステップ3:アプリをテストし、フロントエンドディレクトリ内から次のコマンドを使用します
反射実行
コンポーネントの変更を始めましょう。まず、chat.pyファイルを変更しましょう。
以下は同じコードです。
Rxとして反射をインポートします Reflex_demo.comPonentsからImport Loading_iconから Reflex_demo.State Import QA、Stateから message_style = dict( display = "inline-block"、 パディング= "0 10px"、 border_radius = "8px"、 max_width = ["30em"、 "30em"、 "50em"、 "50em"、 "50em"、 "50em"]、 )) def message(qa:qa) - > rx.component: "" "単一の質問/回答メッセージ。 args: QA:質問/回答ペア。 返品: 質問/回答ペアを表示するコンポーネント。 "" " Rx.boxを返します( rx.box( rx.markdown( Qa.Question、 background_color = rx.color( "mauve"、4)、 color = rx.color( "mauve"、12)、 ** message_style、 )、、 text_align = "right"、 margin_top = "1em"、 )、、 rx.box( rx.markdown( Qa.Answer、 background_color = rx.color( "accent"、4)、 color = rx.color( "accent"、12)、 ** message_style、 )、、 text_align = "left"、 padding_top = "1em"、 )、、 width = "100%"、 )) def chat() - > rx.component: "" "すべてのメッセージを1回の会話でリストします。" "" RX.VSTACKを返します( rx.box(rx.foreach(state.chats [state.current_chat]、message)、width = "100%")、 py = "8"、 flex = "1"、 width = "100%"、 max_width = "50em"、 padding_x = "4px"、 align_self = "center"、 オーバーフロー= "hidden"、 padding_bottom = "5em"、 )) def Action_bar() - > rx.component: "" "新しいメッセージを送信するアクションバー。" "" RX.Centerを返します( rx.vstack( rx.chakra.form( rx.chakra.form_control( rx.hstack( rx.input( rx.input.slot( rx.tooltip( rx.icon( "info"、size = 18)、 content = "質問を入力して応答を取得します。"、 )) )、、 PlaceHolder = "Type Something ..."、 、 width = ["15em"、 "20em"、 "45em"、 "50em"、 "50em"、 "50em"]、 )、、 rx.button( rx.cond( state.processing、 loading_icon(height = "1EM")、 rx.text( "send"、font_family = "ubuntu")、 )、、 type = "submit"、 )、、 align_items = "center"、 )、、 is_disabled = state.processing、 )、、 on_submit = state.process_question、 reset_on_submit = true、 )、、 rx.text( 「ReflexGPTは、事実上正しくないまたは誤解を招く応答を返す可能性があります。裁量を使用してください。」 text_align = "center"、 font_size = "。75em"、 color = rx.color( "mauve"、10)、 font_family = "ubuntu"、 )、、 rx.logo(mign_top = "-1Em"、mirdain_bottom = "-1Em")、 align_items = "center"、 )、、 position = "Sticky"、 bottom = "0"、 左= "0"、 padding_y = "16px"、 backdrop_filter = "auto"、 backdrop_blur = "lg"、 border_top = f "1px solid {rx.color( 'mauve'、3)}"、 background_color = rx.color( "mauve"、2)、 align_items = "ストレッチ"、 width = "100%"、 ))
変更は、テンプレートにネイティブに存在するものから最小限です。
次に、chat.pyアプリを編集します。これがメインのチャットコンポーネントです。
メインチャットコンポーネントのコード
以下はそれのコードです:
Rxとして反射をインポートします Reflex_demo.components Import Chat、navbar、upload_formから Reflex_demo.Stateインポート状態から @rx.page(route = "/chat"、title = "rag chatbot") def chat_interface() - > rx.component: RX.Chakra.VStackを返します( navbar()、 chat.chat()、 chat.action_bar()、 background_color = rx.color( "mauve"、1)、 color = rx.color( "mauve"、12)、 min_height = "100VH"、 align_items = "ストレッチ"、 間隔= "0"、 )) @rx.page(route = "/"、title = "rag chatbot") def index() - > rx.component: RX.Chakra.VStackを返します( navbar()、 upload_form()、 background_color = rx.color( "mauve"、1)、 color = rx.color( "mauve"、12)、 min_height = "100VH"、 align_items = "ストレッチ"、 間隔= "0"、 )) #アプリに状態とページを追加します。 app = rx.app( テーマ= rx.theme( 外観= "ダーク"、 accent_color = "jade"、 )、、 styleSheets = ["https://fonts.googleapis.com/css2?family=ubuntu&display=swap"]、 style = { 「font_family」:「ubuntu」、 }、 )) app.add_page(index) app.add_page(chat_interface)
これは、チャットインターフェイスのコードです。フォントファミリをアプリの構成に追加しただけで、残りのコードは同じです。
次に、state.pyファイルを編集しましょう。これは、フロントエンドが応答のためにAPIエンドポイントを呼び出す場所です。
State.pyファイルの編集
リクエストをインポートします Rxとして反射をインポートします クラスQA(rx.base): 質問:str 回答:str default_chats = { 「イントロ」:[]、 } クラス状態(Rx.State): チャット:dict [str、list [qa]] = default_chats current_chat = "intros" url:str = "http:// localhost:8089/query" 質問:str 処理:bool = false new_chat_name:str = "" def create_chat(self): "" "新しいチャットの作成" "" #チャットのリストに新しいチャットを追加します。 self.current_chat = self.new_chat_name self.chats [self.new_chat_name] = [] def delete_chat(self): "" "現在のチャットを削除してください。" "" del self.chats [self.current_chat] Len(self.chats)== 0の場合: self.chats = default_chats self.current_chat = list(self.chats.keys())[0] def set_chat(self、chat_name:str): "" "現在のチャットの名前を設定します。 args: chat_name:チャットの名前。 "" " self.current_chat = chat_name @rx.var def chat_titles(self) - > list [str]: "" "チャットタイトルのリストを取得します。 返品: チャット名のリスト。 "" " returnリスト(self.chats.keys()) async def process_question(self、form_data:dict [str、str]): #フォームから質問を取得します 質問= form_data ["question"] #質問が空であるかどうかを確認してください 質問== ""の場合: 戻る Model = self.openai_process_question モデルの価値に対する非同期(質問): 降伏値 async def openai_process_question(self、question:str): "" "APIから応答を取得します。 args: form_data:現在の質問とのdict。 "" " #質問のリストに質問を追加します。 QA = QA(質問=質問、回答= "") self.chats [self.current_chat] .append(qa) ペイロード= {"質問":質問} #入力をクリアし、処理を開始します。 self.processing = true 収率 応答= requests.post(self.url、json = payload、stream = true) #結果をストリーミングし、すべての単語の後に生成します。 Response.iter_content(chunk_size = 512)の回答_textの場合: #surnsed_textが連結前にはないことを確認してください Answer_text = Answer_text.decode() answer_textがいない場合: self.chats [self.current_chat] [-1] .answer = answer_text それ以外: Answer_Text = "" self.chats [self.current_chat] [-1] .answer = answer_text self.chats = self.chats 収率 #処理フラグを切り替えます。 self.processing = false
このファイルでは、クエリエンドポイントのURLを定義しました。また、openai_process_questionメソッドを変更して、クエリエンドポイントにPOSTリクエストを送信し、ストリーミングを取得しました
応答。チャットインターフェイスに表示されます。
file_upload.pyファイルのコンテンツを作成します
最後に、file_upload.pyファイルの内容を書きましょう。このコンポーネントは最初に表示され、ファイルを摂取用にアップロードできます。
Rxとして反射をインポートします OSをインポートします インポート時間 リクエストをインポートします クラスuploadexample(rx.state): アップロード:bool = false 摂取:bool = false 進行状況:int = 0 Total_bytes:int = 0 ingestion_url = "http://127.0.0.1:8089/ingest" async def handle_upload(self、files:list [rx.uploadfile]): self.ingesting = true 収率 ファイルのファイルの場合: file_bytes = await file.read() file_name = file.fileName files = { "file" :( os.path.basename(file_name)、file_bytes、 "multipart/form-data") } response = requests.post(self.ingestion_url、files = files) self.ingesting = false 収率 response.status_code == 200の場合: #降伏rx.redirect( "/chat") self.show_redirect_popup() def handle_upload_progress(self、progress:dict): self.uploading = true self.progress = round(progress ["progress"] * 100) self.progress> = 100の場合: self.uploading = false def cancel_upload(self): self.uploading = false RX.CANCEL_UPLOAD( "upload3")を返す def upload_form(): RX.VSTACKを返します( rx.upload( rx.flex( rx.text( 「ここでファイルをドラッグアンドドロップするか、[ファイルを選択して[ファイル]を選択します」、 font_family = "ubuntu"、 )、、 rx.icon( "upload"、size = 30)、 方向= "列"、 align = "center"、 )、、 、 border = "1pxソリッドRGB(233、233,233、0.4)"、 マージン= "5em 0 10px 0"、 background_color = "rgb(107,99,246)"、 border_radius = "8px"、 パディング= "1em"、 )、、 rx.vstack(rx.foreach(rx.selected_files( "upload3")、rx.text))、 rx.cond( 〜uploadexample.ingesting、 rx.button( "アップロード"、 on_click = uploadexample.handle_upload( rx.upload_files( アップロード_、 on_upload_progress = uploadexample.handle_upload_progress、 )、、 )、、 )、、 rx.flex( rx.spinner(size = "3"、loading = uploadexample.ingesting)、 rx.button( "キャンセル"、 on_click = uploadexample.cancel_upload、 )、、 align = "center"、 間隔= "3"、 )、、 )、、 rx.alert_dialog.root( rx.alert_dialog.trigger( rx.button( "Conion of Chat"、color_scheme = "green")、 )、、 rx.alert_dialog.content( rx.alert_dialog.title( "チャットインターフェイスにリダイレクト?")、 rx.alert_dialog.description( 「チャットインターフェイスにリダイレクトされます。」 size = "2"、 )、、 rx.flex( rx.alert_dialog.cancel( rx.button( "キャンセル"、 variant = "soft"、 color_scheme = "gray"、 )、、 )、、 rx.alert_dialog.action( rx.button( "続く"、 color_scheme = "green"、 variant = "solid"、 on_click = rx.redirect( "/chat")、 )、、 )、、 間隔= "3"、 margin_top = "16px"、 justify = "end"、 )、、 style = {"max_width":450}、 )、、 )、、 align = "center"、 ))
このコンポーネントを使用すると、ファイルをアップロードしてベクトルストアに摂取できます。 FastAPIアプリのINGESTエンドポイントを使用して、ファイルをアップロードして摂取します。摂取後、ユーザーは単純に移動できます
クエリを尋ねるためのチャットインターフェイスに。
これにより、アプリケーション用のフロントエンドの構築を完了しました。次に、いくつかのドキュメントを使用してアプリケーションをテストする必要があります。
テストと展開
次に、いくつかのマニュアルまたはドキュメントでアプリケーションをテストしましょう。アプリケーションを使用するには、バックエンドアプリとReflexアプリの両方を個別に実行する必要があります。を使用して、ディレクトリからバックエンドアプリを実行します
次のコマンド:
python app.py
Fastapiが走り始めるのを待ちます。次に、別の端末インスタンスで、次のコマンドを使用してフロントエンドアプリを実行します。
反射実行
アプリが稼働している1つは、次のURLにアクセスしてReflexアプリにアクセスしました。最初はファイルアップロードページになります。ファイルをアップロードして、アップロードボタンを押します。
ファイルはアップロードされて摂取されます。ドキュメントのサイズに応じて、これには時間がかかります
デバイス仕様。完了したら、[チャットを続行]ボタンをクリックして、チャットインターフェイスに移動します。クエリを書き、送信を押します。
結論
このTwo部品では、コアパイプラインの作成からFastAPIバックエンドでラッピングし、反射ベースのフロントエンドの開発まで、Raspberry Piに完全かつ機能的なRAGアプリケーションを構築しました。これらのツールを使用すると、RAGパイプラインにアクセスしやすくインタラクティブになり、ユーザーフレンドリーなWebインターフェイスを介してリアルタイムのクエリ処理を提供します。これらの手順を習得することで、コンパクトで効率的なプラットフォームにエンドツーエンドアプリケーションを構築および展開することで貴重な経験を積むことができます。このセットアップは、Raspberry Piなどのリソース制約のあるデバイスにAI駆動型アプリケーションを展開するための無数の可能性への扉を開き、最先端のテクノロジーを日常の使用にアクセスしやすく実用的にします。
キーテイクアウト
- Ollamaを使用して必要な依存関係とモデルをインストールするなど、開発環境のセットアップに関する詳細なガイドが提供され、アプリケーションが最終ビルドの準備ができていることを確認します。
- この記事では、モデルをクエリするためのエンドポイントのセットアップやWeb APIを介してパイプラインにアクセスできるようにするなど、RAGパイプラインをFastAPIアプリケーションでラップする方法について説明します。
- RAGアプリケーションのフロントエンドは、PythonのみのフロントエンドライブラリであるReflexを使用して構築されています。この記事では、チャットアプリケーションテンプレートを変更して、RAGパイプラインと対話するためのユーザーフレンドリーなインターフェイスを作成する方法を示しています。
- この記事は、FastaPiバックエンドを反射フロントエンドと統合し、Raspberry PIに完全なアプリケーションを展開し、シームレスな操作とユーザーのアクセシビリティを確保することについてガイドします。
- PostmanやThunderクライアントなどのツールを使用して、摂取エンドポイントとクエリエンドポイントの両方をテストするための実用的な手順と、リフレックスフロントエンドの実行とテストを行い、アプリケーション全体が予想どおりに機能するようにします。
よくある質問
Q1:セキュリティを損なうことなく、世界のどこからでもアプリにアクセスできるようにするにはどうすればよいですか?A.テールスケールという名前のプラットフォームがあり、デバイスをプライベートセキュアネットワークに接続して、アクセスできるプラットフォームがあります。 Raspberry PIおよびその他のデバイスをテールスケールデバイスに追加し、VPNに接続して、世界中のどこからでもアプリにアクセスできます。
Q2:私のアプリケーションは、摂取とQNAの点で非常に遅いです。A.これは、Raspberry Piのハードウェア仕様が低いための制約です。この記事は、Raspberry PiとOllamaを使用してRagアプリの構築を開始する方法に関するヘッドアップチュートリアルです。
この記事に示されているメディアは、Analytics Vidhyaが所有しておらず、著者の裁量で使用されています。
以上がラングチェーン付きのエッジデバイスでのセルフホスティングラグアプリケーションの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undress AI Tool
脱衣画像を無料で

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック

投資は活況を呈していますが、資本だけでは十分ではありません。評価が上昇し、独特の衰退があるため、AIに焦点を当てたベンチャーファンドの投資家は、優位性を獲得するために購入、構築、またはパートナーの重要な決定を下す必要がありますか?各オプションを評価する方法とpr

それについて話しましょう。 革新的なAIブレークスルーのこの分析は、さまざまなインパクトのあるAIの複雑さの特定と説明など、最新のAIで進行中のForbes列のカバレッジの一部です(こちらのリンクを参照)。 アギに向かっています

今年初めにゲナイ産業を混乱させたオープンソースの中国モデルの洪水を覚えていますか? Deepseekはほとんどの見出しを取りましたが、Kimi K1.5はリストの著名な名前の1つでした。そして、モデルはとてもクールでした。

それについて話しましょう。 革新的なAIブレークスルーのこの分析は、さまざまなインパクトのあるAIの複雑さの特定と説明など、最新のAIで進行中のForbes列のカバレッジの一部です(こちらのリンクを参照)。 hの読者のために

2025年半ばまでに、AIの「武器競争」は熱くなり、Xaiと人類は両方ともフラッグシップモデルであるGrok 4とClaude 4をリリースしました。これら2つのモデルは、設計哲学と展開プラットフォームの反対側にありますが、

たとえば、モデルに「(x)人は(x)会社で何をしているのですか?」という質問をする場合、システムが必要な情報を取得する方法を知っていると仮定して、このようなものに見える推論チェーンを見るかもしれません:COの詳細を見つける

臨床試験は医薬品開発における膨大なボトルネックであり、キムとレディは、PI Healthで構築していたAI対応ソフトウェアが、潜在的に適格な患者のプールを拡大することでより速く、より安価にできると考えました。しかし、

上院は、火曜日の朝99-1で投票して、擁護団体、議員、そしてそれを危険な行き過ぎと見なした何万人ものアメリカ人からの土壇場の騒動の後、モラトリアムを殺しました。彼らは静かにいませんでした。上院は聞いた
