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

如何用LlamaIndex加载大CSV文件适配OpenAI API查询?

处理大型CSV文件的LlamaIndex解决方案

问题背景

用create-llama搭建的应用,SimpleDirectoryReader().loadData可正常处理100多页PDF,但加载含17566个token的大型CSV时,触发以下错误:

BadRequestError: 400 This model's maximum context length is 8192 tokens, however you requested 17566 tokens (17566 in your prompt; 0 for the completion). Please reduce your prompt; or completion length.
at Function.generate (C:\Code\canoe\node_modules\openai\src\error.ts:70:14)
at OpenAI.makeStatusError (C:\Code\canoe\node_modules\openai\src\core.ts:383:21)
at OpenAI.makeRequest (C:\Code\canoe\node_modules\openai\src\core.ts:446:24)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async OpenAIEmbedding.getOpenAIEmbedding (C:\Code\canoe\node_modules\llamaindex\dist\cjs\embeddings\OpenAIEmbedding.js:100:26)
at async OpenAIEmbedding.getTextEmbeddings (C:\Code\canoe\node_modules\llamaindex\dist\cjs\embeddings\OpenAIEmbedding.js:111:16)
at async batchEmbeddings (C:\Code\canoe\node_modules\llamaindex\dist\cjs\embeddings\types.js:61:32)
at async OpenAIEmbedding.getTextEmbeddingsBatch (C:\Code\canoe\node_modules\llamaindex\dist\cjs\embeddings\types.js:43:16)
at async OpenAIEmbedding.transform (C:\Code\canoe\node_modules\llamaindex\dist\cjs\embeddings\types.js:47:28)
at async VectorStoreIndex.getNodeEmbeddingResults (C:\Code\canoe\node_modules\llamaindex\dist\cjs\indices\vectorStore\index.js:487:9)
at async VectorStoreIndex.insertNodes (C:\Code\canoe\node_modules\llamaindex\dist\cjs\indices\vectorStore\index.js:572:17)
at async VectorStoreIndex.buildIndexFromNodes (C:\Code\canoe\node_modules\llamaindex\dist\cjs\indices\vectorStore\index.js:497:9)
at async VectorStoreIndex.init (C:\Code\canoe\node_modules\llamaindex\dist\cjs\indices\vectorStore\index.js:445:13)
at async VectorStoreIndex.fromDocuments (C:\Code\canoe\node_modules\llamaindex\dist\cjs\indices\vectorStore\index.js:523:16)
at <anonymous> (C:\Code\canoe\app\api\chat\engine\generate.ts:27:5)
at getRuntime (C:\Code\canoe\app\api\chat\engine\generate.ts:14:3) {

核心失败代码:

async function generateDatasource() {
  console.log(`Generating storage context...`);
  // Split documents, create embeddings and store them in the storage context
  const ms = await getRuntime(async () => {
    const storageContext = await storageContextFromDefaults({
      persistDir: STORAGE_CACHE_DIR,
    });
    const documents = await getDocuments();
    await VectorStoreIndex.fromDocuments(documents, {
      storageContext,
    });
  });
  console.log(`Storage context successfully generated in ${ms / 1000}s.`);
}

.env配置:

MODEL=gpt-4-turbo 
EMBEDDING_MODEL=text-embedding-3-large
EMBEDDING_DIM=1024

解决方案

1. 创建无错误的文档存储、索引存储和向量存储

问题根源是默认读取方式将整个CSV文件作为单个Document处理,导致生成embedding时token数超限制。需通过文档拆分解决:

方式一:使用文本拆分器自动拆分

修改generateDatasource函数,在创建索引时指定文本拆分规则,确保每个chunk的token数低于embedding模型限制(text-embedding-3-large最大支持8192 token,建议留余量设为4000):

import { RecursiveCharacterTextSplitter } from "llamaindex";

async function generateDatasource() {
  console.log(`Generating storage context...`);
  const ms = await getRuntime(async () => {
    const storageContext = await storageContextFromDefaults({
      persistDir: STORAGE_CACHE_DIR,
    });
    const documents = await getDocuments();
    // 添加文本拆分器,拆分大型CSV为小chunk
    await VectorStoreIndex.fromDocuments(documents, {
      storageContext,
      transformations: [
        new RecursiveCharacterTextSplitter({
          chunkSize: 4000, // 每个chunk的token数
          chunkOverlap: 200, // 重叠部分,保持上下文连贯性
        }),
      ],
    });
  });
  console.log(`Storage context successfully generated in ${ms / 1000}s.`);
}

方式二:使用CSVReader针对性读取

如果CSV是结构化表格,用CSVReader替代默认读取器,可按行或自定义规则拆分文档:

import { CSVReader, RecursiveCharacterTextSplitter } from "llamaindex";

async function getDocuments() {
  // 初始化CSV读取器,支持配置表头、分隔符等
  const csvReader = new CSVReader({
    headerRow: true,
    separator: ",",
  });
  // 读取CSV文件,返回Document数组
  const documents = await csvReader.loadData("./path/to/large.csv");
  // 配合拆分器进一步拆分
  const splitter = new RecursiveCharacterTextSplitter({
    chunkSize: 4000,
    chunkOverlap: 200,
  });
  return splitter.splitDocuments(documents);
}

2. 在token限制内查询CSV数据

针对大型CSV的查询,需优化召回逻辑,避免超出LLM的token限制:

方式一:优化向量查询引擎

构建查询引擎时,控制召回的chunk数量,并设置压缩模式减少token使用:

// 创建索引后构建查询引擎
const index = await VectorStoreIndex.fromDocuments(splitDocuments, { storageContext });
const queryEngine = index.asQueryEngine({
  similarityTopK: 5, // 召回前5个最相关的chunk,根据需求调整
  responseMode: "compact", // 压缩召回内容,减少输入token数
});

// 执行查询
const response = await queryEngine.query("请统计某列的平均值");
console.log(response.response);

方式二:使用PandasQueryEngine处理结构化数据

如果CSV是标准表格,用PandasQueryEngine直接基于结构化数据查询,效率更高且无需拆分文本:

import { PandasQueryEngine, OpenAI } from "llamaindex";
import pandas from "pandas-js";

// 将CSV转为DataFrame
const df = pandas.read_csv("./path/to/large.csv");

// 初始化Pandas查询引擎
const queryEngine = new PandasQueryEngine({
  pandasDF: df,
  llm: new OpenAI({ model: "gpt-4-turbo" }),
});

// 执行SQL-like查询
const response = await queryEngine.query("计算所有行中'销售额'列的总和");
console.log(response.response);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 05:39:53