Fråga dina Excel-filer lokalt: En offline RAG-pipeline med specialiserade AI-agenter för SQL-generering

Publicerad 2 april 2025 av Joel Thyberg

Fråga dina Excel-filer lokalt: En offline RAG-pipeline med specialiserade AI-agenter för SQL-generering

Utmaningen: Att Fråga Känslig Data i Excel-filer

Att låsa upp insikter gömda i lokala Excel-filer med vanliga svenska frågor är en utmaning. Det kräver ofta djup Excel-kunskap för komplexa analyser, och att skicka stora eller känsliga filer till molnbaserade AI-tjänster är sällan ett alternativ på grund av integritetsrisker och praktiska begränsningar. Dessutom är råa, stora Excel-strukturer svårhanterliga för de flesta AI-modeller.

Detta projekt demonstrerar en helt offline AI-pipeline som löser dessa problem. Genom att kombinera Retrieval-Augmented Generation (RAG), vektordatabaser och specialiserade, lokalt körda AI-agenter (inklusive en kvantiserad 7B-modell), omvandlas komplexa svenska frågor – även med negationer – till säkra SQL-anrop. Resultatet är ett kraftfullt, lokalt verktyg som gör Excel-data tillgänglig för analys utan behov av SQL-kunskaper eller internetuppkoppling, vilket garanterar fullständig datasekretess och kontroll.

Mål och Kriterier

Huvudmålet var att skapa ett system som låter användare interagera med sina lokala Excel-data via naturlig svenska. Specifika delmål och kriterier inkluderade:

  • Tolkning av komplex svenska: Systemet måste förstå nyanser som negationer ("inte", "saknar") och relationer mellan begrepp i frågan.
  • Hantering av ostrukturerad data: Kunna extrahera information även från Excel-filer som saknar perfekt tabellstruktur.
  • Automatisk & Säker SQL: Generera korrekta SQL-frågor automatiskt och implementera strikta säkerhetsspärrar för att endast tillåta dataläsning (SELECT) och blockera skadliga operationer.
  • Lokal Exekvering (Offline): Hela processen, inklusive AI-modellerna, måste köras lokalt för att säkerställa datasekretess (ingen data lämnar användarens dator) och oberoende av internetuppkoppling.
  • Tillgänglighet på Standardhårdvara: Designa systemet så att det kan köras på vanlig konsumenthårdvara, vilket uppnås genom effektiviseringar som modellkvantisering (t.ex. använda en kvantiserad 7B LLM).

Lösningen: En Modulär AI-Pipeline

Lösningen är en modulär AI-pipeline byggd i Python som orkestrerar flera AI-modeller och tekniker lokalt:

  1. Datakonvertering & Schemaanalys: Excel-filer (.xlsx) omvandlas till SQLite-tabeller. En analysmodul identifierar tabellstruktur och datatyper även i mindre strukturerade filer.
  2. Vektorisering (Embedding): Kolumnnamn och unika cellvärden omvandlas till vektorer med en lokal embedding-modell (via Ollama, t.ex. Nomic Embed) och lagras i en lokal vektordatabas (Qdrant) för semantisk sökning. Hash-värden används för effektiv uppdatering vid dataändringar.
  3. Avancerad Frågebearbetning:
    • Den svenska frågan genomgår: Lemmatisering (Stanza), Negationsanalys (spaCy), Termextraktion, Namngiven Entitetsigenkänning (NER med spaCy för personer, platser, organisationer).
    • Selektiv Översättning: En hybridstrategi används där generella delar av frågan översätts till engelska med modellen Helsinki-NLP/opus-mt-sv-en (för bättre LLM-kompatibilitet) medan identifierade entiteter och domänspecifika termer (med låg översättningskonfidens) behålls på svenska. Detta maximerar LLM:ens förståelse samtidigt som kritiska värden bevaras exakt.
  4. Kontextsökning (Retrieval): Bearbetade termer och deras vektorer används för att söka i Qdrant. Systemet hittar de mest relevanta databastabellerna, kolumnerna (via namn-embedding) och specifika värden (via värde-embedding) för frågan.
  5. SQL-generering (Generation - RAG):
    • En lokal LLM-agent via Ollama (specifikt en kvantiserad version av qwen2.5 coder instruct 7b) anropas för att generera SQL.
    • Dynamiska Prompter: Istället för en generell prompt används ett system med över 900 rader av specialiserade prompter. Rätt prompt väljs dynamiskt baserat på analysen av frågan (t.ex. typ av matchning – kolumn/värde/mixad, subtyp, och om negation identifierats). Detta ger LLM:en extremt specifik vägledning för att generera korrekt och säker SQL för just det scenariot.
    • Prompten inkluderar kontext från vektorsökningen (matchade kolumner/värden) och strikta regler för syntax och säkerhet.
  6. Säker Exekvering: Den genererade SQL-koden valideras rigoröst: endast SELECT-satser tillåts, och en lista med förbjudna kommandon (UPDATE, DELETE, DROP, etc.) blockeras aktivt. Först efter validering körs frågan mot den lokala SQLite-databasen. Resultaten samlas in och presenteras.

