<?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: Soufiane Zaari</title>
    <description>The latest articles on DEV Community by Soufiane Zaari (@soufianezaari).</description>
    <link>https://dev.to/soufianezaari</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%2F4153231%2Ff88ca42d-0f62-4f58-bb99-abbb7f138ff5.jpg</url>
      <title>DEV Community: Soufiane Zaari</title>
      <link>https://dev.to/soufianezaari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/soufianezaari"/>
    <language>en</language>
    <item>
      <title>Tangier Explorer - Bringing Open-Source AI to the Alleyways of Tangier</title>
      <dc:creator>Soufiane Zaari</dc:creator>
      <pubDate>Mon, 05 Oct 2026 21:23:59 +0000</pubDate>
      <link>https://dev.to/soufianezaari/tangier-explorer-bringing-open-source-ai-to-the-alleyways-of-tangier-1e8</link>
      <guid>https://dev.to/soufianezaari/tangier-explorer-bringing-open-source-ai-to-the-alleyways-of-tangier-1e8</guid>
      <description>&lt;h2&gt;
  
  
  Screen Fatigue in the White City
&lt;/h2&gt;

&lt;p&gt;When travelers and locals explore Tangier, a recurring pattern emerges: eyes glued to phone screens, blindly following generic mapping algorithms or crowdsourced listicles that lack local soul. In an ancient labyrinth like the Medina or Kasbah, mainstream maps often fail: GPS signals bounce off high white walls, cellular coverage drops in the narrowest alleyways, and generic AI recommendations feel sterile and disconnected from local culture.&lt;br&gt;
Technology should encourage us to experience the world, not trap us behind glass. That is why I built Tangier Explorer for the Hacktoberfest Open-Source AI Challenge: Week 1 (Touch Grass).&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Tangier Explorer?
&lt;/h2&gt;

&lt;p&gt;Tangier Explorer is a 100% offline walking route generator tailored to the city of Tangier. Instead of relying on cloud APIs, it runs locally on a laptop using Google's Gemma 3 (4B) via Ollama.&lt;br&gt;
The premise is straightforward:&lt;br&gt;
Select your preferred vibe (History, Food, Hidden spots, Sea, Nature, Culture).&lt;br&gt;
Choose your available duration (1 hour, 2 hours, or a half-day).&lt;br&gt;
Tangier Explorer builds a personalized walking tour with an authentic Tangier local persona ("Tanjaoui"), giving you the exact path, estimated walking times, and historical context. Once generated, download the route, close your laptop and start walking.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Here is how the interface looks using Gradio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3b76kr01jynk6vwyq0tn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3b76kr01jynk6vwyq0tn.png" alt=" " width="800" height="478"&gt;&lt;/a&gt;&lt;br&gt;
)&lt;br&gt;
The interface is designed to be minimal: pick your vibe, choose your time, click generate, and step outside.&lt;/p&gt;

&lt;p&gt;How It Works: "Data is Truth, Gemma is Storyteller"&lt;br&gt;
To avoid hallucinations while preserving creative narrative generation, I split the architecture into two distinct responsibilities:&lt;br&gt;
Deterministic Ground Truth (spots.json): A curated database of 148 verified locations across Tangier (Kasbah, Marshan, Perdicaris Forest, Cap Spartel, Grand Socco). Each entry includes name, neighborhood, category, and curated descriptions.&lt;br&gt;
Context Filtering: When a user selects a vibe, the app filters relevant spots locally and passes them into the prompt.&lt;br&gt;
Local Inference with Gemma 3 (4B): Gemma receives the filtered subset alongside a strict system prompt instructing it to act as an authentic local guide. Gemma structures the walking route, calculates transitions, and injects local flavor without inventing fictitious landmarks.&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;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gradio&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;gr&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Load curated dataset
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spots.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;SPOTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;SYSTEM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Nta guide touristique tanjaoui 9dim, katfhem bzzaf f Tanja w katdwi b Darija tanjawiya drayfa.
3ti l&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user circuit mtiye9, w 9ol lih fin ymchi khatwa b khatwa 3la 7ssab l&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;we9t w l&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vibe li khtar, w sta3mel ghir l&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amakin li m3tayin lik.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vibe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;SPOTS&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;vibe&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;spots_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;area&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;user_msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Vibe: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;vibe&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Duration: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Use ONLY these spots:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;spots_text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Build my walking route!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemma3:4b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SYSTEM&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_msg&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;route.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;# Tangier Explorer - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;vibe&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;route.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Taking Tangier Explorer Outside
&lt;/h2&gt;

