<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yashvardhan Thanvi</title>
    <description>The latest articles on DEV Community by Yashvardhan Thanvi (@yashvardhan_thanvi_6762e7).</description>
    <link>https://dev.to/yashvardhan_thanvi_6762e7</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4035868%2F4e58f434-01c4-431c-b790-212fd74c1f08.jpg</url>
      <title>DEV Community: Yashvardhan Thanvi</title>
      <link>https://dev.to/yashvardhan_thanvi_6762e7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yashvardhan_thanvi_6762e7"/>
    <language>en</language>
    <item>
      <title>Building LLMSlim: Architecture Deep-Dive into Deterministic Prompt Compression</title>
      <dc:creator>Yashvardhan Thanvi</dc:creator>
      <pubDate>Sat, 18 Jul 2026 22:23:27 +0000</pubDate>
      <link>https://dev.to/yashvardhan_thanvi_6762e7/building-llmslim-architecture-deep-dive-into-deterministic-prompt-compression-2ip0</link>
      <guid>https://dev.to/yashvardhan_thanvi_6762e7/building-llmslim-architecture-deep-dive-into-deterministic-prompt-compression-2ip0</guid>
      <description>&lt;p&gt;Most prompt compression discussions focus on the happy path: you have a long RAG context, you trim it to 50% of tokens, and your API bill halves. What rarely gets discussed are the failure modes: dropped system instructions, truncated JSON schemas, broken code fences, and entity names that get quietly pruned because they scored low in some similarity metric.&lt;/p&gt;

