npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

csv-charts-ai

v1.14.1

Published

AI-powered CSV analysis, chart generation, and interactive visualization. Parse CSV, detect anomalies, suggest charts, and ask questions about your data using any LLM provider.

Readme

csv-charts-ai

AI-powered CSV analysis, chart generation, and interactive visualization. Built on the Vercel AI SDK and Recharts.

Works with any LLM provider — OpenAI, Anthropic, Google, Mistral, Ollama, or any OpenAI-compatible endpoint.

Installation

pnpm add csv-charts-ai

Then install only the AI provider(s) you need:

# Pick one or more
pnpm add @ai-sdk/openai      # OpenAI / OpenAI-compatible (Ollama, vLLM, LM Studio…)
pnpm add @ai-sdk/anthropic    # Anthropic
pnpm add @ai-sdk/google       # Google Generative AI
pnpm add @ai-sdk/mistral      # Mistral

Core dependencies (ai, zod, read-excel-file) are bundled. AI provider SDKs are optional peer dependencies — you only install what you use.

Optional peer dependencies (only for React chart components): react, recharts, lucide-react.

Quick Start

import { registerProvider, fromSDK, parseCSV, analyzeData, suggestQuestions } from "csv-charts-ai";
import { createOpenAI } from "@ai-sdk/openai";

// 1. Register your provider(s) — once, at app startup
registerProvider("openai", fromSDK(createOpenAI));

// 2. Parse CSV string into structured data
const data = parseCSV(`name,age,city,salary
Alice,30,Paris,75000
Bob,25,London,62000
Charlie,35,Berlin,88000`);

// 3. Run full AI analysis (summary + anomalies + charts) in parallel
const result = await analyzeData({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
});

console.log(result.summary.keyInsights);
console.log(`Found ${result.anomalies.length} anomalies`);
console.log(`Generated ${result.charts.length} chart suggestions`);

// 4. Suggest questions the user could ask
const questions = await suggestQuestions({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
});
questions.forEach(q => console.log(`[${q.category}] ${q.question}`));

Provider Setup

Register AI providers once at app startup, before calling any AI function. You only install and register the providers you need.

