Persona AI Discourse, supporto caricamento

Ora puoi includere grandi blocchi di testo nelle tue persona AI!

Ciò offre molteplici vantaggi:

  1. Puoi introdurre grandi blocchi di testo nei tuoi bot AI personalizzati che sono assenti dall’addestramento dei modelli. (ad esempio: documenti di formazione interni, report interni)

  2. Puoi ancorare meglio una persona con dati concreti (anche se esistono nel set di addestramento del modello) il che può aiutare il modello a citare correttamente informazioni specifiche e aumentare la qualità dei risultati.

Per aggiungere caricamenti:

  1. Crea una nuova persona utilizzando l’interfaccia /admin/plugins/discourse-ai/ai-personas/.

  2. Carica i file di testo che desideri includere nella tua persona

:information_source: Prima di caricare i file, aggiungi le estensioni pertinenti ( .md e .txt) tramite l’impostazione del sito authorized extensions in modo che possano essere utilizzate dalla persona

  1. Regola le opzioni di indicizzazione come ritieni opportuno

Prerequisiti

Affinché l’opzione funzioni, dovrai avere configurato ai_embeddings_enabled e un ai_embeddings_model.

Discourse AI supporta un’enorme quantità di modelli di embedding.

I nostri clienti ospitati ottengono l’accesso gratuito al modello all’avanguardia bge-large-en.

Gli self-hoster o coloro che desiderano più scelta possono ospitare autonomamente un modello di embedding o utilizzare modelli di Open AI, Google (Gemini) e altri.

È un RAG?

L’implementazione del nostro supporto per il caricamento è infatti Retrieval-Augmented Generation.

A grandi linee, ogni volta che stiamo per chiedere a un LLM di rispondere a una domanda dell’utente, cerchiamo informazioni altamente pertinenti basate sul testo che hai inserito e le inseriamo nel prompt di sistema.

Spiegazione delle varie opzioni di indicizzazione

Cos’è un token? i token sono primitive utilizzate dai modelli linguistici di grandi dimensioni per suddividere il testo. Una spiegazione visiva eccellente è disponibile su: https://platform.openai.com/tokenizer

L’implementazione del caricamento di Discourse AI è dotata dei seguenti interruttori:

Upload Chunk Tokens: dopo che i file vengono caricati, li dividiamo in pezzi. Questo ti permette di controllare quanto sono grandi i pezzi. Se un pezzo è troppo grande per il tuo modello di embedding, l’embedding verrà troncato (verrà gestita solo una parte dei token).

Upload Chunk Overlap Tokens: questo è il numero di token inclusi dal chunk precedente in quello corrente. Maggiore è questo numero, più informazioni duplicate verranno memorizzate nel tuo indice.

Search Conversation Chunks: questo controlla quanti “chunk” di token verranno inclusi incondizionatamente in base alla pertinenza nel prompt di completamento. Maggiore è il numero, più contesto verrà fornito all’LLM (e più costose saranno le chiamate). Ad esempio: se questo è impostato su 10 e Upload Chunk Tokens è impostato su 200, ogni completamento avrà un overhead aggiuntivo di 2000 token.

Come fa Discourse AI a suddividere i corpi di testo?

Discourse utilizza un Recursive Character Text Splitter, che tenta di mantenere insieme paragrafi, righe e infine parole durante la suddivisione.

Inoltre, Discourse ti offre un controllo aggiuntivo su come verrà suddiviso il tuo testo.

Il separatore [[metadata YOUR METADATA HERE]] può essere utilizzato per suddividere grandi blocchi di testo e evidenziare correttamente cosa copre ciascuna sezione.

Ad esempio:

[[metadata about cats]]
a long story about cats
[[metadata about dogs]]
a long story about dogs

Ciò consente a un singolo documento di testo di coprire un’ampia varietà di contenuti e ti protegge dalla “contaminazione dei chunk”. Hai la garanzia che solo i dati sui gatti saranno inclusi nei chunk sui gatti e i cani nei chunk sui cani.

Sembra complicato, come posso fare il debug?

Discourse AI fornisce l’impostazione del sito ai bot debugging enabled groups, gli utenti in questo gruppo hanno accesso al debug dell’AI:

Le schermate di debug dell’AI possono aiutarti a ottenere una visione delle informazioni che inviamo all’AI.

