Verwendung von KI zum Taggen und Kategorisieren von Forenbeiträgen

Ich habe eine Persona erstellt, um neue Themen automatisch zu kategorisieren und zu kennzeichnen. Dies ist der Prompt, den ich für diese Kategorie und diesen Tagger verwende.

Du bist ein KI-Assistent für mein Discourse-Forum. Deine Aufgabe ist es, neue Themen in eine der vordefinierten Kategorien einzuordnen und bis zu 5 relevante Tags anzuwenden.

Kategorien:

  • Kategorie 1
  • Kategorie 2
  • Kategorie 3
  • Kategorie 4
  • Kategorie 5

Tags:

Deine Auswahl muss aus dieser vordefinierten Liste stammen (wähle bis zu 5):
tag1, tag2, tag3, tag4, tag5

Aufgabe:

  • Wähle genau eine Kategorie aus der obigen Liste aus, die am besten zum Thema passt.
  • Wähle bis zu 5 Tags aus der obigen Liste basierend auf der Relevanz aus.
  • Formatiere deine Antwort genau so als JSON:
    {
      "category": "Gewählter Kategoriename",
      "tags": ["tag1", "tag2", "tag3"]
    }
    
    

Wenn ich diese Persona in Automatisierungen verwende und den Beitrag erstelle, identifiziert die KI die Kategorien und Tags mit diesem Ergebnis in einem Beitrag korrekt.

Liste Kategorien
{
“category”: “Korrekt identifizierte Kategorie”,
“tags”: ["Alle ", “gültigen”, “Tags”]
}

Die Frage ist, ob es bereits möglich ist, die KI und Automatisierungen tatsächlich zu nutzen, um neue Beiträge zu verschieben, zu kategorisieren und Tags für das Thema zuzuweisen. Wenn ja, bin ich sicher, dass die Prompts angepasst werden können, um zu optimieren, wie gut es funktioniert.

Danke,

1 „Gefällt mir“

Es wird… ein bisschen knifflig, uns fehlen 2 kleine Teile:

  1. Benutzerdefinierte Tools unterstützen jetzt viele Dinge, aber sie unterstützen keine Kategorisierung und keine Verschlagwortung, das können wir leicht hinzufügen.
  2. Ich benötige einen Responder, der im „stillen“ Modus funktioniert, damit er nicht tatsächlich auf das Thema antwortet.

Sobald beides vorhanden ist, erhalten Sie Zugriff auf 2 benutzerdefinierte Tools

  1. Thema verschlagworten
  2. Thema kategorisieren

(oder ein einzelnes Tool, das beides tut)

5 „Gefällt mir“

Tatsächlich, solange Sie mit dem Flüstern einverstanden sind, können Sie jetzt etwas tun.

Die Idee ist, dass Sie ein benutzerdefiniertes Tool definieren würden, um ein Thema zu kategorisieren (oder zu taggen), und dann die Persona es aufrufen lassen würden.

Ich bin gespannt, wie dieser Ansatz für Sie funktioniert. Sie müssen das Tool testen, es sollte über die Tool-Benutzeroberfläche recht einfach sein.

Es ist ziemlich umständlich, das alles zu bewerkstelligen, aber es ist auch ziemlich :exploding_head: dass es getan werden kann. Das Flüstern ist tatsächlich recht nützlich, da es Ihnen einen kleinen Einblick in den „Denkprozess“ gibt, wie der Antwortende zu den Tags/Kategorien gekommen ist.

3 „Gefällt mir“

Danke Sam,

Für manche einfacher als für andere. Ich gehöre zur letzteren Kategorie :joy:

Ich spiele damit herum und habe es noch nicht zum Laufen gebracht. Ich habe keine Erfahrung mit Tools und freue mich darauf, dies zum Laufen zu bringen, um über andere Möglichkeiten nachzudenken, Tools zu nutzen.

Ich habe versucht, den Code aus Ihrem Blog mit einem API-Schlüssel zu verwenden, was nicht funktionierte. Die KI schlug vor, eine hartcodierte URL zu verwenden, also habe ich das ohne Erfolg versucht.

Der API-Schlüssel wurde nicht aufgerufen und es wurden keine Protokolle mit Fehlern erstellt.

Dies wird verwendet, um Themen bei der Erstellung automatisch zu kategorisieren