&lt;p&gt;In the spirit of the "Touch Grass" theme, I tested the app on the ground in Tangier: walking a generated circuit, following the downloaded route where mobile data signal drops.&lt;br&gt;
What worked well:&lt;br&gt;
Zero latency and no signal anxiety: running Gemma locally meant generating the plan without worrying about 4G coverage inside thick stone walls.&lt;br&gt;
Narrative quality: Gemma 3 produced concise transitions between stops and captured the authentic rhythm of walking through the Kasbah.&lt;br&gt;
What needed tuning:&lt;br&gt;
Time estimation: the model initially packed too many steep uphill segments into a 1-hour walk. Restricting the prompt to fewer candidate spots fixed pace expectations significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Open-Source AI Matters
&lt;/h2&gt;

&lt;p&gt;This project demonstrates why open-weight models are vital for real-world utility:&lt;br&gt;
Zero internet requirement: ideal for outdoor exploration, remote hiking, and dense historic districts where mobile network connectivity is unreliable.&lt;br&gt;
Privacy by default: travel patterns, interests, and schedules remain entirely on the local device without tracking or central data aggregation.&lt;br&gt;
Accessible and extensible: free from recurring API billing or credit exhaustion. Anyone can fork the repository, swap spots.json with their own hometown data, and create an instant offline walking guide for any city in the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;I am submitting this project for:&lt;br&gt;
Hacktoberfest Open-Source AI Challenge: Week 1 (Touch Grass)&lt;br&gt;
Best Use of Gemma ($200 Featured Partner Category): leveraging Google's Gemma 3 4B locally via Ollama to create an edge-ready cultural walking guide.&lt;/p&gt;

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

&lt;p&gt;GitHub repository: &lt;a href="https://github.com/SoufianeZaari/tangier-explorer" rel="noopener noreferrer"&gt;https://github.com/SoufianeZaari/tangier-explorer&lt;/a&gt;&lt;br&gt;
Model: Google Gemma 3 (4B) via Ollama&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>ai</category>
    </item>
    <item>
      <title>Darija Buddy: A Local Gemma-Powered Tutor for a Friend</title>
      <dc:creator>Soufiane Zaari</dc:creator>
      <pubDate>Sat, 03 Oct 2026 01:02:48 +0000</pubDate>
      <link>https://dev.to/soufianezaari/darija-buddy-a-local-gemma-powered-tutor-for-a-friend-1kdh</link>
      <guid>https://dev.to/soufianezaari/darija-buddy-a-local-gemma-powered-tutor-for-a-friend-1kdh</guid>
      <description>&lt;h2&gt;
  
  
  The Friend &amp;amp; The Problem
&lt;/h2&gt;

&lt;p&gt;Moving to Morocco as an international student comes with a unique linguistic hurdle: Moroccan Darija. While formal Arabic (MSA) or French might get you through official paperwork, everyday social life happens in Darija.&lt;/p&gt;

&lt;p&gt;My university classmate, Alex, has been struggling to fit into group banter and daily conversations. He understands some basics, but when people talk fast or switch between Arabizi (Latin-script Darija using numbers like 3, 7, 9) and spoken phrases, he freezes.&lt;/p&gt;

&lt;p&gt;Traditional language apps don't support Moroccan Darija well—they usually default to Modern Standard Arabic, which locals rarely speak on the street. Human tutoring is expensive, and practicing with friends can feel intimidating when you're afraid of making mistakes.&lt;/p&gt;

&lt;p&gt;He needed a safe, patient, and conversational practice partner that speaks genuine Darija, understands phonetically typed Arabizi, and explains nuances in French.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built: Darija Buddy 🇲🇦
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Darija Buddy&lt;/strong&gt; is a lightweight, local conversational tutor designed to help non-Moroccan beginners practice real-life Darija speech.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Capabilities:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speaks authentic Darija:&lt;/strong&gt; It avoids rigid Modern Standard Arabic and replies in natural Moroccan expressions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual input handling:&lt;/strong&gt; It comprehends Latin-script Darija (Arabizi), French, and standard Arabic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bilingual feedback loop:&lt;/strong&gt; Whenever it introduces colloquial vocabulary or idioms, it appends concise pedagogical explanations in French.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gentle error correction:&lt;/strong&gt; If the learner makes a grammar or lexical slip, Darija Buddy reformulates the phrase constructively before keeping the conversation flowing.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Technical Architecture &amp;amp; How It Works
&lt;/h2&gt;