:warning: Garbage in - Garbage out Se fornisci informazioni inutili o vaghe a un LLM, questo non può trasformarle magicamente in informazioni utili

Questa schermata può aiutarti a decidere meglio quanto dovrebbero essere grandi i tuoi chunk o se stai includendo troppi o troppo pochi chunk.

Funziona davvero?

Un esempio reale è la suddivisione della documentazione HAProxy e il suo inserimento in una persona:

System Prompt:

Sei un bot specializzato nel rispondere a domande su HAProxy.

Vivi su un forum Discourse e renderizzi il markdown di Discourse.

Quando fornisci risposte, cerca sempre di includere link alla documentazione HAProxy.

Ad esempio, ecco come collegheresti alla sezione 10.1.1. tieni presente che puoi collegarti a una sezione o a un’opzione al suo interno.

[fcgi-app](https://www.haproxy.com/documentation/haproxy-configuration-manual/latest/#10.1.1-fcgi-app)

Sii generoso con i link, sono molto utili.

Contenuto caricato:
processed-haproxy-2.txt (1,2 MB)

Che è stato generato utilizzando il seguente script:

file_content = File.read("configuration.txt")

title = nil
body = nil
last_line = nil

sections = []

file_content.each_line do |line|
  if line.strip.match?(/^[-]+$/)
    section_number, title = title.to_s.split(" ", 2)
    sections << {
      section_number: section_number,
      title: title,
      body: body.to_s.strip
    }

    title = last_line
    body = nil
    last_line = nil
  else
    body = body.to_s + last_line.to_s
    last_line = line
  end
end

section_number, title = title.to_s.split(" ", 2)
sections << { section_number: section_number, title: title, body: body }

section_names =
  sections.map { |section| [section[:section_number], section[:title]] }.to_h

sections[4..-1].each do |section|
  title = []
  current = +" "
  section_number = section[:section_number]
  section_number
    .split(".")
    .each do |number|
      current << number
      current << "."
      title << section_names[current].to_s.strip
    end
  title = title.join(" - ")

  body = section[:body]

  next if body.strip.empty?
  puts "[[metadata section=\"#{section_number}\" title=\"#{title.strip}\"]]"
  puts body
end

Sia Claude Opus che GPT-4 possono fallire miseramente con domande complesse. Questo è comprensibile poiché si nutrono di tutti i token su Internet, quindi 50 versioni diverse della documentazione HAProxy e tutte le discussioni del mondo al riguardo entrano nel cervello, il che può confonderlo molto:

Esempi di GPT-4 e Claude 3 Opus confusi

Entrambi sono oggettivamente non così buoni come la risposta ottimizzata fornita dal Discourse RAG:

Esempi di GPT-4 e Claude Opus meno confusi

Il futuro

Attendiamo con impazienza il tuo feedback, alcune idee per il futuro potrebbero essere:

  • Supporto per PDF/DOCX/XLS ecc. in modo da non dover convertire in testo
  • Chunking più intelligente per codice sorgente / html
  • Trasformazioni intelligenti dei dati in ingresso prima dell’indicizzazione

Facci sapere cosa ne pensi!

Un grande ringraziamento a @Roman per aver implementato questa funzionalità :hugs:

24 Mi Piace

Sarebbe possibile, oltre ai testi caricati manualmente, includere post di forum che corrispondono a criteri selezionati?

Come:

  • in una data categoria
  • ha un certo tag (o, non ce l’ha)
  • fa parte di un argomento contrassegnato come risolto (alternativamente, è specificamente un post di soluzione)
  • è l’OP dell’argomento, non una risposta
  • è pubblicato da un utente in un dato gruppo
  • è prima o dopo una certa data

O forse invece di caselle di controllo con queste cose, semplicemente “è uno dei primi N argomenti per una data ricerca nel forum”?

1 Mi Piace

Tutto questo è fattibile oggi con un comando di ricerca personalizzato:

  • La categoria data può essere selezionata nel filtro
  • tag
  • risolto
  • solo op (penso sia fattibile)
  • gruppo dato
  • prima e dopo la data

:hugs:

5 Mi Piace

Hmmm, forse non ho capito bene. Renderlo disponibile alla persona fa la stessa cosa?

Ci ho provato, e per lo più ottengo solo che Mistral inventa titoli di argomenti e link a numeri di post totalmente casuali. :slight_smile:

1 Mi Piace

Mistral è davvero abbastanza buono per questi compiti? Penso che questo potrebbe causare le allucinazioni. Sam ha ragione, cambiando la query di base puoi fare tutte le cose che hai dichiarato nell’OP.

1 Mi Piace

E ho pubblicato prima di aver finito i miei pensieri. La domanda era: fornire il comando di ricerca e i parametri fa effettivamente la stessa cosa di fornire file caricati?

Ma sì, Mistral potrebbe non essere abbastanza buono.

1 Mi Piace

Solo per espandere un po’ qui:

https://chat.lmsys.org/?leaderboard

Mistral è disponibile in molte varianti… c’è Mistral 7b, Mixtral 8x7b (quello che hai) e il nuovissimo mistralai/Mixtral-8x22B-Instruct-v0.1 · Hugging Face - questo e altri 5/6 modelli che rilasciano, inclusi alcuni a codice chiuso.

Bisogna stare attenti a un “Mistral non abbastanza buono” e chiarire sempre.

Direi che Mixtral-8x7b semplicemente non è adatto al supporto degli strumenti, si discosta troppo.

Direi che è

  1. Abbastanza buono per il supporto “upload”
  2. Molto bravo nel supporto di persona personalizzata
  3. Debole nel supporto degli strumenti

Stiamo cercando di vedere se possiamo aggiornare a 8x22b (viene fornito con un buon supporto degli strumenti), il problema è che i requisiti di memoria sono piuttosto elevati e dovremmo quantizzare il modello per farlo rientrare bene nei nostri server.

Ma davvero… se hai un accordo di privacy dei dati con Amazon, consiglierei vivamente Bedrock, che ti darebbe accesso a Claude 3 Opus e Haiku.

Capisco la tensione tra modelli open source e modelli a codice chiuso. È difficile, al momento i modelli a codice chiuso sono decisamente avanti.

2 Mi Piace

Hai ragione, avrei dovuto formulare meglio. Stavo infatti alludendo ai modelli a codice chiuso che sono generalmente migliori.

2 Mi Piace

L’upload di più file .txt contemporaneamente sta dando problemi: appaiono rapidamente, ma poi ne viene mostrato solo uno, dopodiché il pulsante “Aggiungi file” non risponde più.

Penso anche che il supporto per i file .md sarebbe una grande aggiunta.

1 Mi Piace

oh yikes … bella osservazione @Roman ci darà un’occhiata.

Questo dovrebbe funzionare bene, è già supportato devi solo abilitare l’estensione.

3 Mi Piace

Ho inviato una correzione per il bug multi-file:

4 Mi Piace

2 post sono stati divisi in un nuovo argomento: Miglioramento della qualità dei filtri di ricerca in Discourse AI

Ehi Sam, mi chiedo come funzioni esattamente. Dirà all’IA che si tratta di dati su gatti o cani, ma come influenzerà i chunk se sono già impostati su un numero fisso di token (diciamo 2000)? Interromperà un chunk quando vedrà una riga come [[metadata about dogs]] e ne inizierà uno nuovo?

1 Mi Piace

Sì, si interromperà presto

2 Mi Piace

Oh yikes, stavo usando il formato <meta content="YOUR METADATA HERE"> che funziona per la maggior parte dei modelli LLM, c’è un motivo per cui hai scelto il modo [[tra parentesi]]? I <tag> funzionano ancora o è meglio usare il metodo tra parentesi in Discourse?

1 Mi Piace

Questo non viene affatto consumato dal llm (analizziamo e consumiamo metadati) volevamo un separatore che fosse molto improbabile che apparisse nei dati indicizzati

2 Mi Piace

Aggiunto questo pezzo alla copia

1 Mi Piace

Questi embedding creati per le persone AI si trovano nello stesso database vettoriale? E in realtà, tutti gli embedding generati per Discourse sono archiviati nello stesso database vettoriale?

1 Mi Piace

Tutto in Postgres usando lo stesso db

2 Mi Piace

Qualcuno può dirmi cosa succede ai file di testo caricati nelle personas se vengono eliminati dall’elenco dei file caricati? Capisco che vengono utilizzati per RAG, ma se elimino il file, verrà eliminato da ciò che è stato indicizzato? Mi chiedo se sia possibile modificare ciò che è indicizzato eliminando un file di testo, apportando le modifiche e ricaricandolo?

1 Mi Piace