Ich werde das Thema „Einblicke aus Jesu frühen Jahren und Wunder“ in die Kategorie Neues Testament einordnen, da es sich auf das Leben und die Lehren Jesu bezieht.
Ich verschiebe das Thema jetzt…

Das ist, was ich versucht habe.

/**

  • Kurzübersicht über die Tool-API
  • Einstiegsfunktionen
  • invoke(parameters): Hauptfunktion. Empfängt Parameter (Objekt). Muss einen JSON-serialisierbaren Wert zurückgeben.
  • Beispiel:
  • function invoke(parameters) { return “result”; }
  • details(): Optional. Gibt eine Zeichenkette zurück, die das Tool beschreibt.
  • Beispiel:
  • function details() { return “Tool description.”; }
  • Bereitgestellte Objekte
    1. http
  • http.get(url, options?): Führt eine HTTP-GET-Anfrage durch.
  • Parameter:
  •  url (string): Die URL der Anfrage.
    
  •  options (Object, optional):
    
  •    headers (Object): Header der Anfrage.
    
  • Gibt zurück:
  •  { status: number, body: string }
    
  • http.post(url, options?): Führt eine HTTP-POST-Anfrage durch.
  • Parameter:
  •  url (string): Die URL der Anfrage.
    
  •  options (Object, optional):
    
  •    headers (Object): Header der Anfrage.
    
  •    body (string): Body der Anfrage.
    
  • Gibt zurück:
  •  { status: number, body: string }
    
  • (auch verfügbar: http.put, http.patch, http.delete)
  • Hinweis: Maximal 20 HTTP-Anfragen pro Ausführung.
    1. llm
  • llm.truncate(text, length): Kürzt Text auf eine bestimmte Token-Länge.
  • Parameter:
  •  text (string): Zu kürzender Text.
    
  •  length (number): Maximale Tokens.
    
  • Gibt zurück:
  •  Gekürzter String.
    
    1. index
  • index.search(query, options?): Durchsucht indizierte Dokumente.
  • Parameter:
  •  query (string): Suchanfrage.
    
  •  options (Object, optional):
    
  •    filenames (Array): Suchanfrage auf bestimmte Dateien beschränken.
    
  •    limit (number): Maximale Fragmente (bis zu 200).
    
  • Gibt zurück:
  •  Array von { fragment: string, metadata: string }
    
    1. upload
  • upload.create(filename, base_64_content): Lädt eine Datei hoch.
  • Parameter:
  •  filename (string): Dateiname.
    
  •  base_64_content (string): Base64-kodierter Dateiinhalt.
    
  • Gibt zurück:
  •  { id: number, short_url: string }
    
    1. chain
  • chain.setCustomRaw(raw): Setzt den Body des Beitrags und beendet die Kette.
  • Parameter:
  •  raw (string): Roher Inhalt, der dem Beitrag hinzugefügt werden soll.
    
  • Einschränkungen
  • Ausführungszeit: ≤ 2000ms
  • Speicher: ≤ 10MB
  • HTTP-Anfragen: ≤ 20 pro Ausführung
  • Das Überschreiten der Limits führt zu Fehlern oder Beendigung.
  • Sicherheit
  • Sandboxed-Umgebung: Kein Zugriff auf System- oder globale Objekte.
  • Kein Dateisystemzugriff: Keine Dateien lesen oder schreiben.
    */

/**

  • Discourse Topic Categorizer
  • Dieses Tool ermöglicht es Ihnen, die Kategorie eines Discourse-Themas
  • über die Discourse-API zu ändern.
    */

/**

  • Discourse Topic Categorizer
  • Dieses Tool ermöglicht es Ihnen, die Kategorie eines Discourse-Themas
  • über die Discourse-API zu ändern.
    */

/**

  • Discourse Topic Categorizer
  • Dieses Tool ermöglicht es Ihnen, die Kategorie eines Discourse-Themas
  • über die Discourse-API zu ändern.
    */

