---
title: "DataFrames for an LLM"
newsletter: "MLOps Community"
date: 2025-08-05
source: https://aaif.live/newsletters/mlopscommunity/2025-08-05-dataframes-for-an-llm
---

# DataFrames for an LLM

*Declarative LLM ops without the boilerplate*

*MLOps Community — Agentic AI Foundation, 2025-08-05*

CTOs everywhere just sighed with relief after hearing Musk’s getting $29B from Tesla [https://go.mlops.community/intro5aug] to stick around for the “AI talent war.”

## Preview:

TUESDAY TOOL REVIEW - FENIC: DATAFRAMES FOR AN LLM WORLD
BY STEPHEN OLADELE [https://www.linkedin.com/in/stephenoladele/]



Preview:

Fenic turns LLM calls into first-class DataFrame ops (semantic.map, classify, extract, join). PySpark vibes, Arrow under the hood, Rust speed… but also a young ecosystem with sharp edges (maturing, install quirks). Is it ready for your prod pipelines?

Fenic just went public on GitHub (★ ~165, Apache 2.0, v0.2.1 [https://github.com/typedef-ai/fenic/releases/tag/v0.2.1], July, 2025). The goal: treat LLM inference as a first-class DataFrame primitive, so everything from paraphrasing to schema extraction looks like a familiar df.select().

⏩ TL;DR

 * What it is: An OSS, PySpark-inspired DataFrame engine where LLM inference is a column operation (map/classify/extract/semantic.join).
 * Why it matters: Collapses “data prep + batch inference + eval” into one declarative API; no more bolting Python scripts onto ETL.
 * Sweet spots: Rapid dataset augmentation, structured extraction to Pydantic schemas, semantic joins for RAG, eval/lineage baked in.
 * Watch-outs: Early project (June 2025), Rust toolchain required, docs still thin, limited ecosystem support and integrations.
 * Verdict (4/5): Great fit if you live in DataFrames and need LLM infra but might be overkill if simple SDK calls suffice.


WHAT IS FENIC?

“Think pandas/Polars, but with semantic.extract, semantic.join, semantic.map baked in.” — Kostas Pardalis, Fenic creator (MLOps Slack launch thread [https://mlops-community.slack.com/archives/C018E4N2H9V/p1752102040389509]).

Under the hood, Fenic is an opinionated, PySpark-inspired query engine built from scratch for AI and agentic applications.

Fenic treats LLM workflows as built-in DataFrame primitives instead of attaching them to external systems. This approach might make it much easier to build and run your workflows.

Here are the primary selling points:

 * Semantic operators (analyze_sentiment, classify, extract, group_by, join, predicate) are first-class.
 * Native unstructured types: Markdown, transcripts, JSON, long-form text with auto-chunking.
 * Batch and retry layer with token counting and cost metrics built-in.
 * Multi-provider (OpenAI, Anthropic, Gemini) and local / cloud execution modes.
 * Familiar API: lazy DataFrame, SQL support, PySpark-like chaining
 * Languages: Python 87%, Rust 13%. Rust core already powers Arrow-native execution, with design choices influenced by Polars for speed and efficiency.

Wes McKinney (pandas creator) publicly endorsed the concept [https://www.typedef.ai/] (“a natural evolution of the DataFrame abstraction”).


⚙️ KEY FEATURES (WHY IT’S NOT JUST PANDAS + API LOOPS)

https://github.com/typedef-ai/fenichttps://github.com/typedef-ai/fenic https://github.com/typedef-ai/fenichttps://github.com/typedef-ai/fenic

⚡ Quick Spin-Up: Podcast → Segments → Extract → Summaries (Fenic)

Here’s a quick example of how to analyze and extract summaries from a podcast episode with Fenic:

Python pip install fenic # Python 3.10-3.12, Fenic v0.2.1 export OPENAI_API_KEY=... # Add your Op # ------------------------- from pathlib import Path from pydantic import BaseModel, Field import fenic as fc # 1. ---- Define schemas for structured extraction ---- class SegmentSchema(BaseModel): speaker: str = Field(description="Who is talking in this segment") start_time: float = Field(description="Start time (seconds)") end_time: float = Field(description="End time (seconds)") key_points: list[str] = Field(description="Bullet points for this segment") class EpisodeSummary(BaseModel): title: str guests: list[str] main_topics: list[str] actionable_insights: list[str] # 2. ---- Init a Fenic session with a model alias ---- config = fc.SessionConfig( app_name="podcast_quickspin", semantic=fc.SemanticConfig( language_models={ "mini": fc.OpenAIModelConfig(model_name="gpt-4o-mini", rpm=300, tpm=150_000) } ), ) session = fc.Session.get_or_create(config) # 3. ---- Load raw transcript/metadata as strings ---- data_dir = Path("data") # put your JSON/text here transcript_text = (data_dir / "transcript.json").read_text() meta_text = (data_dir / "meta.json").read_text() df = fc.DataFrame({"meta": [meta_text], "transcript": [transcript_text]}) # 4. ---- Extract structured metadata & segment the transcript ---- processed = ( df.select( "*", fc.semantic.extract("meta", EpisodeSummary, model="mini").alias("episode"), fc.semantic.chunk("transcript", max_tokens=1200).alias("chunks"), ) .explode("chunks") .select( fc.col("chunks").alias("chunk"), fc.semantic.extract("chunk", SegmentSchema, model="mini").alias("segment"), ) ) # 5. ---- Abstractive recap per speaker/segment & global summary ---- final = ( processed .select("*", fc.semantic.map( "Summarize this segment in 2 sentences:\n{chunk}", model="mini" ).alias("segment_summary") ) .group_by(fc.col("segment.speaker")) .agg( fc.semantic.map( "Combine these summaries into one clear paragraph:\n{segment_summary}", model="mini" ).alias("speaker_summary") ) ) final.show(truncate=120) # Optional: write to parquet/csv final.write.parquet("podcast_summaries.parquet") session.stop()


TIPS TO ADAPT QUICKLY

 * Different providers: swap OpenAIModelConfig for AnthropicModelConfig, etc.
 * Bigger files: bump max_tokens or chunk size; Fenic batches/streams for you.
 * Eval pass: add another select() with a classifier prompt to tag “quality: good/needs fix”.
 * Cost guardrails: set max_tokens_per_call or inspect session.metrics() after run.
 * Need a variant for YouTube transcripts or research PDFs? Just change the loader and schemas—the pipeline shape stays identical.


WHY YOU SHOULD CARE

 * Declarative pipelines → push your ETL and inference into the same DAG.
 * Cheaper evaluation loops → token and cost metrics are first-class.
 * Semantic joins → fuzzy “does this paper help my research question?” join in one line via semantic.join
 * Structured extraction to Pydantic → easier downstream analytics, eval & labeling.
 * Agent synergy → pre-batch heavy reasoning offline, feed lean contexts to online agents.


GOTCHAS AND CAVEATS

 1. Toolchain friction: Installing Fenic via pip is straightforward, but developing new features requires the Rust toolchain (rustc, cargo, maturin), which isn’t fully documented yet.
 2. Young ecosystem: Core support includes Arrow, CSV, and Parquet, with native connectors for Snowflake, BigQuery, and S3 expected soon.
 3. Operational maturity: No proven large-scale benchmarks published; cloud engine still alpha [https://www.typedef.ai/blog/typedef-launch].
 4. Docs still sparse: docs.fenic.ai exists but is thin; many API details live only in README/examples. A more structured documentation system is in the works, with an MCP-backed server already in progress.
 5. Single-node today: no distributed executor yet; large corpora need chunked runs or Spark/Polars fallback.


📊 FENIC VS. COMMON ALTERNATIVES (AS OF JULY 2025)

Legend: ✅ robust & built-in · ⚠️ partial/indirect · ❌ absent


🧑‍⚖️ FINAL VERDICT: 4/5


RATING: ⭐⭐⭐⭐☆ (4/5)

Fenic nails a gap nobody else covers: treating LLM inference as a native DataFrame primitive. If your team already loves SQL/PySpark and spends hours duct-taping looped API calls, Fenic will feel like a super-power.

Ship it if…

 * You batch-process lots of text and need semantic joins/extractions weekly.
 * You’re prototyping an RAG/agent pipeline and want repeatable, cost-aware ETL.
 * You can tolerate early-project rough edges and contribute fixes upstream.

Hold off if…

 * You need petabyte-scale, distributed compute today.
 * Your workloads are real-time, sub-second.
 * You require enterprise auth/row-level security out of the box.

📌 More Resources

 * Docs and Quickstarts → https://docs.fenic.ai/latest/
 * GitHub repo (Apache-2.0) → https://github.com/typedef-ai/fenic
 * Blog intro (“PySpark-inspired DataFrame for AI”) (June 18, 2025) → https://www.typedef.ai/blog/fenic-open-source
 * Example gallery → examples/ [https://github.com/typedef-ai/fenic/blob/main/examples] folder on GitHub
 * Author Q&A in MLOps Slack → link [https://mlops-community.slack.com/archives/C018E4N2H9V/p1752102040389509]

Love this review? Forward it to your fellow data and MLOps friends, or share on X with #TuesdayToolReview and tag @mlopscommunity

Want deeper tutorials? Subscribe to The Neural Blueprint [https://neurlcreators.substack.com/] for hands-on guides! 🫡

Working on something tricky or planning ahead? Here’s how we can help - just hit reply:

 * Custom workshops tailored to your company’s needs
 * Hiring? I know some quality folks looking for a new adventure
 * Want to connect with someone tackling similar problems? I can introduce you

Thanks for reading, catch you next time!

Interested in partnering with us? Get in touch: partners@mlops.community

Thanks for reading. See you in Slack [https://go.mlops.community/slack], YouTube [https://www.youtube.com/channel/UCG6qpjVnBTTT8wLGBygANOQ?view_as=subscriber], and podcast [https://home.mlops.community/public/content/] land. Oh yeah, and we are also on X [https://twitter.com/mlopscommunity] and LinkedIn [https://go.mlops.community/linkedin].

Thanks again to Stephen Oladele [https://www.linkedin.com/in/stephenoladele/] for his contribution.

---
Source: https://aaif.live/newsletters/mlopscommunity/2025-08-05-dataframes-for-an-llm
