<?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: Alexandr I</title>
    <description>The latest articles on DEV Community by Alexandr I (@alexandr_i_ffce3f9e072773).</description>
    <link>https://dev.to/alexandr_i_ffce3f9e072773</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3859388%2Fd1df91bb-e8cb-48a4-86aa-40787bad6a2d.png</url>
      <title>DEV Community: Alexandr I</title>
      <link>https://dev.to/alexandr_i_ffce3f9e072773</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexandr_i_ffce3f9e072773"/>
    <language>en</language>
    <item>
      <title>I Built a Moderation Agent That Refuses to Be Intelligent — Just Focused</title>
      <dc:creator>Alexandr I</dc:creator>
      <pubDate>Fri, 03 Apr 2026 12:49:47 +0000</pubDate>
      <link>https://dev.to/alexandr_i_ffce3f9e072773/i-built-a-moderation-agent-that-refuses-to-be-intelligent-just-focused-e59</link>
      <guid>https://dev.to/alexandr_i_ffce3f9e072773/i-built-a-moderation-agent-that-refuses-to-be-intelligent-just-focused-e59</guid>
      <description>&lt;p&gt;Cross‑posted from Medium:&lt;br&gt;&lt;br&gt;
&lt;a href="https://medium.com/@alex6055082i/a-simple-text-moderation-system-with-llm-or-why-we-dont-need-another-agent-d991174e6107" rel="noopener noreferrer"&gt;https://medium.com/@alex6055082i/a-simple-text-moderation-system-with-llm-or-why-we-dont-need-another-agent-d991174e6107&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I spent weeks reading papers about multi-agent systems. Autonomous this, reasoning chains that. Everyone seemed convinced that complexity equals power.&lt;/p&gt;

&lt;p&gt;Then I realized something: my moderation problem doesn't need a genius. It needs someone who can say "block" or "pass" with confidence.&lt;/p&gt;

&lt;p&gt;So I built Lexicont differently. It's an agent, yes. But a stubborn one. It refuses to be "smart" in the conventional sense. No multi-tasking. No autonomous wandering. No pretending to understand philosophy when it just needs to catch bad text.&lt;/p&gt;

&lt;p&gt;The result? Something that actually works. Transparently. Predictably. Without the theater.&lt;/p&gt;
&lt;h2&gt;
  
  
  How It Works: Four Layers, No Loops
&lt;/h2&gt;

&lt;p&gt;The pipeline runs sequentially from fast to slow, without unnecessary cycles:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Pre-filter (rules and dictionaries)
&lt;/h3&gt;

&lt;p&gt;It starts with lightning-fast checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built-in profanity filter in 23 languages&lt;/li&gt;
&lt;li&gt;Detection of leetspeak (when people write "k1ll" or "5ex" instead of normal letters)&lt;/li&gt;
&lt;li&gt;Unicode obfuscation (attempts to hide bad words using similar symbols)&lt;/li&gt;
&lt;li&gt;Custom trigger lists&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples of what gets caught:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"buy fk documents" → BLOCK
"h4te you" → BLOCK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the text is caught here, it's immediately BLOCK. We don't go further.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. ML Classifier (detoxification)
&lt;/h3&gt;

&lt;p&gt;A small, fast ML classifier runs on CPU in about 50ms. It evaluates text across categories: toxicity, threat, insult, identity attack, and others.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: "I'll beat you up tomorrow"
Model: threat score 0.95 → BLOCK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If confidence is greater than or equal to 0.85, it's BLOCK again. Early exit triggers.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Contextual Analysis (LLM)
&lt;/h3&gt;

&lt;p&gt;If earlier layers aren't confident (confidence less than 0.8), the LLM kicks in.&lt;/p&gt;

&lt;p&gt;Here's the key point: the LLM doesn't make the final decision. It provides category scores, confidence levels, and a brief explanation. The actual verdict (block, review, or pass) comes from a rule engine that considers the contribution of all previous layers to the LLM's assessment.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Rule Engine (final verdict)
&lt;/h3&gt;

&lt;p&gt;The rule engine makes the final decision, taking into account results from all layers.&lt;/p&gt;

&lt;p&gt;This way, even when the LLM is involved, the system stays more controllable and deterministic than complex multi-agent architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It's Done This Way
&lt;/h2&gt;