function invoke(params) {
// Validierung erforderlicher Parameter
if (!params.topic_id) {
return { error: “Fehlender erforderlicher Parameter: topic_id” };
}

if (!params.category_id) {
return { error: “Fehlender erforderlicher Parameter: category_id” };
}

// Basis-URL für Ihre Discourse-Instanz
const baseUrl = “https://community.mysite.com”;

// Vollständige API-Endpunkt-URL zum Aktualisieren eines Themas
const apiUrl = ${baseUrl}/t/${params.topic_id}.json;

// Anforderungs-Body vorbereiten
const requestBody = {
category_id: params.category_id
};

// Optionaler Parameter: Titel aktualisieren, falls angegeben
if (params.title) {
requestBody.title = params.title;
}

// Verwenden Sie Ihren bereitgestellten API-Schlüssel
const apiKey = “Discourse-API-Key”;

try {
// PUT-Anfrage zur Aktualisierung des Themas stellen
const response = http.put(apiUrl, {
headers: {
“Content-Type”: “application/json”,
“Api-Key”: apiKey,
“Api-Username”: params.api_username || “system”
},
body: JSON.stringify(requestBody)
});

if (response.status >= 200 && response.status < 300) {
  return {
    success: true,
    topic_id: params.topic_id,
    category_id: params.category_id,
    response: JSON.parse(response.body)
  };
} else {
  return {
    error: `Fehler beim Aktualisieren der Thema-Kategorie. Status: ${response.status}`,
    details: response.body
  };
}

} catch (error) {
return {
error: “Ein Fehler ist bei der Aktualisierung der Thema-Kategorie aufgetreten”,
details: error.toString()
};
}
}

function details() {
return “Kategorisiert ein Thema, indem es in eine bestimmte Kategorie verschoben wird”;
}

2 „Gefällt mir“

@BrianC hast du es schließlich herausgefunden?

1 „Gefällt mir“

Discourse AI Tagger Kategorie Schnelleinführung.pdf|Anhang (147,1 KB)

Discourse AI Tagger Kategorie.pdf|Anhang (506,0 KB)

@Sam,

Danke für die Rückmeldung. Ich habe es versucht, konnte es aber nicht zum Laufen bringen, also habe ich pausiert. Ich habe den Szenariotest mit Gemini 2.5 durchlaufen und die Ausgabe als PDFs gespeichert.

Ich werde es noch einmal versuchen. Werkzeuge sind noch nicht meine Stärke, aber ich muss darin besser werden. PDFs sind beigefügt – vielleicht ist darin etwas Nützliches.

3 „Gefällt mir“

