Back to roadmaps langchain Course

Project: CSV Table Querying Chatbot

In this project, we will build a CSV-querying chatbot. The pipeline parses a local store product CSV file, indexes the rows into a vector database, and uses an LCEL chain to answer user questions about product pricing.


1. Project Workflow

graph TD
    A[products.csv file] -->|CSVLoader| B[Document items]
    B -->|MemoryVectorStore| C[Indexed Vector DB]
    D[User: How much does item A cost?] -->|Retriever| C
    C -->|Top matches| E[Prompt builder]
    E -->|gpt-4o-mini| F[Final answer text reply]

2. Implementing the CSV Query Engine

Create the full service module that chains retrieval and text completions:

// src/services/csvBot.ts
import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai";
import { CSVLoader } from "@langchain/community/document_loaders/fs/csv";
import { MemoryVectorStore } from "langchain/vectorstores/memory";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { StringOutputParser } from "@langchain/core/output_parsers";
import { RunnablePassthrough, RunnableSequence } from "@langchain/core/runnables";

// 1. Create a helper to format retrieved documents list into a raw string
function formatDocuments(docs: any[]) {
  return docs.map((d) => d.pageContent).join("\n---\n");
}

export async function queryCsvCatalog(csvFilePath: string, userQuery: string) {
  // 2. Load CSV records
  const loader = new CSVLoader(csvFilePath);
  const rawDocs = await loader.load();

  // 3. Setup embeddings and index in MemoryVectorStore
  const embeddings = new OpenAIEmbeddings({ modelName: "text-embedding-3-small" });
  const vectorStore = await MemoryVectorStore.fromDocuments(rawDocs, embeddings);
  const retriever = vectorStore.asRetriever({ k: 3 });

  // 4. Declare the prompt template
  const prompt = ChatPromptTemplate.fromMessages([
    [
      "system",
      "You are a sales inventory helper. Answer customer questions based on these CSV records:\n\n{context}"
    ],
    ["user", "{userInput}"]
  ]);

  const model = new ChatOpenAI({ modelName: "gpt-4o-mini", temperature: 0.1 });
  const parser = new StringOutputParser();

  // 5. Compose the LCEL pipeline sequence
  const queryChain = RunnableSequence.from([
    {
      // Retrieve documents and pipe them to format helper
      context: retriever.pipe(formatDocuments),
      userInput: new RunnablePassthrough()
    },
    prompt,
    model,
    parser
  ]);

  // 6. Invoke the pipeline
  const answer = await queryChain.invoke(userQuery);
  return answer;
}

3. Creating Mock Data and Executing

Create a mock data file named products.csv:

id,name,price,description
1,Wireless Mouse,29.99,Ergonomic battery powered 2.4Ghz computer mouse.
2,Mechanical Keyboard,89.99,RGB backlit mechanical switches typing keyboard.
3,Noise Canceling Headphones,199.99,Bluetooth over-ear active noise canceling headphones.

Call the query helper:

const answer = await queryCsvCatalog("./products.csv", "What is the price of the keyboard?");
console.log("Chatbot response:", answer); // Output: The price of the Mechanical Keyboard is $89.99.
Published on Last updated: