You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Streamlit file_uploader与LangChain文档加载器配合使用?

Streamlit上传文件适配LangChain加载器解决方案

很多LangChain文档加载器(比如PyPDFLoader)要么需要本地文件路径,要么支持类文件对象,但直接把上传文件转成字符串会破坏原文件的二进制结构,导致加载器无法解析。下面是两种适配方案,其中临时文件方案是通用适配所有加载器的最优解。

方案1:临时文件(通用适配所有加载器)

不少加载器只认文件路径,这时候就需要把上传的文件内容写入一个临时文件,用临时文件路径给加载器用,用完再删掉临时文件就行。步骤很简单:

  • 用tempfile模块创建带原扩展名的临时文件
  • 把上传文件的字节数据写入临时文件
  • 用对应加载器读取临时文件路径
  • 处理完手动删除临时文件(避免残留)

方案2:类文件对象(仅部分加载器支持)

像TextLoader、CSVLoader这类加载器支持直接传入Streamlit上传的uploaded_file对象(本身就是类文件对象),不用创建临时文件,直接用就行。

完整可运行代码

import streamlit as st
from tempfile import NamedTemporaryFile
import os
from langchain.document_loaders import (
    PyPDFLoader, TextLoader, CSVLoader, Docx2txtLoader
)

# 定义文件扩展名和对应加载器的映射,方便扩展
LOADER_MAPPING = {
    ".pdf": PyPDFLoader,
    ".txt": TextLoader,
    ".csv": CSVLoader,
    ".docx": Docx2txtLoader
}

def load_uploaded_file(uploaded_file):
    # 提取文件扩展名(转小写)
    file_extension = "." + uploaded_file.name.split(".")[-1].lower()
    
    if file_extension not in LOADER_MAPPING:
        st.error(f"不支持该文件格式:{file_extension}")
        return None
    
    LoaderClass = LOADER_MAPPING[file_extension]
    
    # 针对需要文件路径的加载器(比如PDF、DOCX)
    if LoaderClass in [PyPDFLoader, Docx2txtLoader]:
        # 创建临时文件,保留原扩展名,delete=False表示先不自动删除
        with NamedTemporaryFile(delete=False, suffix=file_extension) as temp_file:
            temp_file.write(uploaded_file.getvalue())
            temp_path = temp_file.name
        
        # 加载并拆分文档
        loader = LoaderClass(temp_path)
        docs = loader.load_and_split()
        
        # 手动删除临时文件
        os.unlink(temp_path)
        
        return docs
    else:
        # 支持类文件对象的加载器,直接传入uploaded_file
        loader = LoaderClass(uploaded_file)
        docs = loader.load_and_split()
        return docs

# Streamlit页面布局
st.title("LangChain 文件加载工具")
uploaded_file = st.file_uploader("选择要加载的文件", type=list(LOADER_MAPPING.keys()))

if uploaded_file is not None:
    st.success(f"已成功上传:{uploaded_file.name}")
    loaded_docs = load_uploaded_file(uploaded_file)
    
    if loaded_docs:
        st.subheader("加载结果预览")
        for idx, doc in enumerate(loaded_docs):
            st.write(f"### 片段 {idx+1}")
            st.write(f"**来源文件:** {doc.metadata['source']}")
            st.write(f"**内容摘要:** {doc.page_content[:500]}...")  # 只显示前500字符,避免太长

重点说明

  • 临时文件处理:用NamedTemporaryFile创建临时文件时,delete=False是为了写完后能让加载器读取,处理完必须手动删除,防止临时文件堆积
  • 扩展性:如果需要支持更多文件格式,直接在LOADER_MAPPING里加对应的扩展名和加载器就行
  • 性能优化:对支持类文件对象的加载器直接使用上传对象,省去临时文件的IO操作,更快

内容的提问来源于stack exchange,提问作者Arshad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:37:41