搜索
首页科技周边人工智能带有Langchain的边缘设备上的自托管抹布应用

介绍

在我们在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
商业领袖生成引擎优化指南(GEO)商业领袖生成引擎优化指南(GEO)May 03, 2025 am 11:14 AM

Google正在领导这一转变。它的“ AI概述”功能已经为10亿用户提供服务,在任何人单击链接之前提供完整的答案。[^2] 其他球员也正在迅速获得地面。 Chatgpt,Microsoft Copilot和PE

该初创公司正在使用AI代理来与恶意广告和模仿帐户进行战斗该初创公司正在使用AI代理来与恶意广告和模仿帐户进行战斗May 03, 2025 am 11:13 AM

2022年,他创立了社会工程防御初创公司Doppel,以此做到这一点。随着网络犯罪分子越来越高级的AI模型来涡轮增压,Doppel的AI系统帮助企业对其进行了大规模的对抗 - 更快,更快,

世界模型如何从根本上重塑生成AI和LLM的未来世界模型如何从根本上重塑生成AI和LLM的未来May 03, 2025 am 11:12 AM

瞧,通过与合适的世界模型进行交互,可以实质上提高生成的AI和LLM。 让我们来谈谈。 对创新AI突破的这种分析是我正在进行的《福布斯》列的最新覆盖范围的一部分,包括

2050年五月:我们要庆祝什么?2050年五月:我们要庆祝什么?May 03, 2025 am 11:11 AM

劳动节2050年。全国范围内的公园充满了享受传统烧烤的家庭,而怀旧游行则穿过城市街道。然而,庆祝活动现在具有像博物馆般的品质 - 历史重演而不是纪念C

您从未听说过的DeepFake探测器准确是98%您从未听说过的DeepFake探测器准确是98%May 03, 2025 am 11:10 AM

为了帮助解决这一紧急且令人不安的趋势,在2025年2月的TEM期刊上进行了同行评审的文章,提供了有关该技术深击目前面对的最清晰,数据驱动的评估之一。 研究员

量子人才战争:隐藏的危机威胁技术的下一个边界量子人才战争:隐藏的危机威胁技术的下一个边界May 03, 2025 am 11:09 AM

从大大减少制定新药所需的时间到创造更绿色的能源,企业将有巨大的机会打破新的地面。 不过,有一个很大的问题:严重缺乏技能的人

原型:这些细菌可以产生电力原型:这些细菌可以产生电力May 03, 2025 am 11:08 AM

几年前,科学家发现某些类型的细菌似乎通过发电而不是吸收氧气而呼吸,但是它们是如何做到的,这是一个谜。一项发表在“杂志”杂志上的新研究确定了这种情况的发生方式:Microb

AI和网络安全:新政府的100天估算AI和网络安全:新政府的100天估算May 03, 2025 am 11:07 AM

在本周的RSAC 2025会议上,Snyk举办了一个及时的小组,标题为“前100天:AI,Policy&Cyber​​security Collide如何相撞”,其中包括全明星阵容:前CISA董事Jen Easterly;妮可·珀洛斯(Nicole Perlroth),前记者和帕特纳(Partne)

See all articles

热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

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

热工具

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器