目录
介绍
学习目标
目录
创建Python环境
使用FastApi开发后端
摄入的代码
QNA类代码
FastAPI应用程序的代码
用反射设计前端
前端目录
最终应用程序的步骤
步骤1:在前端目录中克隆聊天模板存储库
步骤2:运行以下命令将目录初始化为反射应用
步骤3:测试应用程序,使用从前端目录内部的以下命令
主聊天组件的代码
编辑状态.py文件
编写file_upload.py文件的内容
测试和部署
结论
关键要点
常见问题
首页 科技周边 人工智能 带有Langchain的边缘设备上的自托管抹布应用

带有Langchain的边缘设备上的自托管抹布应用

Apr 14, 2025 am 10:35 AM

介绍

在我们在Raspberry Pi上构建RAG应用程序的系列文章的第二部分中,我们将在第一部分奠定的基础上扩展,在该基础上我们创建并测试了核心管道。在第一部分中,我们创建了核心管道并对其进行了测试,以确保一切按预期工作。现在,我们将通过构建FastApi应用程序来服务我们的破布管道并创建反射应用程序,从而为用户提供一种简单且交互式的方式来访问它,从而进一步迈出一步。这部分将指导您设置FastApi后端,用Reflex设计前端,并在Raspberry Pi上启动并运行所有内容。最后,您将拥有一个完整的工作应用程序,该应用程序已准备好现实使用。

学习目标

  • 设置FastApi后端,以与现有的RAG管道集成并有效地查询。
  • 使用Reflex设计一个用户友好的界面,以与FastApi后端和RAG管道进行交互。
  • 创建和测试用于查询和文档摄入的API端点,从而确保使用FastAPI平稳操作。
  • 在Raspberry Pi上部署和测试完整的应用程序,以确保后端和前端组件同时无缝函数。
  • 了解FastApi和Reflex之间的集成,以获得凝聚力的RAG应用体验。
  • 实施和故障排除FastApi和Reflex组件,以在Raspberry Pi上提供完全操作的抹布应用。

如果您错过了上一版,请务必在此处查看:带有Langchain和Ollama的边缘设备上的自托管破布应用程序 - 第一部分

目录

  • 创建Python环境
  • 使用FastApi开发后端
  • 用反射设计前端
  • 测试和部署
  • 常见问题

本文作为数据科学博客马拉松的一部分发表

创建Python环境

在创建应用程序开始之前,我们需要设置环境。创建环境并安装以下依赖关系:

深石 
boto3 == 1.34.144 
Botocore == 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 
兰链核== 0.2.11 
Langchain-验证== 0.0.62 
Langchain-Text-Splitters == 0.2.2 
langsmith == 0.1.83 
棉花糖== 3.21.3 
numpy == 1.26.4 
熊猫== 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
登录后复制

安装了所需的软件包后,我们需要在设备中放置所需的型号。我们将使用Ollama来做到这一点。请按照本文第1部分的步骤下载语言和嵌入模型。最后,为后端和前端应用程序创建两个目录。

一旦使用Ollama拉动了模型,我们就准备构建最终应用程序。

使用FastApi开发后端

在本文的第1部分中,我们建立了具有摄入和QNA模块的抹布管道。我们已经使用一些文档对两个管道进行了测试,并且它们正常工作。现在,我们需要用FastAPI包装管道来创建易于使用的API。这将有助于我们将其与任何前端应用程序集成在一起,例如简化,链条,Gradio,Reflex,React,Angular等。让我们首先构建应用程序的结构。遵循结构是完全可选的,但是如果您遵循其他结构来创建应用程序,请确保检查依赖关系导入。

以下是我们将遵循的树结构:

后端
├ -  app.py
├ - ─txt
└ -  src
    ├─Config.py
    ├─doc_loader
    │││─-base_loader.py
    │├├前__init__.py
    PDF_LOADER.PY
    ├─摄取
    ├ -  __init__.py
    └─QNA.PY
登录后复制

让我们从config.py开始。该文件将包含应用程序的所有可配置选项,例如Ollama URL,LLM名称和嵌入式模型名称。以下是一个示例:

 lanking_model_name =“ phi3”