Using @ai-sdk/* packages

The fromSDK() helper wraps any @ai-sdk/* creator into the format the library expects:

import { registerProvider, fromSDK } from "csv-charts-ai";
import { createOpenAI } from "@ai-sdk/openai";
import { createAnthropic } from "@ai-sdk/anthropic";
import { createGoogleGenerativeAI } from "@ai-sdk/google";
import { createMistral } from "@ai-sdk/mistral";

registerProvider("openai", fromSDK(createOpenAI));
registerProvider("anthropic", fromSDK(createAnthropic));
registerProvider("google", fromSDK(createGoogleGenerativeAI));
registerProvider("mistral", fromSDK(createMistral));

Custom / self-hosted providers

For full control, pass a ProviderFactory directly — a function that receives { apiKey, model, baseURL?, headers? } and returns a LanguageModel:

import { registerProvider } from "csv-charts-ai";

registerProvider("my-llm", (config) => {
  return myCustomSDK.createModel(config.apiKey, config.model);
});

Batch registration

import { registerProviders, fromSDK } from "csv-charts-ai";
import { createOpenAI } from "@ai-sdk/openai";
import { createAnthropic } from "@ai-sdk/anthropic";

registerProviders({
  openai: fromSDK(createOpenAI),
  anthropic: fromSDK(createAnthropic),
});

Aliases

npm package names are resolved automatically — "@ai-sdk/openai" and "openai" map to the same slot. So createModel({ provider: "openai" }) and createAppModel({ providerNpm: "@ai-sdk/openai" }) both work after a single registration.

CSV Parsing

Parse CSV strings into the TabularData format with automatic delimiter detection and column type inference.

import { parseCSV } from "csv-charts-ai";

// Auto-detects delimiter (comma, semicolon, tab, pipe)
const data = parseCSV(csvString);

// Explicit options
const data = parseCSV(csvString, {
  delimiter: ";",
  hasHeader: true,
  skipEmpty: true,
});

console.log(data.headers);   // ["name", "age", "city"]
console.log(data.rowCount);  // 100
console.log(data.columns);   // [{ name: "name", type: "string", index: 0 }, ...]

Type inference detects string, number, date, and boolean columns by sampling values. Handles quoted fields, escaped quotes, multi-line values, and BOM stripping (RFC 4180).

For very large files or exotic encodings, consider using PapaParse and passing the result as TabularData directly.

XLSX Parsing

Parse Excel (.xlsx) files into the same TabularData format. read-excel-file is bundled.

Browser

import { parseXLSX } from "csv-charts-ai";

const data = await parseXLSX(file); // File from <input> or drag-and-drop
console.log(data.headers, data.rowCount);

Node.js / Universal

Use convertXLSXRows with any XLSX reader — it takes raw row arrays and has zero dependencies:

import readXlsxFile from "read-excel-file/node";
import { convertXLSXRows } from "csv-charts-ai";

const rows = await readXlsxFile("data.xlsx");
const data = convertXLSXRows(rows);

Options: { hasHeader?: boolean, skipEmpty?: boolean } — same defaults as parseCSV.

AI Functions

All AI functions accept either a simple config object or a pre-built LanguageModel from the Vercel AI SDK. All support an optional signal (AbortSignal) for cancellation.

Chart Suggestions

import { suggestCharts } from "csv-charts-ai";

// Simple — OpenAI (provider must be registered, see Provider Setup)
const charts = await suggestCharts({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
});

// Custom endpoint — Ollama / vLLM / LM Studio (uses the "openai" provider)
const charts = await suggestCharts({
  model: { apiKey: "", model: "llama3", baseURL: "http://localhost:11434/v1" },
  data,
});

// Other providers — Anthropic, Google, Mistral
const charts = await suggestCharts({
  model: { apiKey: "sk-ant-...", model: "claude-sonnet-4-20250514", provider: "anthropic" },
  data,
});

// Advanced — any LanguageModel instance (no registration needed)
import { createAnthropic } from "@ai-sdk/anthropic";
const anthropic = createAnthropic({ apiKey: "sk-ant-..." });
const charts = await suggestCharts({
  model: anthropic("claude-sonnet-4-20250514"),
  data,
  language: "French",
});

Custom Chart from Prompt

import { suggestCustomChart } from "csv-charts-ai";

const chart = await suggestCustomChart({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
  prompt: "Show me a bar chart of revenue by category",
});

Repair a Broken Chart

import { repairChart } from "csv-charts-ai";

const fixed = await repairChart({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  failedChart: brokenChart,
  columns: ["name", "sales", "date"],
  errorContext: "Column 'revenue' does not exist",
});

Data Summary

import { summarizeData } from "csv-charts-ai";

const result = await summarizeData({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
});

console.log(result.summary);      // "This dataset contains sales records..."
console.log(result.keyInsights);   // ["Revenue peaks in Q4", "Product A leads..."]
console.log(result.dataQuality);   // "Good completeness, 2 missing values in..."

Anomaly Detection

import { detectAnomalies } from "csv-charts-ai";

const anomalies = await detectAnomalies({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
  maxRows: 100, // default: 50
});

anomalies.forEach(a =>
  console.log(`[${a.severity}] Row ${a.row}, ${a.column}: ${a.issue}`)
);

Ask Questions About Data

import { askAboutData, streamAskAboutData } from "csv-charts-ai";

// Non-streaming
const answer = await askAboutData({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
  question: "What is the average revenue by region?",
  history: [{ prompt: "How many rows?", response: "There are 1000 rows." }],
});

// Streaming
await streamAskAboutData({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
  question: "What trends do you see?",
  onChunk: (chunk) => process.stdout.write(chunk),
  onComplete: (full) => console.log("\nDone:", full.length, "chars"),
});

Suggest Questions

import { suggestQuestions } from "csv-charts-ai";

const questions = await suggestQuestions({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
  count: 5,
});

questions.forEach(q => console.log(`[${q.category}] ${q.question}`));
// [trend] How has revenue changed month over month?
// [comparison] Which region has the highest average order value?
// [correlation] Is there a relationship between marketing spend and sales?

Full Analysis Pipeline

Runs summary, anomaly detection, and chart suggestions in parallel:

import { analyzeData } from "csv-charts-ai";

const result = await analyzeData({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
  detectAnomalies: true,  // default: true
  suggestCharts: true,    // default: true
});

// result.summary   — DataSummaryResult
// result.anomalies — AnomalyResult[]
// result.charts    — ChartConfig[]

Cancellation (AbortSignal)

All AI functions support signal for cancellation — essential for React cleanup and timeouts:

const controller = new AbortController();

const charts = await suggestCharts({
  model: { apiKey: "sk-...", model: "gpt-4o" },
  data,
  signal: controller.signal,
});

// Cancel from elsewhere
controller.abort();

React example:

useEffect(() => {
  const controller = new AbortController();
  analyzeData({ model, data, signal: controller.signal })
    .then(setResult)
    .catch(() => {});
  return () => controller.abort();
}, [data]);

React Components (csv-charts-ai/charts)

Chart components are available as a separate entry point so projects that only need AI/parsing don't pull in React or Recharts.

# Optional peer dependencies — only needed if you import from csv-charts-ai/charts
pnpm add react recharts

Icons are built-in (SVG, zero dependency). To use your own icon library, see Custom Icons below.

Display Charts

import { ChartDisplay } from "csv-charts-ai/charts";

<ChartDisplay data={data} charts={charts} />

With Theme

import { ChartDisplay, defaultLightTheme } from "csv-charts-ai/charts";

<ChartDisplay data={data} charts={charts} theme={defaultLightTheme} />

Custom Card Wrapper

import { ChartDisplay } from "csv-charts-ai/charts";
import { repairChart } from "csv-charts-ai";

<ChartDisplay
  data={data}
  charts={charts}
  cardWrapper={({ children, title }) => (
    <div className="my-card">
      <h2>{title}</h2>
      {children}
    </div>
  )}
  onRegenerate={async (chart) => {
    const fixed = await repairChart({ model, failedChart: chart, columns: data.headers, errorContext: "Rendering failed" });
    // update state with fixed chart
  }}
/>

Unstyled Mode (No Tailwind Required)

Pass unstyled to strip all built-in Tailwind classes and style components yourself:

<ChartDisplay
  data={data}
  charts={charts}
  unstyled
  className="my-charts-container"
  chartClassName="my-chart-card"
  titleClassName="my-chart-title"
/>

You can also pass className to any component to add classes alongside the built-in ones:

<ChartDisplay data={data} charts={charts} className="my-extra-class" />

Custom Icons

Chart toolbar icons are built-in as minimal SVGs (zero dependency). To use your own icon library (lucide-react, heroicons, phosphor, etc.), wrap your charts with ChartIconProvider:

import { ChartDisplay, ChartIconProvider } from "csv-charts-ai/charts";
import { RefreshCw, Download, ArrowUp, ArrowDown, RotateCcw, TrendingUp, Filter, Image } from "lucide-react";

const icons = { RefreshCw, Download, SortAsc: ArrowUp, SortDesc: ArrowDown, RotateCcw, TrendingUp, Filter, ImageIcon: Image };

<ChartIconProvider icons={icons}>
  <ChartDisplay data={data} charts={charts} />
</ChartIconProvider>

You only need to override the icons you want to change — the rest fall back to the built-in SVGs.

Headless Usage (No React)

The core entry point (csv-charts-ai) works without React — use it in Node.js scripts, APIs, or CLI tools:

import { registerProvider, fromSDK, parseCSV, analyzeData } from "csv-charts-ai";
import { createOpenAI } from "@ai-sdk/openai";
import { readFileSync } from "fs";

registerProvider("openai", fromSDK(createOpenAI));

const csv = readFileSync("sales.csv", "utf-8");
const data = parseCSV(csv);

const result = await analyzeData({
  model: { apiKey: process.env.OPENAI_API_KEY!, model: "gpt-4o" },
  data,
});

console.log(result.summary.keyInsights);

Components Reference (csv-charts-ai/charts)

| Export | Description | |--------|-------------| | ChartDisplay | Multi-chart container with optional card wrapper and theme | | SingleChart | Individual chart with toolbar (sort, zoom, trendline, CSV/PNG export) | | ChartToolbar | Standalone toolbar component | | ChartThemeProvider | React context for chart theming | | ChartIconProvider | React context for pluggable icons (default: built-in SVGs) | | defaultDarkTheme / defaultLightTheme | Built-in themes | | defaultIcons | Built-in SVG icon set |

AI Functions Reference

| Export | Description | |--------|-------------| | suggestCharts(options) | Generate 2-4 chart suggestions from data | | suggestCustomChart(options) | Generate a single chart from a text prompt | | repairChart(options) | Fix a chart config that failed to render | | summarizeData(options) | AI-generated data summary with key insights | | detectAnomalies(options) | Find outliers, missing values, type mismatches | | askAboutData(options) | Ask natural language questions about data | | streamAskAboutData(options) | Streaming version of askAboutData | | suggestQuestions(options) | Suggest interesting questions to ask about the data | | analyzeData(options) | Full pipeline: summary + anomalies + charts in parallel |

Provider Registry Reference

| Export | Description | |--------|-------------| | registerProvider(name, factory) | Register a provider by name | | registerProviders(map) | Register multiple providers at once | | fromSDK(creator) | Wrap an @ai-sdk/* creator into a ProviderFactory | | getProvider(name) | Get a registered provider (or undefined) | | hasProvider(name) | Check if a provider is registered | | clearProviders() | Remove all registered providers (for testing) |

Utilities Reference

| Export | Description | |--------|-------------| | parseCSV(csv, options?) | Parse CSV string into TabularData | | parseXLSX(file, options?) | Parse XLSX file into TabularData (browser) | | convertXLSXRows(rows, options?) | Convert raw XLSX rows into TabularData (universal) | | computeDiff(dataA, dataB, options) | Compare two datasets (index, key, or content matching) | | createModel(config) | Create a LanguageModel from an AIConfig | | createAppModel(config) | Create a LanguageModel from multi-provider app config | | resolveModel(input) | Resolve AIConfig, AppModelConfig, or LanguageModel | | generateDataSummary(data) | Detailed human-readable data summary with sample rows | | summarizeTabularData(data) | Compact data summary for AI prompt consumption | | getAIErrorMessage(error) | Extract user-friendly error messages | | processChartData(data, chart) | Process and aggregate chart data | | processChartDataMultiSeries(data, chart) | Multi-series data processing | | COLORS | Default 8-color palette |

Validation Schemas

| Export | Description | |--------|-------------| | AIConfigSchema | Zod schema for validating AI config objects | | TabularDataSchema | Zod schema for validating TabularData input |

Chart Types

bar | line | area | scatter | pie

Multi-series supported via groupBy for bar, line, and area charts.

Aggregation Types

sum | avg | count | min | max | none

CSV Diff

Compare two datasets and detect added, removed, and changed rows:

import { computeDiff } from "csv-charts-ai";

const diff = computeDiff(dataA, dataB, { matchMode: "key", keyColumn: "id" });

console.log(diff.counts); // { same: 10, changed: 3, added: 2, removed: 1 }
diff.rows.forEach(r => {
  if (r.status === "changed") {
    console.log(`Row ${r.indexA}: changed columns: ${[...r.changedCols].join(", ")}`);
  }
});

Match modes: "index" (positional), "key" (by column value), "content" (full row match).

Provider Support

Install only the provider(s) you need and register them at startup (see Provider Setup).

| Provider | Install | Config | |----------|---------|--------| | OpenAI | @ai-sdk/openai | { apiKey, model } | | Anthropic | @ai-sdk/anthropic | { provider: "anthropic", apiKey, model } | | Google | @ai-sdk/google | { provider: "google", apiKey, model } | | Mistral | @ai-sdk/mistral | { provider: "mistral", apiKey, model } | | Ollama / vLLM / LM Studio | @ai-sdk/openai | { apiKey: "", model, baseURL } | | Custom provider | — | registerProvider("name", factory) | | Any LanguageModel | — | Pass instance directly |

License

MIT