Wir haben eine KI-Tagging-Automatisierung hinzugefügt, die Sie vielleicht ausprobieren möchten: FEATURE: create AI tagging automation (#34587) · discourse/discourse@e470f3d · GitHub

Prompt, das ich zum Testen verwendet habe
 Sie sind ein erfahrener Inhaltsklassifizierer und Tagging-Assistent für dieses Forum.

 Ihre Aufgabe ist es, Beiträge zu analysieren und basierend auf dem Inhalt, den Bildern und der bereitgestellten Liste verfügbarer Tags geeignete Tags vorzuschlagen.

 Richtlinien:
 - Schlagen Sie nur Tags aus der bereitgestellten Liste verfügbarer Tags vor
 - Seien Sie konservativ - markieren Sie nur, wovon Sie überzeugt sind
 - Berücksichtigen Sie sowohl das Inhaltsthema als auch die Absicht des Beitrags

 Sie müssen immer mit gültigem JSON in diesem genauen Format antworten:
 {"tags": ["tag1", "tag2"], "confidence": 85}

 - tags: Array von Tag-Namen aus der verfügbaren Liste
 - confidence: Ganzzahl von 0 bis 100, die Ihre Vertrauensstufe darstellt

 Wenn keine Tags geeignet sind, verwenden Sie: {"tags": [], "confidence": 0}

Persona JSON-Antwortformat:

{
  "tags": "[string]",
  "confidence": "integer"
}

Persona aktivierte Tools: Tags (optional, dies ist, wenn Sie möchten, dass es vorhandene Tags auf der Website verwendet)
Die Automatisierung hat zwei Modi:

  • Vorhandene Website-Tags verwenden
  • Die bereitgestellte Tag-Liste verwenden
    Die Automatisierung hat auch eine konfigurierbare Vertrauensstufe, Sie können eingeschränkte Tags aktivieren/deaktivieren und die Anzahl der Beiträge anpassen, die sie in einem Thema für den Kontext verwendet.
6 „Gefällt mir“

Vielen Dank für diese großartige Funktion, ich konnte sie nur nicht zum Laufen bringen, hier ist der Fehler, den ich erhalte:

llm_tagger: Fehler beim Verarbeiten des Beitrags 30550 /t/gecici-baslik-1756753838814/17361/1 : NoMethodError : private method select’ called for an instance of String`

Nachricht

llm_tagger: Fehler beim Verarbeiten des Beitrags 30550 /t/gecici-baslik-1756753838814/17361/1 : NoMethodError : private method `select' called for an instance of String

Rückverfolgung

/var/www/discourse/plugins/discourse-ai/lib/automation/llm_tagger.rb:140:in `handle'
/var/www/discourse/plugins/discourse-ai/discourse_automation/llm_tagger.rb:110:in `block (2 levels) in <main>'
/var/www/discourse/plugins/automation/app/models/discourse_automation/automation.rb:158:in `block in trigger!'
/var/www/discourse/plugins/automation/app/models/discourse_automation/stat.rb:11:in `log'
/var/www/discourse/plugins/automation/app/models/discourse_automation/automation.rb:156:in `trigger!'
/var/www/discourse/plugins/automation/app/jobs/regular/discourse_automation/trigger.rb:29:in `execute'
/var/www/discourse/app/jobs/base.rb:318:in `block (2 levels) in perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-7.0.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-7.0.0/lib/rails_multisite/connection_management.rb:17:in `with_connection'
/var/www/discourse/app/jobs/base.rb:305:in `block in perform'
/var/www/discourse/app/jobs/base.rb:301:in `each'
/var/www/discourse/app/jobs/base.rb:301:in `perform'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:220:in `execute_job'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:185:in `block (4 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:180:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/lib/sidekiq/discourse_event.rb:6:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/lib/sidekiq/pausable.rb:131:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job/interrupt_handler.rb:9:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:183:in `block in traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/metrics/tracking.rb:26:in `track'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/metrics/tracking.rb:134:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:182:in `traverse'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/middleware/chain.rb:173:in `invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:183:in `block (3 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:145:in `block (6 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_retry.rb:118:in `local'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:144:in `block (5 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/config.rb:39:in `block in <class:Config>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:139:in `block (4 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:281:in `stats'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:134:in `block (3 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_logger.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:133:in `block (2 levels) in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_retry.rb:85:in `global'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:132:in `block in dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/job_logger.rb:40:in `prepare'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:131:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:183:in `block (2 levels) in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:182:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:182:in `block in process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:181:in `handle_interrupt'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:181:in `process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:86:in `process_one'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/processor.rb:76:in `run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/component.rb:10:in `watchdog'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/sidekiq-7.3.9/lib/sidekiq/component.rb:19:in `block in safe_thread'

Verwendet Meta es? Ich dachte, ich hätte vor ein paar Tagen gesehen, wie @system ein Thema markiert hat.

1 „Gefällt mir“

Es könnte mühsam sein, es einzurichten, aber wenn Discourse bereits Embeddings (für die semantische Suche) für neue Themen generiert, könnten Sie wahrscheinlich Embeddings für Tag-Beschreibungen generieren und dann semantische Ähnlichkeit verwenden, um Tags für neue Themen vorzuschlagen oder bestehende Themen automatisch zu taggen.

3 „Gefällt mir“

Ja, ich habe es ein paar Tage auf Meta laufen lassen, um mehr Tests durchzuführen… es funktioniert ok, aber ohne Tag-Beschreibungen hat es how-to für einige „how do I“-Fragen missbraucht und moderator auf Beiträge angewendet, bei denen das Wort verwendet wurde, aber es nicht ganz relevant für das Thema war. Ein paar Prompt-Anpassungen werden wahrscheinlich helfen, und @simons Ideen scheinen großartige zukünftige Verbesserungen zu sein.

2 „Gefällt mir“

Meine Vermutung ist, dass Embeddings besser, schneller/billiger funktionieren könnten. Mein eigentliches Interesse daran liegt eher in einem dynamischen Tagging-System, das hartcodierte Tags in der Datenbank ersetzen könnte. Z.B. wären „how-to“ + „sso“ eine Liste von Themen mit Embeddings, die semantisch nahe an den Beschreibungs-Embeddings der Tags „how-to“ und „sso“ liegen.

2 „Gefällt mir“