&lt;p&gt;LLMSlim (&lt;a href="https://www.llmslim.app" rel="noopener noreferrer"&gt;https://www.llmslim.app&lt;/a&gt;) is a Python library I've spent the last few months building to handle these edge cases properly. This post goes deep on the architecture decisions that make it work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Problem: Information vs. Filler
&lt;/h2&gt;

&lt;p&gt;LLM input prompts have a structural problem. The instructions that govern model behavior (system roles, JSON schemas, MUST/NEVER directives) are typically a tiny fraction of the total token count. The rest is context: retrieved documents, conversation history, background information. And within that context, a significant fraction is prose that exists for human readability, not informational density.&lt;/p&gt;

&lt;p&gt;The challenge is distinguishing high-value informational sentences from low-value filler without a model call, without embeddings, and in under 30ms.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 6-Step Pipeline
&lt;/h2&gt;

&lt;p&gt;LLMSlim processes prompts through a deterministic DAG (Directed Acyclic Graph) with six stages:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Protected Sentence Splitting
&lt;/h3&gt;

&lt;p&gt;Naive sentence splitting on periods breaks code blocks and URLs. The first stage uses regex-based splitting that respects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AST code fences (triple backticks) - treated as atomic units&lt;/li&gt;
&lt;li&gt;Markdown heading markers&lt;/li&gt;
&lt;li&gt;URLs (no splitting on periods within URLs)&lt;/li&gt;
&lt;li&gt;Common abbreviations (e.g., U.S., etc.)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Pseudocode: core split logic
&lt;/span&gt;&lt;span class="n"&gt;sentences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;regex_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentences&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_code_fence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sent&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;protected&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;  &lt;span class="c1"&gt;# immune to scoring
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. TF-IDF Vector Graph Construction
&lt;/h3&gt;

&lt;p&gt;Each sentence becomes a TF-IDF vector. We compute the full pairwise cosine similarity matrix over these vectors to build a weighted undirected graph where edge weight(i,j) = cosine_similarity(v_i, v_j).&lt;/p&gt;

&lt;p&gt;The choice of TF-IDF over neural embeddings was deliberate. TF-IDF runs in microseconds per sentence. It captures vocabulary overlap well, which is exactly what matters for identifying redundant prose. Neural embeddings add 50-100ms of latency and model loading overhead that isn't justified for this task.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. LexRank Centrality Scoring
&lt;/h3&gt;

&lt;p&gt;We apply the LexRank algorithm: convert the similarity graph to a stochastic transition matrix M, then find the stationary distribution via power iteration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p_t+1 = d * M * p_t + (1-d) / n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where d is a damping factor (typically 0.85) and n is the sentence count. Convergence typically happens in 20-30 iterations. The resulting stationary probability vector gives each sentence a centrality score representing how informationally central it is to the document.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Priority Tier Hard Locking
&lt;/h3&gt;

&lt;p&gt;This is the stage that separates LLMSlim from naive extraction approaches. Before any sentence can be pruned, a deterministic rule pass classifies every sentence into one of four tiers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tier 4 (Inviolable)&lt;/strong&gt;: Sentences containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Role markers: &lt;code&gt;system:&lt;/code&gt;, &lt;code&gt;developer:&lt;/code&gt;, &lt;code&gt;user:&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Imperative keywords: &lt;code&gt;MUST&lt;/code&gt;, &lt;code&gt;NEVER&lt;/code&gt;, &lt;code&gt;ALWAYS&lt;/code&gt;, &lt;code&gt;REQUIRED&lt;/code&gt;, &lt;code&gt;DO NOT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;JSON/XML schema delimiters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tier 3 (Protected)&lt;/strong&gt;: Sentences containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Numerical entities (currency, percentages, measurements)&lt;/li&gt;
&lt;li&gt;Proper nouns and named entities&lt;/li&gt;
&lt;li&gt;URL references&lt;/li&gt;
&lt;li&gt;Code identifiers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tier 2 (Standard)&lt;/strong&gt;: Regular content sentences&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tier 1 (Candidate for removal)&lt;/strong&gt;: Filler phrases, transition sentences&lt;/p&gt;

&lt;p&gt;Tier 4 sentences are hardcoded to survive the compression pass regardless of their LexRank score. A sentence saying "You MUST respond only in JSON" will score low in a document full of prose paragraphs - but it's the most important sentence in the prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Two-Pass Budget Allocation
&lt;/h3&gt;

&lt;p&gt;Pass 1 divides the document into semantic chunks and allocates token budgets proportionally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chunk_budget_i = target_tokens * (chunk_tokens_i / total_tokens)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass 2 applies a global rebalancing step. Each chunk may have selected sentences that, together, slightly exceed or undershoot its budget. The second pass collects the surplus/deficit across all chunks and redistributes tokens using a priority-aware greedy knapsack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sort remaining unselected sentences by (tier, lexrank_score) descending&lt;/li&gt;
&lt;li&gt;Greedily include sentences until global token target is hit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This two-pass approach is why the library consistently hits within 2-3% of the target ratio even on highly variable document structures.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Ordered Reassembly
&lt;/h3&gt;

&lt;p&gt;Selected sentences are sorted by their original document position and concatenated. Original ordering is preserved because causal reasoning and logical flow in documents depends on sequence, not just content.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hybrid Strategy (v0.3.0)
&lt;/h2&gt;

&lt;p&gt;v0.3.0 adds a generative compression layer on top of the extractive pipeline. The flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extractive pre-pruning reduces the context to ~130% of target (intentionally slightly over)&lt;/li&gt;
&lt;li&gt;A RewriteRequest is passed to a pluggable CallableProvider&lt;/li&gt;
&lt;li&gt;The LLM rewrites the pre-pruned context targeting the final ratio&lt;/li&gt;
&lt;li&gt;A validation pass checks that all Tier 4 sentences survived&lt;/li&gt;
&lt;li&gt;If validation fails, the extractive output is returned as fallback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pluggable provider model means you don't need a specific LLM API key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llmslim&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;compress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CallableProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RewriteRequest&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RewriteRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# req.system_prompt, req.user_prompt, req.target_ratio all available
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;your_llm_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CallableProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_ratio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hybrid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benchmarks
&lt;/h2&gt;

&lt;p&gt;All benchmarks are reproducible. Hardware: AMD EPYC 7763, 64GB RAM, Ubuntu 24.04, Python 3.12.3, tiktoken cl100k_base. N=500 prompts per dataset, 100 iterations per sample.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dataset&lt;/th&gt;
&lt;th&gt;Token Reduction&lt;/th&gt;
&lt;th&gt;Latency (mean)&lt;/th&gt;
&lt;th&gt;Directive Retention&lt;/th&gt;
&lt;th&gt;Entity Preservation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System Directives&lt;/td&gt;
&lt;td&gt;51.4% ± 1.2%&lt;/td&gt;
&lt;td&gt;24.8ms ± 2.1ms&lt;/td&gt;
&lt;td&gt;100.0%&lt;/td&gt;
&lt;td&gt;95.1% ± 1.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50k Context (GPT-5)&lt;/td&gt;
&lt;td&gt;55.0% ± 1.1%&lt;/td&gt;
&lt;td&gt;26.0ms ± 2.4ms&lt;/td&gt;
&lt;td&gt;100.0%&lt;/td&gt;
&lt;td&gt;94.9% ± 1.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XML Mode (Claude 3.5)&lt;/td&gt;
&lt;td&gt;50.0% ± 0.8%&lt;/td&gt;
&lt;td&gt;24.0ms ± 1.9ms&lt;/td&gt;
&lt;td&gt;100.0%&lt;/td&gt;
&lt;td&gt;96.4% ± 0.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100k RAG (Gemini)&lt;/td&gt;
&lt;td&gt;65.0% ± 1.3%&lt;/td&gt;
&lt;td&gt;38.0ms ± 3.1ms&lt;/td&gt;
&lt;td&gt;100.0%&lt;/td&gt;
&lt;td&gt;94.8% ± 1.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What Didn't Work
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Attempt 1: Pure TF-IDF cutoff.&lt;/strong&gt; Setting a similarity threshold and dropping sentences below it sounds simple. In practice, document sections with specialized vocabulary score low across the board even when they contain critical information. Threshold tuning became document-specific.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attempt 2: Summarization for compression.&lt;/strong&gt; Running a smaller model to summarize chunks seems appealing. It adds a full model inference call (50-500ms), requires an API dependency, and summaries tend to drop entity specifics that matter for downstream model performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attempt 3: Single-pass budget allocation.&lt;/strong&gt; Works fine for uniform documents. Fails badly on documents with mixed density: technical specs mixed with background narrative. The two-pass approach emerged from debugging these failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation and Links
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;llmslim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Website with full docs: &lt;a href="https://www.llmslim.app" rel="noopener noreferrer"&gt;https://www.llmslim.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub with reproducible benchmarks: &lt;a href="https://github.com/Thanatos9404/llmslim" rel="noopener noreferrer"&gt;https://github.com/Thanatos9404/llmslim&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The benchmark scripts, raw JSON payloads, and full methodology are open. If you find issues with the numbers, open an issue - I'd genuinely like to know.&lt;/p&gt;

</description>
      <category>python</category>
      <category>machinelearning</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Why Your LLM Pipeline Is Burning 60% of Its Token Budget on Noise (and How to Fix It)</title>
      <dc:creator>Yashvardhan Thanvi</dc:creator>
      <pubDate>Sat, 18 Jul 2026 22:13:03 +0000</pubDate>
      <link>https://dev.to/yashvardhan_thanvi_6762e7/why-your-llm-pipeline-is-burning-60-of-its-token-budget-on-noise-and-how-to-fix-it-27gp</link>
      <guid>https://dev.to/yashvardhan_thanvi_6762e7/why-your-llm-pipeline-is-burning-60-of-its-token-budget-on-noise-and-how-to-fix-it-27gp</guid>
      <description>&lt;p&gt;I run a lot of RAG pipelines. And for a while, I was doing what most people do: retrieve the top-k documents, concatenate them into the context, and ship the whole thing to the LLM.&lt;/p&gt;

&lt;p&gt;It worked. But when I started looking closely at what was actually in those contexts, I noticed something uncomfortable: a huge fraction of every prompt was filler. Background sentences that restated the obvious. Transition paragraphs that connected ideas the model didn't need connected. Prose padding that existed because technical documents are written for humans who need continuity, not for models that need information density.&lt;/p&gt;

&lt;p&gt;And I was paying for every token of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Is Worse Than You Think
&lt;/h2&gt;

&lt;p&gt;Here's what makes this particularly painful: it's not just a billing issue. Long-context prompts have real performance implications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quadratic attention cost.&lt;/strong&gt; Transformer attention scales as O(n^2) with sequence length. Adding 2,000 filler tokens to a 4,000-token context doesn't increase cost by 50% - it increases the prefill computation by nearly 225%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lost in the Middle.&lt;/strong&gt; Research consistently shows that LLMs underweight information in the middle of long contexts. If your most relevant retrieved chunk lands in position 12 of 20, the model may not give it the attention it deserves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instruction drift.&lt;/strong&gt; This is the one that bit me hardest. When system directives are diluted across thousands of tokens of prose, models sometimes drop low-frequency rules. A JSON schema requirement buried after 3,000 tokens of context is easier to forget than one sitting at token 200.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I spent about three months building LLMSlim, a Python library for surgical prompt compression. The goal was simple: reduce the token count of prompts significantly without losing any critical information and without touching system instructions.&lt;/p&gt;

&lt;p&gt;The core of the library is a 6-step deterministic pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llmslim&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;compress&lt;/span&gt;

&lt;span class="c1"&gt;# One line to compress your context
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;your_massive_rag_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target_ratio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Keep 50% of tokens
&lt;/span&gt;    &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;extractive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# 100% offline
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compressed_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Compressed context ready to use
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_reduction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# e.g., 0.52 (52% reduction)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How the Pipeline Works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Protected Sentence Splitting&lt;/strong&gt;&lt;br&gt;
The text is split into sentences using regex patterns that avoid breaking on code fences (&lt;code&gt;&lt;/code&gt;`&lt;code&gt;&lt;/code&gt;), URLs, or Markdown title markers. AST fence content is preserved as atomic units.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: TF-IDF Vector Graph Construction&lt;/strong&gt;&lt;br&gt;
Each sentence becomes a vector in TF-IDF space. We compute pairwise cosine similarities to build a weighted graph where edges represent semantic similarity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: LexRank Centrality Scoring&lt;/strong&gt;&lt;br&gt;
We run power iteration over the stochastic transition matrix derived from the similarity graph. Sentences with higher stationary probability scores are more informationally central to the document.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Priority Tier Hard Locking&lt;/strong&gt;&lt;br&gt;
Before any pruning happens, a deterministic rule pass identifies and hard-locks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tier 4 (highest): Sentences containing MUST, NEVER, ALWAYS, REQUIRED, or system role markers&lt;/li&gt;
&lt;li&gt;Tier 3: Sentences with numerical entities, proper nouns, URLs, and technical identifiers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These sentences are immune to the scoring algorithm. They survive regardless of centrality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Two-Pass Budget Allocation&lt;/strong&gt;&lt;br&gt;
Pass 1 allocates token budgets proportionally across semantic chunks. Pass 2 rebalances globally to hit the target ratio, using a priority-aware knapsack allocation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Ordered Reassembly&lt;/strong&gt;&lt;br&gt;
Selected sentences are reassembled in their original document order. This preserves logical flow and causal reasoning chains.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hybrid Strategy (v0.3.0)
&lt;/h2&gt;

&lt;p&gt;The extractive pipeline is fast (sub-30ms) and fully offline. But for contexts where you want even higher compression quality, v0.3.0 introduces hybrid mode:&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;python&lt;br&gt;
from llmslim import compress, CallableProvider, RewriteRequest&lt;/p&gt;

&lt;h1&gt;
  
  
  Plug in any LLM you already have
&lt;/h1&gt;

&lt;p&gt;def my_rewriter(req: RewriteRequest) -&amp;gt; str:&lt;br&gt;
    return openai_client.chat.completions.create(&lt;br&gt;
        model="gpt-4o-mini",&lt;br&gt;
        messages=[{"role": "user", "content": req.user_prompt}]&lt;br&gt;
    ).choices[0].message.content&lt;/p&gt;

&lt;p&gt;provider = CallableProvider(my_rewriter)&lt;/p&gt;

&lt;p&gt;result = compress(&lt;br&gt;
    context,&lt;br&gt;
    target_ratio=0.45,&lt;br&gt;
    strategy="hybrid",&lt;br&gt;
    provider=provider&lt;br&gt;
)&lt;br&gt;
&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;The hybrid mode runs extractive pre-pruning first (removing obvious noise), then passes the reduced context to the LLM rewriter for semantic compression. This achieves higher information density than pure extraction while keeping the LLM call focused on a smaller input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarks
&lt;/h2&gt;

&lt;p&gt;All benchmarks are reproducible and run on N=500 prompts per dataset:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dataset&lt;/th&gt;
&lt;th&gt;Token Reduction&lt;/th&gt;
&lt;th&gt;Latency&lt;/th&gt;
&lt;th&gt;Directive Retention&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;System Directives&lt;/td&gt;
&lt;td&gt;51.4%&lt;/td&gt;
&lt;td&gt;24.8ms&lt;/td&gt;
&lt;td&gt;100.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50k Long Context (GPT-5)&lt;/td&gt;
&lt;td&gt;55.0%&lt;/td&gt;
&lt;td&gt;26.0ms&lt;/td&gt;
&lt;td&gt;100.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XML Mode (Claude 3.5)&lt;/td&gt;
&lt;td&gt;50.0%&lt;/td&gt;
&lt;td&gt;24.0ms&lt;/td&gt;
&lt;td&gt;100.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100k Megabyte RAG (Gemini)&lt;/td&gt;
&lt;td&gt;65.0%&lt;/td&gt;
&lt;td&gt;38.0ms&lt;/td&gt;
&lt;td&gt;100.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 100% directive retention across all test domains is the number I'm most proud of. It's not coincidental - it's the Priority Tier system doing exactly what it was designed to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;A few things surprised me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TF-IDF is surprisingly competitive with embeddings for this task.&lt;/strong&gt; I initially assumed I'd need neural embeddings for good centrality scoring. TF-IDF vector space turned out to work remarkably well for identifying genuinely redundant prose, largely because redundant sentences tend to share vocabulary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The two-pass budget allocator matters more than I expected.&lt;/strong&gt; A naive single-pass selection consistently underperforms because it doesn't account for how information clusters within documents. The second pass global rebalancing step is responsible for maybe 8-10% of the quality improvement over simpler approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instruction fidelity is a hard constraint, not a soft one.&lt;/strong&gt; Early versions of the pipeline treated all sentences equally by score. The moment I realized I needed a hard exclusion layer (not just upweighting) for directives, the results became dramatically more reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;`bash&lt;br&gt;
pip install llmslim&lt;br&gt;
`&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Full documentation, integration guides for LangChain, LlamaIndex, FastAPI, Ollama, and more are at &lt;a href="https://www.llmslim.app" rel="noopener noreferrer"&gt;https://www.llmslim.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source is on GitHub and the benchmark methodology is fully open if you want to reproduce or challenge the numbers.&lt;/p&gt;

&lt;p&gt;I'd genuinely love to hear from anyone running production RAG pipelines about what compression approaches you've tried and what's worked. This is still a largely unsolved problem at the edges.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>opensource</category>
      <category>machinelearning</category>
    </item>
  </channel>
</rss>