Hela denna pipeline, från frågeanalys till SQL-exekvering, körs helt lokalt utan att skicka data externt.

Resultat: Ett Konkret Exempel

Resultatet är ett robust och säkert system som framgångsrikt överbryggar klyftan mellan mänskligt språk (svenska) och strukturerad data dold i Excel-filer. Systemet testades och validerades på ett dataset bestående av tre Excel-filer, var och en med cirka 1000 rader och 60 kolumner, innehållande fågelobservationsdata. För en typisk komplex fråga som kräver analys över alla tre filerna, tog hela processen från inmatad svensk fråga till presenterat svar cirka 40 sekunder på standardhårdvara. Systemets förmåga kan illustreras med ett konkret exempel baserat på fågelobservationsdata:

Exempel: Fråga "Hur många unika artnamn har inte Joel Thyberg rapporterat?"

  1. Frågebearbetning: Frågan lemmatiseras ("hur mången unik artnamn ha inte joel thyberg rapportera"), negation ("inte") identifieras, och nyckeltermer ("joel thyberg", "artnamn") extraheras. "Joel Thyberg" identifieras som en person (NER). Frågan översätts selektivt (viktiga namn/termer behålls på svenska).
  2. Kontextsökning (Retrieval): Systemet söker i vektordatabasen (Qdrant) och hittar att "joel thyberg" är ett värde i kolumnen "Rapportör" och "artnamn" matchar kolumnen "Artnamn" i flera tabeller (t.ex. faglar_2022, faglar_2023, faglar_2024).
  3. Dynamisk Prompt & SQL-generering (Generation): Eftersom frågan innehåller både ett specifikt värde ("Joel Thyberg") och en kolumnreferens ("Artnamn"), samt en negation, väljer systemet en specialiserad negationsprompt för blandade värde/kolumn-frågor. Denna prompt instruerar den lokala LLM:en (kvantiserad qwen2.5 coder instruct 7b) att:
    • Skapa en subquery för att hitta alla "Artnamn" som har rapporterats av "Joel Thyberg" i respektive tabell.
    • Skapa en huvudquery som räknar (COUNT(DISTINCT ...) ) unika "Artnamn" som inte finns i subqueryns resultat (WHERE "Artnamn" NOT IN (SELECT ...)), samtidigt som den filtrerar bort ogiltiga värden (NULL, tomma strängar, och kolumnrubriken 'Artnamn').
    • Generera separata, validerade SQL-frågor för varje relevant tabell (2022, 2023, 2024).
  4. Säker Exekvering & Resultat: De genererade SELECT-frågorna valideras (inga otillåtna operationer) och körs sedan mot den lokala SQLite-databasen. Resultaten från varje tabell samlas in:
    • faglar_2022: {'COUNT(DISTINCT "Unnamed: 6")': 25}
    • faglar_2023: {'COUNT(DISTINCT "Unnamed: 6")': 15}
    • faglar_2024: {'COUNT(DISTINCT "Unnamed: 6")': 10}
  5. Presentation: Svaret presenteras för användaren på ett aggregerat och lättförståeligt sätt.

Detta exempel visar hur användare kan ställa komplexa frågor och få precisa svar utan SQL-kunskap, med full insyn i processen via loggning. Systemet demonstrerar kraften i att kombinera:

  • RAG: För att hämta relevant kontext.
  • Specialiserade AI-agenter/Prompter: För högkvalitativ, säker SQL.
  • Lokal AI-bearbetning: För dataintegritet, säkerhet och offline-funktionalitet.

Projektet visar ett konkret exempel på hur en genomtänkt AI-pipeline kan lösa verkliga problem och göra data mer tillgänglig.