&lt;p&gt;The whole project runs entirely offline on a personal laptop — no expensive cloud infrastructure needed.&lt;br&gt;
+-----------------------------------------------------------+&lt;br&gt;
| Local Machine |&lt;br&gt;
| |&lt;br&gt;
| +-------------------+ +--------------------+ |&lt;br&gt;
| | Gradio Web UI | &amp;lt;------&amp;gt; | Ollama Runtime | |&lt;br&gt;
| | (darija_buddy.py) | | (gemma3:4b Model) | |&lt;br&gt;
| +-------------------+ +--------------------+ |&lt;br&gt;
+-----------------------------------------------------------+&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Core Model: Google Gemma 3 (4B)
&lt;/h3&gt;

&lt;p&gt;I selected &lt;strong&gt;Gemma 3 (4B)&lt;/strong&gt; as the reasoning engine. For a compact 4B-parameter open-weight model, Gemma 3 showcases remarkable multilingual understanding, easily deciphering transliterated Arabizi and grasping cultural Moroccan idioms.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Local Inference with Ollama
&lt;/h3&gt;

&lt;p&gt;Instead of relying on remote APIs with variable latency and pay-per-token pricing, the model runs via &lt;strong&gt;Ollama&lt;/strong&gt;. The quantized 4B weights run smoothly on consumer hardware (CPU-only), keeping RAM consumption under ~4 GB.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Gradio Interface
&lt;/h3&gt;

&lt;p&gt;The frontend is encapsulated in a single Python script using &lt;code&gt;gradio.ChatInterface&lt;/code&gt;, making it instantly accessible in any local browser window at &lt;code&gt;http://127.0.0.1:7860&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Pedagogical System Prompt Engineering
&lt;/h3&gt;

&lt;p&gt;The behavior is governed by a system prompt (full prompt in darija_buddy.py on GitHub) enforcing: authentic Darija instead of MSA, short French explanations, Arabizi/French/English input handling, gentle error correction, and short conversational replies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo &amp;amp; Interaction
&lt;/h2&gt;

&lt;p&gt;Here is a practice session where the user initiates in Arabizi, receives natural conversational responses, and gets immediate French vocabulary breakdowns:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr0w4ojmo3kg0mhu3am2i.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr0w4ojmo3kg0mhu3am2i.jpeg" alt=" " width="800" height="248"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhe6b82ahcg2nwuoc0my6.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhe6b82ahcg2nwuoc0my6.jpeg" alt=" " width="800" height="248"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fop1ynjn3m0c5tfu7kxkb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fop1ynjn3m0c5tfu7kxkb.jpeg" alt=" " width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why Open Innovation Matters for This Project&lt;br&gt;
This project highlights why open-weight models and local inference triumph over proprietary closed APIs:&lt;/p&gt;

&lt;p&gt;Zero Operational Cost: Language practice requires repetitive, daily micro-conversations. Running Gemma 3 locally means zero token costs, no API credits expiring, and no credit card requirements for students.&lt;br&gt;
Total Privacy for the Learner: Practicing a new language involves vulnerability and personal conversations. All inference happens in-memory on the laptop; no conversation logs or personal data are ever uploaded to remote commercial servers.&lt;br&gt;
Offline Reliability: University Wi-Fi and mobile data can be unpredictable. Darija Buddy works entirely on a plane, on a train, or in a cafe without an active internet connection.&lt;br&gt;
Customizability: With open weights, I'm not locked into proprietary censorship or forced model upgrades. I can easily fine-tune Gemma on dialectal corpora or swap weights as newer open models release.&lt;br&gt;
What My Friend Said&lt;br&gt;
When I showed it to Alex on a video call:&lt;/p&gt;

&lt;p&gt;"C'est magnifique... et ça va beaucoup m'aider à apprendre le Darija."&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code Repository&lt;br&gt;
The code is completely open-source and easy to reproduce:&lt;/p&gt;