embeddings_model_name =“ nomic-embed-text”
Ollama_url =“ http:// localhost:11434”
登录后复制

base_loader.py文件包含由孩子Document Loader继承的父文档加载程序类。在此应用程序中,我们仅使用PDF文件,因此Child PDFLoader类将是
创建将继承基本负载类。

以下是base_loader.py和pdf_loader.py的内容:

 #base_loader.py
来自ABC Import ABC,AbstractMethod

班级加载工(ABC):
    def __init __(self,file_path:str) - >无:
        self.file_path = file_path

    @AbstractMethod
    异步def load_document(self):
        经过


#pdf_loader.py
导入操作系统

来自.base_loader导入基本负载器
来自langchain.schema导入文档
来自langchain.document_loaders.pdf导入pymupdfloader
来自langchain.text_splitter导入tarnextsplitter


PDFLOADER类(基本负载器):
    def __init __(self,file_path:str) - >无:
        super().__ INT __(file_path)

    异步def load_document(self):
        self.file_name = os.path.basename(self.file_path)
        loader = pymupdfloader(file_path = self.file_path)

        text_splitter = partinextsplitter(
            saparator =“ \ n”,
            chunk_size = 1000,
            chunk_overlap = 200,
        )
        页面=等待loader.aload()
        total_pages = len(页)
        块= []
        对于IDX,枚举(页)中的页面:
            chunks.append(
                文档(
                    page_content = pag.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部分中构建的那个相同。

摄入的代码

导入操作系统
导入config作为CFG

来自Pinecone Import Pinecone
来自langchain.Vectorstores.Deeplake Import Deeplake
来自langchain.embeddings.ollama进口Ollamaembeddings
来自.doc_loader导入pdfloader

类摄入:
    “”“记录摄入管道。”“”
    def __init __(自我):
        尝试:
            self.embeddings = ollamaembeddings(
                型号= 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,
                冗长= false,
            )
        除例外为E:
            提高RuntimeError(F“无法初始化摄入系统。错误:{e}”)

    异步def create_and_add_embeddings(
        自己,
        文件:str,,
    ):
        尝试:
            loader = pdfloader(
                file_path =文件,
            )

            块=等待loader.load_document()
            size =等待self.vector_store.aadd_documents(documents =块)
            返回Len(尺寸)
        除(valueerror,runtimeerror,keyError,typeError)作为e:
            提高异常(f“错误:{e}”)
登录后复制

现在,我们已经设置了摄入类,我们将继续创建QNA类。这也与我们在本文第1部分中创建的那个相同。

QNA类代码

导入操作系统
导入config作为CFG

来自Pinecone Import Pinecone
来自langchain.Vectorstores.Deeplake Import Deeplake
来自langchain.embeddings.ollama进口Ollamaembeddings
来自langchain_community.llms.ollama import ollama
来自.doc_loader导入pdfloader

QNA类:
    “”“记录摄入管道。”“”
    def __init __(自我):
        尝试:
            self.embeddings = ollamaembeddings(
                型号= cfg.embeddings_model_name,
                base_url = cfg.ollama_url,
                show_progress = true,
            )
            self.model = ollama(
                型号= cfg.language_model_name,
                base_url = cfg.ollama_url,
                详细= true,
                温度= 0.2,
            )
            self.vector_store = deeplake(
                dataset_path =“ data/text_vectorstore”,
                嵌入= self.embeddings,
                num_workers = 4,
                冗长= false,
            )
            self.triever = self.vector_store.as_retriever(
                search_type =“相似性”,
                search_kwargs = {
                    “ K”:10,
                },,
            )
        除例外为E:
            提高RuntimeError(F“无法初始化摄入系统。错误:{e}”)

    def create_rag_chain(self):
        尝试:
            system_prompt =“”“”
            ”“”
            提示= chatprompttemplate.from_messages(
                [
                    (“系统”,system_prompt),
                    (“人类”,“ {input}”),
                这是给出的
            )
            Question_answer_chain = create_stuff_documents_chain(self.model,提示)
            rag_chain = create_retrieval_chain(self.triever,Question_answer_chain)

            返回rag_chain
        除例外为E:
            提高RuntimeError(F“无法创建检索链。错误:{e}”)
登录后复制

这样,我们已经完成了创建RAG应用程序的代码功能。现在,让我们用fastapi包装该应用程序。

FastAPI应用程序的代码

导入系统
导入操作系统
导入紫外线

从SRC进口QNA摄入
来自FastAPI Import FastApi,请求,文件,uploadfile
来自fastapi.Respons import streamResponse

app = fastapi()

摄入=摄入()
chatbot = qna()
rag_chain = chatbot.create_rag_chain()


@app.get(“/”)
def hello():
    返回{“消息”:“在服务器8089中运行的API}


@app.post(“/query”)
异步def ask_query(请求:请求):
    data =等待请求.json()
    问题= data.get(“问题”)

    异步def event_generator():
        对于rag_chain.pick中的块(“答案”)。
            产生块

    返回streamingresponse(event_generator(),媒体_type =“ text/plain”)


@app.post(“/ingest”)
异步def ingest_document(文件:uploadfile = file(...)):
    尝试:
        os.makedirs(“文件”,equent_ok = true)
        file_location = f“ files/{file.filename}”
        使用file_object的打开(file_location,“ wb”):
            file_object.write(file.file.read())

        size =等待摄入.create_and_add_embeddings(file = file_location)
        返回{“消息”:f“摄入文件!文档计数:{size}”}
    除例外为E:
        返回{“消息”:f“发生错误:{e}”}


如果__name__ ==“ __ -main __”:
    尝试:
        uvicorn.run(app,host =“ 0.0.0.0”,端口= 8089)
    除了键盘间断为E:
        打印(“应用程序停止!”)
登录后复制

让我们通过每个端点分解应用程序:

  • 首先,我们初始化FastApi应用程序,摄入和QNA对象。然后,我们使用QNA类的create_rag_chain方法创建一个抹布链。
  • 我们的第一个终点是一个简单的获取方法。这将有助于我们知道该应用是否健康。将其视为“ Hello World”终点。
  • 第二个是查询端点。这是一种帖子方法,将用于运行链条。它采用一个请求参数,我们从中提取用户的查询。然后,我们创建了一种异步方法,该方法在链条函数呼叫周围充当异步包装器。我们需要这样做,以允许FastApi处理LLM的流函数调用,以在聊天界面中获得类似ChatGpt的体验。然后,我们将异步方法与StreamResponse类包装并返回。
  • 第三端点是摄入端点。这也是一种帖子方法,将整个文件作为输入作为字节。我们将此文件存储在本地目录中,然后使用摄入类的create_and_add_embeddings方法摄入。

最后,我们使用主机和端口使用Uvicorn软件包运行该应用程序。要测试应用程序,只需使用以下命令运行应用程序:

 python app.py
登录后复制
登录后复制

带有Langchain的边缘设备上的自托管抹布应用

使用Postman,失眠或Bruno等API测试IDE测试应用程序。您也可以使用Thunder Client Extension进行相同的操作。

测试摄入端点:

带有Langchain的边缘设备上的自托管抹布应用

测试查询端点:

带有Langchain的边缘设备上的自托管抹布应用

用反射设计前端

我们已经成功创建了一个用于后端的FastApi应用程序。是时候建立我们的前端了。您可以为此选择任何前端库,但是对于本文,我们将使用Reflex构建前端。 Reflex是一个仅使用Python的前端库,纯粹是使用Python构建Web应用程序的。它通过用于计算器,图像生成和聊天机器人等常见应用程序的模板证明了我们。我们将使用聊天机器人应用模板作为用户界面的启动。我们的最终应用程序将具有以下结构,因此让我们在此处参考。

前端目录

我们将拥有一个前端目录:

前端
├ - 资产
│└└前favicon.ico
├ - 文档
│└ -  emo.gif
├ - 聊天
组件
││││站
│││├站file_upload.py
││├ -  __init__.py
││││─..poting_icon.py
│││├站
Navbar.py
│├├前__init__.py
Chat.py
sate.py
├ - ─txt
├─-rxConfig.py
└ - 上传_files
登录后复制

最终应用程序的步骤

按照步骤准备最终应用程序的接地。

步骤1:在前端目录中克隆聊天模板存储库

git克隆https://github.com/reflex-dev/reflex-chat.git。
登录后复制

步骤2:运行以下命令将目录初始化为反射应用

Reflex Init
登录后复制

带有Langchain的边缘设备上的自托管抹布应用

这将设置Reflex应用程序,并准备好运行和开发。

步骤3:测试应用程序,使用从前端目录内部的以下命令

反射运行
登录后复制
登录后复制

带有Langchain的边缘设备上的自托管抹布应用

让我们开始修改组件。首先,让我们修改chat.py文件。

以下是相同的代码:

导入反射为Rx
来自reflex_demo.com import incort loading_icon
来自reflex_demo.State Import QA,状态

messages_style = dict(dict)(
    display =“ inline-block”,
    填充=“ 0 10px”,
    border_radius =“ 8px”,
    max_width = [“ 30em”,“ 30em”,“ 50em”,“ 50em”,“ 50em”,“ 50em”],
)


DEF消息(QA:QA) - > rx.component:
    “”“一个问题/答案消息。

    args:
        QA:问题/答案对。

    返回:
        显示问题/答案对的组件。
    ”“”
    返回rx.box(
        rx.box(
            rx.markdown(
                QA.问题,
                background_color = rx.color(“淡紫色”,4),,
                color = rx.color(“淡紫色”,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 =“左”,
            padding_top =“ 1em”,
        ),
        宽度=“ 100%”,
    )


def chat() - > rx.component:
    “”“列出单个对话中的所有消息。”“”
    返回rx.vstack(
        rx.box(rx.foreach(state.chats [state.current_chat],消息),width =“ 100%”),
        py =“ 8”,
        flex =“ 1”,
        宽度=“ 100%”,
        max_width =“ 50em”,
        padding_x =“ 4px”,
        align_self =“中心”,
        溢出=“隐藏”,
        padding_bottom =“ 5em”,
    )


def Action_bar() - > rx.component:
    ”“”“动作栏发送新信息。”“”
    返回rx.center(
        rx.vstack(
            rx.chakra.form(
                rx.chakra.form_control(
                    rx.hstack(
                        rx。输入(
                            rx.input.slot(
                                rx.tooltip(
                                    rx.icon(“ info”,size = 18),
                                    content =“输入一个问题以获取答复。”,,
                                )
                            ),
                            占位符=“键入某物...”,
                            ,,,,
                            width = [“ 15em”,“ 20em”,“ 45em”,“ 50EM”,“ 50EM”,“ 50EM”],
                        ),
                        rx.button(
                            rx.cond(
                                state.processing,
                                loading_icon(高度=“ 1em”),
                                rx.text(“ send”,font_family =“ ubuntu”),
                            ),
                            type =“提交”,
                        ),
                        align_items =“中心”,
                    ),
                    is_disabled = state.processing,
                ),
                on_submit = state.process_question,
                reset_on_submit = true,
            ),
            rx.text(
                “反射可能会返回事实不正确或误导性响应。使用酌处权。”,
                text_align =“中心”,
                font_size =“。75EM”,
                color = rx.Color(“淡紫色”,10),
                font_family =“ ubuntu”,
            ),
            rx.logo(margin_top =“  -  1em”,margin_bottom =“  -  1em”),
            align_items =“中心”,
        ),
        位置=“粘性”,
        底部=“ 0”,
        左=“ 0”,
        padding_y =“ 16px”,
        backdrop_filter =“自动”,
        backdrop_blur =“ lg”,
        border_top = f“ 1px solid {rx.color('mauve',3)}”,
        background_color = rx.color(“淡紫色”,2),
        align_items =“ stract”,
        宽度=“ 100%”,
    )
登录后复制

这些变化是从模板中本地存在的最小化。

接下来,我们将编辑chat.py应用程序。这是主要的聊天组件。

主聊天组件的代码

以下是它的代码:

导入反射为Rx
来自reflex_demo.com.ponents导入聊天,navbar,upload_form
来自reflex_demo.State Extiment State


@rx.page(路由=“/chat”,title =“ rag chatbot”)
def chat_interface() - > rx.component:
    返回rx.chakra.vstack(
        navbar(),
        chat.chat(),
        chat.action_bar(),
        background_color = rx.color(“淡紫色”,1),
        color = rx.color(“淡紫色”,12),
        min_height =“ 100VH”,
        align_items =“ stract”,
        间距=“ 0”,
    )


@rx.page(route =“/”,title =“ rag chatbot”)
def index() - > rx.component:
    返回rx.chakra.vstack(
        navbar(),
        upload_form(),
        background_color = rx.color(“淡紫色”,1),
        color = rx.color(“淡紫色”,12),
        min_height =“ 100VH”,
        align_items =“ stract”,
        间距=“ 0”,
    )


#将状态和页面添加到应用程序。
app = rx.app(
    主题= rx.theme(
        外观=“黑暗”,
        accent_color =“玉”,
    ),
    stylesheets = [“ https://fonts.googleapis.com/css2?family=ubuntu&display=swap”],
    样式= {
        “ font_family”:“ ubuntu”,
    },,
)
app.add_page(索引)
app.add_page(chan_interface)
登录后复制

这是聊天接口的代码。我们仅将字体系列添加到应用程序配置中,其余代码是相同的。

接下来,让我们编辑state.py文件。这是前端将呼叫API端点以进行响应的地方。

编辑状态.py文件

导入请求
导入反射为Rx


QA类(RX.BASE):
    问题:str
    答案:str


default_chats = {
    “ intros”:[],
}


班级状态(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]:
        “”“获取聊天标题的列表。

        返回:
            聊天名称列表。
        ”“”
        返回列表(self.chats.keys())

    异步def process_question(self,form_data:dict [str,str]):
        #从表格中获取问题
        问题= form_data [“问题”]

        #检查问题是否为空
        如果问题==“”:
            返回

        型号= self.openai_process_question

        在模型中的价值异步(问题):
            产量值

    异步def openai_process_question(自我,问题:str):
        “”“从API获取响应。

        args:
            form_data:一个带有当前问题的dict。
        ”“”
        #将问题添加到问题列表中。
        QA = QA(问题=问题,答案=“”)
        self.chats [self.current_chat] .append(QA)
        有效载荷= {“问题”:问题}

        #清除输入并开始处理。
        self.processing = true
        屈服

        响应= requests.post(self.url,json =有效载荷,流= true)

        #流式传输结果,在每个单词之后产生。
        for Answers_text in enthys.iter_content(chunk_size = 512):
            #确保答案_text在串联之前不是没有
            答案_text = wherme_text.decode()
            如果答案_text不是没有:
                self.Chats [self.current_chat] [ -  1] .answer = answers_text
            别的:
                答案_text =“”
                self.Chats [self.current_chat] [ -  1] .answer = answers_text
            self.chats = self.chats
            屈服

        #切换处理标志。
        self.processing = false
登录后复制

在此文件中,我们为查询端点定义了URL。我们还修改了OpenAI_Process_Question方法,以将邮政请求发送到查询端点并获取流媒体
响应,将显示在聊天接口中。

编写file_upload.py文件的内容

最后,让我们编写file_upload.py文件的内容。此组件将在开头显示,这将使我们可以上传文件以进行摄入。

导入反射为Rx
导入操作系统
进口时间

导入请求


类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 =等待file.read()
            file_name = file.filename
            文件= {
                “文件”:(OS.Path.BasEname(file_name),file_bytes,“ multipart/form-data”)
            }
            响应= requests.post(self.ingestion_url,files = files)
            self.ingesting = false
            屈服
            如果响应。STATUS_CODE== 200:
                #屈服rx.redirect(“/chat”)
                self.show_redirect_popup()

    def handle_upload_progress(自我,进度:dict):
        self.uploading = true
        self.progress = rough(进度[“进度”] * 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(“上传”,大小= 30),
                方向=“列”,
                align =“中心”,
            ),
            ,,,,
            border =“ 1px固体RGB(233,233,233,0.4)”,
            margin =“ 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。
            rx.button(
                “上传”,
                on_click = uploadexample.handle_upload(
                    rx.upload_files(
                        上传_,
                        on_upload_progress = uploadexample.handle_upload_progress,
                    ),
                ),
            ),
            rx.Flex(
                rx.spinner(size =“ 3”,加载= uploadexample.ingesting),
                rx.button(
                    “取消”,
                    on_click = uploadexample.cancel_upload,
                ),
                align =“中心”,
                间距=“ 3”,
            ),
        ),
        rx.alert_dialog.root(
            rx.alert_dialog.trigger(
                rx.button(“继续聊天”,color_scheme =“ green”),
            ),
            rx.alert_dialog.content(
                rx.alert_dialog.title(“重定向聊天接口?”),),
                rx.alert_dialog.Description(
                    “您将被重定向到聊天界面。”
                    尺寸=“ 2”,
                ),
                rx.Flex(
                    rx.alert_dialog.cancel(
                        rx.button(
                            “取消”,
                            变体=“软”,
                            color_scheme =“灰色”,
                        ),
                    ),
                    rx.alert_dialog.Action(
                        rx.button(
                            “继续”,
                            color_scheme =“绿色”,
                            变体=“固体”,
                            on_click = rx.redirect(“/chat”),
                        ),
                    ),
                    间距=“ 3”,
                    margin_top =“ 16px”,
                    Justify =“ End”,
                ),
                样式= {“ max_width”:450},
            ),
        ),
        align =“中心”,
    )
登录后复制

此组件将允许我们上传文件并将其摄入矢量存储。它使用我们的FastApi应用程序的摄入端点上传和摄入文件。摄入后,用户可以简单地移动
到聊天界面询问查询。

这样,我们已经完成了为我们的应用程序构建前端。现在,我们需要使用一些文档来测试应用程序。

测试和部署

现在,让我们在某些手册或文档上测试应用程序。要使用该应用程序,我们需要单独运行后端应用程序和Reflex应用程序。使用该目录运行后端应用
以下命令:

 python app.py
登录后复制
登录后复制

等待FastApi开始运行。然后在另一个终端实例中使用以下命令运行前端应用:

反射运行
登录后复制
登录后复制

应用程序正在启动和运行,到达以下URL访问Reflex应用程序。最初,我们将在文件上传页面中。上传文件,然后按“上传”按钮。

带有Langchain的边缘设备上的自托管抹布应用

该文件将上传并摄入。这将需要一段时间,具体取决于文档的大小和
设备规格。完成后,单击“继续聊天”按钮以移至聊天接口。编写您的查询,然后按发送。

结论

在Thistwo Parteries中,您现在您在Raspberry Pi上构建了一个完整且功能上功能的RAG应用程序,从创建核心管道到用FastApi后端包装并开发基于反射的前端。借助这些工具,您的破布管道是可访问且交互式的,可通过用户友好的Web界面提供实时查询处理。通过掌握这些步骤,您在紧凑,高效的平台上构建和部署端到端应用程序方面获得了宝贵的经验。这种设置为在Raspberry Pi(例如Raspberry Pi)上部署AI驱动应用程序的无数可能性打开了大门,这使得最先进的技术更容易访问和实用。

关键要点

  • 提供了有关设置开发环境的详细指南,包括使用Ollama安装必要的依赖项和模型,以确保该应用程序已准备好最终构建。
  • 本文解释了如何将RAG管道包裹在FastAPI应用程序中,包括设置查询模型和摄入文档的终点,使该管道可以通过Web API访问。
  • RAG应用程序的前端是使用Reflex(仅Python的前端库Reflex构建的。本文演示了如何修改聊天应用程序模板以创建用于与RAG管道进行交互的用户友好界面。
  • 本文指南将FastAPI后端与反射前端集成在一起,并在Raspberry Pi上部署完整的应用程序,以确保无缝操作和用户可访问性。
  • 提供了使用Postman或Thunder Client等工具来测试摄入和查询端点的实用步骤,同时运行和测试反射前端,以确保整个应用程序按预期功能。

常见问题

问题1:如何使自己可以从世界任何地方访问该应用程序而不会损害安全性?

答:有一个名为TailScale的平台,允许您的设备连接到私人安全网络,仅可访问您。您可以将Raspberry Pi和其他设备添加到尾部设备中,并连接到VPN以访问您的应用程序。

Q2:我的摄入和QNA的应用非常慢。

答:由于覆盆子PI的硬件规格较低,这是限制。这篇文章只是有关如何使用Raspberry Pi和Ollama构建RAG应用程序的主题教程。

本文所示的媒体不由Analytics Vidhya拥有,并由作者酌情使用。

以上是带有Langchain的边缘设备上的自托管抹布应用的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
<🎜>掩盖:探险33-如何获得完美的色度催化剂
2 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1677
14
CakePHP 教程
1430
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
如何使用AGNO框架构建多模式AI代理? 如何使用AGNO框架构建多模式AI代理? Apr 23, 2025 am 11:30 AM

在从事代理AI时,开发人员经常发现自己在速度,灵活性和资源效率之间进行权衡。我一直在探索代理AI框架,并遇到了Agno(以前是Phi-

OpenAI以GPT-4.1的重点转移,将编码和成本效率优先考虑 OpenAI以GPT-4.1的重点转移,将编码和成本效率优先考虑 Apr 16, 2025 am 11:37 AM

该版本包括三种不同的型号,GPT-4.1,GPT-4.1 MINI和GPT-4.1 NANO,标志着向大语言模型景观内的特定任务优化迈进。这些模型并未立即替换诸如

如何在SQL中添加列? - 分析Vidhya 如何在SQL中添加列? - 分析Vidhya Apr 17, 2025 am 11:43 AM

SQL的Alter表语句:动态地将列添加到数据库 在数据管理中,SQL的适应性至关重要。 需要即时调整数据库结构吗? Alter表语句是您的解决方案。本指南的详细信息添加了Colu

火箭发射模拟和分析使用Rocketpy -Analytics Vidhya 火箭发射模拟和分析使用Rocketpy -Analytics Vidhya Apr 19, 2025 am 11:12 AM

模拟火箭发射的火箭发射:综合指南 本文指导您使用强大的Python库Rocketpy模拟高功率火箭发射。 我们将介绍从定义火箭组件到分析模拟的所有内容

DeepCoder-14b:O3-Mini和O1的开源竞赛 DeepCoder-14b:O3-Mini和O1的开源竞赛 Apr 26, 2025 am 09:07 AM

在AI社区的重大发展中,Agentica和AI共同发布了一个名为DeepCoder-14B的开源AI编码模型。与OpenAI等封闭源竞争对手提供代码生成功能

提示:chatgpt生成假护照 提示:chatgpt生成假护照 Apr 16, 2025 am 11:35 AM

Chip Giant Nvidia周一表示,它将开始制造AI超级计算机(可以处理大量数据并运行复杂算法的机器),完全是在美国首次在美国境内。这一消息是在特朗普总统SI之后发布的

盖伊·佩里(Guy Peri)通过数据转换帮助麦考密克的未来 盖伊·佩里(Guy Peri)通过数据转换帮助麦考密克的未来 Apr 19, 2025 am 11:35 AM

盖伊·佩里(Guy Peri)是麦考密克(McCormick)的首席信息和数字官。尽管他的角色仅七个月,但Peri正在迅速促进公司数字能力的全面转变。他的职业生涯专注于数据和分析信息

跑道AI的Gen-4:AI蒙太奇如何超越荒谬 跑道AI的Gen-4:AI蒙太奇如何超越荒谬 Apr 16, 2025 am 11:45 AM

从数字营销到社交媒体的所有创意领域,电影业都站在技术十字路口。随着人工智能开始重塑视觉讲故事的各个方面并改变娱乐的景观

See all articles