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

调用FAISS.from_documents时触发IndexError索引越界问题

问题:调用FAISS.from_documents时触发IndexError: list index out of range

问题描述

使用LangChain的FAISS模块从文档列表构建向量索引时,调用FAISS.from_documents(docs, embeddings)触发IndexError: list index out of range,错误指向FAISS源码中index = faiss.IndexFlatL2(len(embeddings[0]))这一行,说明生成的嵌入向量列表为空,无法获取第一个元素的长度。

我的代码

import os
import streamlit as st
import pickle
import time
from langchain_openai import OpenAI
from langchain_openai import OpenAIEmbeddings
from langchain.chains import RetrievalQAWithSourcesChain
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import UnstructuredURLLoader
from dotenv import load_dotenv

load_dotenv()  # 从.env加载环境变量(主要是OpenAI API Key)

st.title("链接研究工具")
st.sidebar.title("新闻文章URL")

urls = []
for i in range(1):
    url = st.sidebar.text_input(f"URL {i+1}")
    urls.append(url)

process_url_clicked = st.sidebar.button("处理URL")
file_path = "faiss_store_openai.pkl"

llm = OpenAI(temperature=0.9, max_tokens=500)
if process_url_clicked:
    loader = UnstructuredURLLoader(urls=urls)
    st.text("数据加载中...")
    data = loader.load()
    text_splitter = RecursiveCharacterTextSplitter(
        separators=['\n\n', '\n', '.', ','],
        chunk_size=1000
    )
    st.text("文本分割中...")
    docs = text_splitter.split_documents(data)
    embeddings = OpenAIEmbeddings()
    db = FAISS.from_documents(docs, embeddings)
    st.text("嵌入向量构建中...")
    time.sleep(2)

query = st.text_input("问题: ")
if query:
    if os.path.exists(file_path):
        with open(file_path, "rb") as f:
            vectorstore = pickle.load(f)
            chain = RetrievalQAWithSourcesChain.from_llm(llm=llm, retriever=vectorstore.as_retriever())
            result = chain({"question": query}, return_only_outputs=True)
            # result格式为 {"answer": "", "sources": [] }
            st.header("答案")
            st.write(result["answer"])

            # 显示来源(如果有)
            sources = result.get("sources", "")
            if sources:
                st.subheader("来源:")
                sources_list = sources.split("\n")
                for source in sources_list:
                    st.write(source)

报错信息

File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 535, in _run_script
    exec(code, module.__dict__)
File "/Users/rahulsharma/Desktop/2_news_research_tool_project/main.py", line 41, in <module>
    db = FAISS.from_documents(docs, embeddings)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/langchain_core/vectorstores.py", line 528, in from_documents
    return cls.from_texts(texts, embedding, metadatas=metadatas, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/langchain_community/vectorstores/faiss.py", line 966, in from_texts
    return cls.__from(
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/langchain_community/vectorstores/faiss.py", line 923, in __from
    index = faiss.IndexFlatL2(len(embeddings[0]))

环境信息

langchain: 0.1.3
python-dotenv: 1.0.0
streamlit: 1.31.1
unstructured: 0.12.5
tiktoken: 0.5.2
faiss-cpu: 1.7.4
libmagic: 1.0
python-magic: 0.4.27
python-magic-bin: None
OpenAI: 1.13.3

原因分析

错误核心是embeddings为空列表,导致代码尝试访问embeddings[0]时触发索引越界。而embeddings为空的根源是输入的docs为空,可能的触发场景:

  • 未输入有效的URL,或输入的URL无法加载到内容
  • UnstructuredURLLoader加载失败(比如URL无效、网络问题、页面内容无法解析)
  • 文本分割后未生成任何有效文档块(比如源内容全是分隔符)

解决方案

1. 添加输入有效性检查

在处理URL前过滤空URL,加载数据和分割文本后检查结果是否为空,避免后续无效操作:

修改process_url_clicked分支的代码:

if process_url_clicked:
    # 过滤空URL
    valid_urls = [url.strip() for url in urls if url.strip()]
    if not valid_urls:
        st.error("请输入有效的URL地址")
        st.stop()
    
    loader = UnstructuredURLLoader(urls=valid_urls)
    st.text("数据加载中...")
    data = loader.load()
    
    # 检查是否加载到内容
    if not data:
        st.error("未能从URL加载到内容,请检查URL有效性或网络连接")
        st.stop()
    
    text_splitter = RecursiveCharacterTextSplitter(
        separators=['\n\n', '\n', '.', ','],
        chunk_size=1000,
        chunk_overlap=200  # 添加重叠部分,避免分割丢失上下文
    )
    st.text("文本分割中...")
    docs = text_splitter.split_documents(data)
    
    # 检查分割后是否有文档块
    if not docs:
        st.error("文本分割后未生成有效文档块,请检查源页面内容")
        st.stop()
    
    embeddings = OpenAIEmbeddings()
    db = FAISS.from_documents(docs, embeddings)
    st.text("嵌入向量构建中...")
    
    # 保存向量索引到文件(原代码缺失此步骤,导致查询时读取不到新构建的索引)
    with open(file_path, "wb") as f:
        pickle.dump(db, f)
    st.success("向量索引构建完成并已保存")

2. 修复其他潜在问题

  • 移除重复的OpenAIEmbeddings导入(原代码中同时从langchain_openai和langchain_community导入,保留一个即可)
  • 给RecursiveCharacterTextSplitter添加chunk_overlap参数,避免分割后上下文丢失
  • 确保.env文件中正确配置了OpenAI API Key,避免嵌入生成失败

预期结果

添加检查后,只有当输入有效URL、加载到内容并生成有效文档块时,才会执行FAISS向量索引构建,避免触发索引越界错误,同时构建完成的索引会保存到文件,供后续查询使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:07:14