&lt;p&gt;Because in real life, most projects don't need the smartest system. They need one they can trust and configure to their own rules.&lt;/p&gt;

&lt;p&gt;The more complex an agent is, the more autonomous it becomes, the higher the risk of getting a black box whose behavior is hard to explain and adjust. When it comes to content moderation, predictability and transparency often matter more than raw model power.&lt;/p&gt;

&lt;p&gt;We deliberately built a linear pipeline without loops or repeated analyses. The LLM doesn't drive the process here. It helps where simple rules aren't enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Beauty of Simplicity
&lt;/h2&gt;

&lt;p&gt;Lexicont turned out minimal in design. No complex abstractions, no reinventing the wheel. Just proven libraries.&lt;/p&gt;

&lt;p&gt;Because of this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any layer can be turned on or off&lt;/li&gt;
&lt;li&gt;You can add your own triggers via a YAML file&lt;/li&gt;
&lt;li&gt;You can use the library partially, just the filters you need&lt;/li&gt;
&lt;li&gt;All logic is transparent and debuggable&lt;/li&gt;
&lt;li&gt;The system can run on a regular CPU, though speed depends on your hardware&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About Models: Small But Capable
&lt;/h2&gt;

&lt;p&gt;Not everyone has a GPU, and large models demand serious resources. I discovered Qwen3-4B, a 4-billion-parameter model from Alibaba Cloud. It offers a surprisingly good balance of quality and speed.&lt;/p&gt;

&lt;p&gt;Quantized versions (Q4_K_M and IQ3_M) from bartowski work especially well. Quantization is when you compress a model to make it smaller while keeping quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q4_K_M:&lt;/strong&gt; ~2.5 GB, works well for most tasks&lt;br&gt;
&lt;strong&gt;IQ3_M:&lt;/strong&gt; ~2.0 GB, if memory is very limited&lt;/p&gt;

&lt;p&gt;For text moderation with the ML classifier, processing happens in 50–200ms on a laptop. When the LLM layer is invoked for complex cases, expect additional latency depending on your hardware.&lt;/p&gt;
&lt;h2&gt;
  
  
  Who This Is For
&lt;/h2&gt;

&lt;p&gt;For small and medium projects, Discord bots, Telegram bots, startups that want their own moderation system but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't want to pay thousands monthly for cloud APIs&lt;/li&gt;
&lt;li&gt;Want to control what rules apply&lt;/li&gt;
&lt;li&gt;Want to adjust behavior for their own policies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes a simple, reliable pipeline you fully control is enough.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try It Now
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/corefrg/lexicont.git
&lt;span class="nb"&gt;cd &lt;/span&gt;lexicont
poetry &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Before running, you need to set up your own configuration files with your moderation rules and policies. Check the documentation for details on configuring moderation_rules.yaml and moderation_config.yaml to match your specific needs.&lt;/p&gt;

&lt;p&gt;You can run the LLM locally using llama.cpp or Ollama:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using Ollama:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull qwen3:4b
ollama serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Or using llama.cpp:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;llama-server &lt;span class="nt"&gt;-m&lt;/span&gt; Qwen_Qwen3-4B-Q4_K_M.gguf &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt; 11434 &lt;span class="nt"&gt;-c&lt;/span&gt; 512 &lt;span class="nt"&gt;--threads&lt;/span&gt; 12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once configured, test it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run lexicont check &lt;span class="s2"&gt;"buy fake documents"&lt;/span&gt; &lt;span class="nt"&gt;--log-level&lt;/span&gt; DEBUG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For quick experimentation, you can also try running it on Kaggle or any machine with a CPU. No GPU required, though speed depends on your hardware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/corefrg/lexicont" rel="noopener noreferrer"&gt;https://github.com/corefrg/lexicont&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PyPI:&lt;/strong&gt; &lt;a href="https://pypi.org/project/lexicont/" rel="noopener noreferrer"&gt;https://pypi.org/project/lexicont/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;This is a text moderation project actively being developed, and its value may lie in showing that simple architecture often works well. More documentation and examples will be added as the project evolves.&lt;/p&gt;

&lt;p&gt;If you also believe that sometimes building a system you understand and can control matters more than something that works by magic, I'd love to hear your thoughts in the comments.&lt;/p&gt;

&lt;p&gt;Simplicity still deserves a place in the world.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>llm</category>
      <category>rag</category>
    </item>
  </channel>
</rss>