&lt;p&gt;GitHub Repository: &lt;a href="https://github.com/SoufianeZaari/darija-buddy" rel="noopener noreferrer"&gt;https://github.com/SoufianeZaari/darija-buddy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>DarijaBench: Do AI Models Actually Understand Moroccan Darija?</title>
      <dc:creator>Soufiane Zaari</dc:creator>
      <pubDate>Thu, 01 Oct 2026 16:39:56 +0000</pubDate>
      <link>https://dev.to/soufianezaari/darijabench-do-ai-models-actually-understand-moroccan-darija-4cm1</link>
      <guid>https://dev.to/soufianezaari/darijabench-do-ai-models-actually-understand-moroccan-darija-4cm1</guid>
      <description>&lt;p&gt;Update (Oct 2): Following reviewer feedback, the 0.95 vs 0.90 gap is not statistically significant (exact McNemar p = 0.25) — the honest reading is a four-way tie at n = 60.&lt;/p&gt;

&lt;p&gt;DarijaBench: Do AI Models Actually Understand Moroccan Darija?&lt;br&gt;
As a Moroccan student, I use AI assistants every day. They are brilliant in English and French — but I kept noticing something: ask them something in Darija (Moroccan Arabic dialect, spoken by 35+ million people), and the confident answers start wobbling. So I decided to stop guessing and start measuring. I built DarijaBench, a 60-item benchmark that tests whether today's frontier models truly understand Moroccan Darija — and ran it on four of them.&lt;br&gt;
🔗 Benchmark: &lt;a href="https://www.kaggle.com/benchmarks/soufianzaari/darijabench" rel="noopener noreferrer"&gt;https://www.kaggle.com/benchmarks/soufianzaari/darijabench&lt;/a&gt;&lt;br&gt;
What DarijaBench tests&lt;br&gt;
Darija is a low-resource dialect: it is barely present in training data compared to English, French, or even Modern Standard Arabic. DarijaBench probes three practical skills, 20 items each:&lt;br&gt;
Darija → French translation — can the model convert everyday Moroccan sentences into French?&lt;br&gt;
Sentiment analysis — can it tell whether a Darija text is positive, negative, or neutral?&lt;br&gt;
Moroccan cultural knowledge — can it answer questions asked in Darija about Morocco (the capital, couscous ingredients, the 2030 World Cup hosts...)?&lt;br&gt;
Each item is graded automatically with keyword checks, and the final score is the average of the three categories. The whole thing was built with the Kaggle Benchmarks SDK, entirely on the free quota.&lt;br&gt;
The results&lt;br&gt;
Model&lt;br&gt;
DarijaBench score&lt;br&gt;
Gemini 3.7 Flash&lt;br&gt;
0.95&lt;br&gt;
Claude Sonnet 5&lt;br&gt;
0.95&lt;br&gt;
Claude Opus 4.7&lt;br&gt;
0.95&lt;br&gt;
GPT-5.6 Luna&lt;br&gt;
0.90&lt;br&gt;
What I learned&lt;/p&gt;

&lt;p&gt;The top models have mostly cracked basic Darija. A three-way tie at 0.95 was not what I expected — I assumed Darija would still be a weak spot. Frontier labs are clearly doing better on dialectal Arabic than their reputation suggests.&lt;br&gt;
Sentiment is the easiest skill. Gemini scored a perfect 20/20 on sentiment. Emotional tone ("هاد المطعم رائع!" vs "الخدمة خايبة") seems to transfer across dialects and languages with little friction.&lt;br&gt;
Translation is the hardest. At 85%, Darija→French was the lowest category for Gemini. Darija is full of French loanwords used differently than in French, plus idioms with no literal equivalent — exactly where word-level understanding breaks down.&lt;br&gt;
Small gaps need bigger samples. GPT-5.6 Luna's 0.90 vs 0.95 is ~3 more failures on 60 items — but a paired test shows this isn't statistically significant (p = 0.25). Detecting a 5-point gap reliably needs ~200–300 items. That's the main lesson for v2.&lt;br&gt;
Honest caveats. Keyword-based grading is brittle — a correct answer phrased unexpectedly can fail. Sixty items is small. And the three-way tie tells me the benchmark is currently too easy to separate the best models. The next version needs harder items: idioms, heavy code-switching (Darija/French/Spanish mixes are everywhere in the north), and regional variants. Try it yourself The benchmark is public — run more models on it, or fork the task and make it harder. If you speak a low-resource dialect, consider building your own version: the Kaggle Benchmarks SDK makes it surprisingly painless, and measuring is always better than vibing.&lt;br&gt;
Built for the DEV x Kaggle Benchmarking Challenge. &lt;/p&gt;

&lt;h1&gt;
  
  
  kagglechallenge
&lt;/h1&gt;

</description>
      <category>kagglechallenge</category>
      <category>llm</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
