如何将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
相关产品推荐
相关产品推荐

