benutzerdefinierten – chatgpz.de – KI-Tools & Praxiswissen http://chatgpz.de Unabhängige Tests, Anleitungen und Hintergründe zu KI-Tools. Sat, 20 Jun 2026 08:18:53 +0000 de-DE hourly 1 https://wordpress.org/?v=6.4.2 234900186 Erstellen eines benutzerdefinierten GStreamer-Plugins für NVIDIA DeepStream http://chatgpz.de/artificial-intelligence/erstellen-eines-benutzerdefinierten-gstreamer-plugins-fuer-nvidia-deepstream/ http://chatgpz.de/artificial-intelligence/erstellen-eines-benutzerdefinierten-gstreamer-plugins-fuer-nvidia-deepstream/#respond Sat, 20 Jun 2026 08:18:52 +0000 https://chatgpz.de/artificial-intelligence/erstellen-eines-benutzerdefinierten-gstreamer-plugins-fuer-nvidia-deepstream/ [ad_1]

eine produktionsbereite Pipeline für Multi-Stream-Videoanalysen: hardwarebeschleunigte Dekodierung, Verfolgung, Bildschirmanzeige und Nachrichtenvermittlung, alles über GStreamer verkabelt. Für nach TensorRT exportierte Standarderkennungsmodelle: nvinfer kümmert sich um alles.

Der allgemeine Fall hat jedoch Grenzen. Imaginative and prescient-Language-Modelle, benutzerdefinierte Nachbearbeitung, gedrehte Begrenzungsrahmen oder die Notwendigkeit, Modelle zur Laufzeit im laufenden Betrieb auszutauschen – das sind Orte, an denen … nvinfer’s Annahmen scheitern. Manchmal haben Sie einen ausgereiften PyTorch-Inferenzstapel, den Ihr Workforce sorgfältig abgestimmt hat, und Sie möchten, dass DeepStream aufruft Das anstatt es in einer Konfigurationsdatei erneut zu implementieren.

Es ist erwähnenswert, dass speziell für Modelle der YOLO-Familie DeepStream-Yolo von Marcos Luciano hat bereits hervorragende Arbeit bei der Implementierung der benutzerdefinierten Nachbearbeitung in C++ geleistet. Wenn C++ auf dem Tisch ist, beginnen Sie dort. Dieser Artikel nimmt einen anderen Standpunkt ein: das gleiche Ergebnis vollständig in Python zu erzielen, indem ein benutzerdefiniertes GStreamer-Plugin mit verwendet wird pyservicemaker ohne Einbußen beim Durchsatz.

Die wichtigste Erkenntnis, die dies ermöglicht: nachgelagerte Elemente wie nvtracker, nvdsosdUnd nvmsgconv Es ist egal, welches Component Erkennungsmetadaten erzeugt hat. Schreiben Sie korrekt in die Metadatenstruktur von DeepStream und der Relaxation des Ökosystems funktioniert so nvinfer warfare nie auf dem Bild.

DeepStream-Metadaten

Jeder Puffer, der durch eine DeepStream-Pipeline fließt, enthält mehr als Pixeldaten. Von dem Second an, in dem Frames durchlaufen werden nvstreammuxjede GstBuffer hat eine NvDsBatchMeta daran befestigte Struktur. Die Hierarchie ist unkompliziert und kann im gefunden werden offizielle Dokumentation.

NvDsBatchMeta
├── NvDsUserMeta                        (batch-level customized metadata)
└── NvDsFrameMeta                       (one per supply stream)
    ├── NvDsUserMeta                    (frame-level customized metadata)
    └── NvDsObjectMeta                  (one per detected object)
        ├── NvDsClassifierMeta
        └── NvDsUserMeta                (object-level customized metadata)

NvDsBatchMeta beschreibt die gesamte Cost. Jede NvDsFrameMeta entspricht einem Quellstream und enthält Informationen auf Body-Ebene wie die Quell-ID und die Body-Nummer. Jede NvDsObjectMeta stellt eine einzelne Erkennung dar. Das heißt, wenn unser Plugin Erkennungen schreibt, schreiben wir eine NvDsObjectMeta für jeden.

Das Wichtigste, was man verstehen muss, ist das Nichts davon ist Eigentum von nvinfer. Es handelt sich um einen Shared-Information-Vertrag. Jedes GStreamer-Component in der Pipeline kann daraus lesen, darauf schreiben oder beides:

  • nvtracker liest Objektbegrenzungsrahmen und schreibt Monitoring-IDs.
  • nvdsosd liest Kästchen und Beschriftungen, um Überlagerungen zu zeichnen.
  • nvmsgconv liest die gesamte Struktur, um Nachrichtennutzlasten zu erzeugen.

Unser benutzerdefiniertes Plugin schreibt Erkennungen einfach auf die gleiche Weise in diese Struktur nvinfer würde, und alles nachgelagerte nimmt sie ohne Änderung auf. Eine wichtige Einschränkung, die es zu verstehen gilt, bevor wir Code schreiben: NvDsObjectMeta Instanzen kann nicht direkt aus Python erstellt werden. Der Versuch, die Klasse zu instanziieren, löst ein aus No constructor outlined! Fehler zur Laufzeit.

Der Grund ist architektonischer Natur. DeepStream verwaltet seine Metadatenobjekte über Speicherpools, vorab zugewiesene Blöcke, die über Frames hinweg recycelt werden, um den Overhead durch wiederholte Heap-Zuweisung und -Freigabe in einer Pipeline mit hohem Durchsatz zu vermeiden. Diese Swimming pools sind Eigentum von NvDsBatchMeta und leben auf der C-Seite der Grenze. Die Python-Bindungen machen den Zugriff auf diese Swimming pools verfügbar, machen aber bewusst keinen Python-seitigen Konstruktor verfügbar, da beim Erstellen eines NvDsObjectMeta Außerhalb des Swimming pools würde das Lebenszyklusmanagement umgangen werden, das die Speichernutzung von DeepStream vorhersehbar hält. Der richtige Weg, einen zu bekommen, besteht darin, die Cost danach zu fragen: batch_meta.acquire_object_meta()wodurch Sie eine vorab zugewiesene Instanz aus dem Pool erhalten. Wenn der Body fertig ist, gibt DeepStream ihn automatisch an den Pool zurück.

Die Python-Brücke: pyservicemaker

Um mit den Metadaten von DeepStream aus Python zu interagieren, verwenden wir pyservicemakerNVIDIAs aktuelles, unterstütztes Python SDK für DeepStream. Der offizielle Dokumentation behandelt die Grundlagen von Pipelines und Flows, zeigt jedoch nicht, wie man Metadaten aus einem benutzerdefinierten Inferenzelement schreibt und anfügt. Das ist die Lücke, die dieser Artikel füllt.

Die Schlüsselabstraktion ist BatchMetadataOperator. Unterklassifizierung und Implementierung handle_metadata(batch_meta) gibt Ihnen Zugriff auf alles NvDsBatchMeta für jeden Puffer, der durch die Pipeline fließt. Von da an ist das Iterieren von Frames genauso einfach wie das Verwenden batch_meta.frame_items und Anbringen eines Erkennungsobjekts.

pyservicemaker bietet auch eine Buffer Wrapper herum Gst.Buffer das entlarvt batch_meta direkt und, was wichtig ist, ein extract(batch_id) Methode, die ein DLPack-Deal with an den GPU-Speicher jedes Frames zurückgibt. Dadurch ist eine Zero-Copy-Inferenz möglich, da wir den Body direkt an TensorRT übergeben können, ohne jemals die GPU zu verlassen.

Anstatt zu benutzen BatchMetadataOperator Standalone über eine Sonde, falten wir das gleiche Muster direkt in unsere benutzerdefinierten Plugins do_transform_ip Methode, die uns neben dem Metadatenzugriff auch die Kontrolle über den Lebenszyklus, die Eigenschaften und die Obergrenzenverhandlung des Parts gibt. Aber zuerst müssen wir dieses Plugin erstellen.

Ein erkennbares Python-GStreamer-Plugin

GStreamer erkennt Plugins zur Laufzeit, indem es die in aufgelisteten Verzeichnisse scannt GST_PLUGIN_PATH. Speziell für Python-Plugins sieht es in a aus python/ Unterverzeichnis innerhalb jedes dieser Pfade. Das bedeutet, dass Ihr Plugin nur ein ist .py Datei an der richtigen Stelle abgelegt, keine Kompilierung, kein CMake, keine gemeinsam genutzte Bibliothek. Der Nachteil besteht darin, dass das Registrierungsmuster streng ist und ein Fehler zu stillen Fehlern führt, die wirklich schwer zu debuggen sind.

$GST_PLUGIN_PATH/
└── python/
    └── gstexampleplugin.py   # your plugin

Satz GST_PLUGIN_PATH auf das übergeordnete Verzeichnis zeigen und GStreamer findet es python/gstexampleplugin.py automatisch beim nächsten Pipeline-Lauf.

Das Plugin-Skelett

Hier ist das minimale Grundgerüst für ein Passthrough-Inferenzelement: Es empfängt gestapelte Videopuffer, führt Inferenz aus, hängt Metadaten an und übergibt den Puffer unverändert an den Downstream.

import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstBase', '1.0')
from gi.repository import Gst, GstBase, GObject

import torch
from pyservicemaker import Buffer

GST_PLUGIN_NAME = "gstexampleplugin"

Gst.init(None)

class GstExamplePlugin(GstBase.BaseTransform):

    __gstmetadata__ = (
        'GstExamplePlugin',                     # title
        'Filter/Impact/Video',                  # classification
        'Customized inference ingredient',             # description
        'Your Identify'                             # creator
    )

    src_format = Gst.Caps.from_string(
        "video/x-raw(reminiscence:NVMM), format=RGB, "
        "width=(int)( 1, 2147483647 ), peak=(int)( 1, 2147483647 ), "
        "framerate=(fraction)( 0/1, 2147483647/1 )"
    )
    sink_format = Gst.Caps.from_string(
        "video/x-raw(reminiscence:NVMM), format=RGB, "
        "width=(int)( 1, 2147483647 ), peak=(int)( 1, 2147483647 ), "
        "framerate=(fraction)( 0/1, 2147483647/1 )"
    )

    src_pad_template = Gst.PadTemplate.new(
        "src", Gst.PadDirection.SRC, Gst.PadPresence.ALWAYS, src_format
    )
    sink_pad_template = Gst.PadTemplate.new(
        "sink", Gst.PadDirection.SINK, Gst.PadPresence.ALWAYS, sink_format
    )
    __gsttemplates__ = (src_pad_template, sink_pad_template)

    __gproperties__ = {
        'model-engine': (
            str,
            'TensorRT engine path',
            'Path to the .engine file',
            '',
            GObject.ParamFlags.READWRITE
        ),
        'confidence-threshold': (
            float,
            'Confidence threshold',
            'Minimal confidence to connect a detection',
            0.0, 1.0, 0.5,
            GObject.ParamFlags.READWRITE
        ),
    }

    def __init__(self):
        tremendous().__init__()
        self.model_engine = ''
        self.confidence_threshold = 0.5
        self.engine = None

    def do_get_property(self, prop):
        if prop.title == 'model-engine':
            return self.model_engine
        elif prop.title == 'confidence-threshold':
            return self.confidence_threshold

    def do_set_property(self, prop, worth):
        if prop.title == 'model-engine':
            self.model_engine = worth
        elif prop.title == 'confidence-threshold':
            self.confidence_threshold = worth

    def do_start(self):
        # Load your TensorRT engine right here
        self.engine = load_engine(self.model_engine) # This operate ought to be carried out
        return True

    def do_transform_ip(self, gst_buffer: Gst.Buffer) -> Gst.FlowReturn:
        """In-place remodel: connect metadata, cross buffer unchanged."""
        buffer = Buffer(gst_buffer)
        batch_meta = buffer.batch_meta

        frames = ()
        for frame_meta in batch_meta.frame_items:
            t = torch.utils.dlpack.from_dlpack(buffer.extract(frame_meta.batch_id))
            frames.append
        batch = torch.stack(frames, dim=0)

        # Run your mannequin inference
        outcomes = self.engine(batch)
        
        # Now we might want to iterate over the outcomes for every body
        # and connect it to the object_meta in case it's detection/segmentation
        # in any other case we are able to do it as user_meta
        # The next is pseudocode, which is determined by your inference
        for frame_meta in batch_meta.frame_items:
            for det in outcomes:
                obj = batch_meta.acquire_object_meta()
                # Fill the obj with every detection
                ...
                frame_meta.append(obj)
 
        return Gst.FlowReturn.OK


# --- Registration ---
GObject.type_register(GstExamplePlugin)
__gstelementfactory__ = (GST_PLUGIN_NAME, Gst.Rank.NONE, GstExamplePlugin)

Ein paar Dinge, die es zu diesem Skelett zu beachten gilt:

GstBase.BaseTransform ist die richtige Basisklasse für einen In-Place-Filter, der einen Puffer empfängt, ihn ändert (durch Anhängen von Metadaten) und ihn an den Downstream weitergibt. Wir überschreiben do_transform_ip statt do_transform weil wir keinen neuen Ausgabepuffer zuweisen.

__gstmetadata__ Und __gsttemplates__ sind nicht optionally available. Ohne sie registriert GStreamer das Component nicht. Die Großbuchstabenzeichenfolge video/x-raw(reminiscence:NVMM) teilt GStreamer mit, dass dieses Component mit NVIDIA-Speicher arbeitet, was wichtig ist, um in einer DeepStream-Pipeline auf der GPU zu bleiben.

__gproperties__ entlarvt model-engine Und confidence-threshold als erstklassige GStreamer-Eigenschaften, was bedeutet, dass Sie sie über a festlegen können gst-launch Befehlszeile oder aus dem Python-Pipeline-Code, ohne die Quelle zu berühren.

Für die Registrierung sind die letzten beiden Zeilen erforderlich: GObject.type_register teilt dem GObject-Typsystem die Klasse mit und __gstelementfactory__ teilt GStreamer mit, welcher Elementname verfügbar gemacht und welche Klasse instanziiert werden soll.

Überprüfung des Plugins. Sobald die Datei vorhanden und der Cache leer ist, überprüfen Sie die Registrierung mit:

GST_PLUGIN_PATH=/path/to/your/plugins gst-inspect-1.0 gstexampleplugin

Sie sollten die Elementmetadaten, Pad-Vorlagen und beide Eigenschaften aufgelistet sehen. Wenn Sie sie sehen, kennt GStreamer Ihr Plugin und Sie können es in eine Pipeline einfügen.

Beispiel einer Finish-to-Finish-Inferenz mit Ultralytics

Nachdem das Plugin-Gerüst vorhanden ist, ist es an der Zeit, die Inferenzlogik auszufüllen. Der vollständige Arbeitscode ist als verfügbar GitHub Gist. Sobald es auffindbar ist, können Sie es wie zuvor überprüfen oder die Pipeline starten. Hier ist ein einfaches Beispiel, das lediglich eine Inferenz durchführt und die fps anzeigt:

gst-launch-1.0 -v 
  nvstreammux title=m width=1280 peak=720 batch-size=1 
    batched-push-timeout=33000 ! 
  nvvideoconvert nvbuf-memory-type=0 ! 
  'video/x-raw(reminiscence:NVMM), format=RGB' ! 
  gstyoloplugin model-path=/path/to/yolo26s.engine ! 
  fpsdisplaysink text-overlay=false silent=false sync=false 
    video-sink=fakesink 
  uridecodebin uri=file:///path/to/video.mp4 ! m.sink_0

Den Code prüfen

Kompatibilitätsproblem

Wenn Sie den Code lesen, ist Ihnen möglicherweise aufgefallen, dass wir den überschreiben tuple Objekt, aber nur drinnen ultralytics.nn.backends.tensorrt Modul, da dort das Downside liegt. Es gibt einen bekannten Kompatibilitätsgrenzfall zwischen TensorRT-Python-Bindungen und die GStreamer Python-Wrapper-Framework (PyGObject) Dadurch wird Ihre Pipeline mit der berüchtigten Meldung „Segmentierungsfehler (Kern-Dump)“ zum Absturz gebracht. Aus diesem Grund warfare es notwendig, diesen Codeausschnitt zu erstellen, der uns hilft, das beabsichtigte Verhalten beizubehalten:

import ultralytics.nn.backends.tensorrt as trt_backend

_original_tuple = tuple

def safe_tuple(obj):
    if "tensorrt" in sort(obj).__module__ and kind(obj).__name__ == "Dims":
        return _original_tuple(obj(i) for i in vary(len(obj)))
    return _original_tuple(obj)

trt_backend.tuple = safe_tuple

Dies ersetzt die tuple Referenz innerhalb des Namensraums des Ultralytics-Backends zur Laufzeit mit einer Model, die auf den indexbasierten Zugriff zurückgreift Dims Gegenstände, alles andere bleibt unberührt. Das ist zwar nicht elegant, aber chirurgisch und muss beim Import erfolgen, bevor ein Modell instanziiert wird.

Die Inferenzschleife

Die Inferenzschleife selbst ist recht einfach:

  1. Extrahieren Sie die Frames aus den Puffern
  2. Vorverarbeitung + Inferenz
  3. Hängen Sie die Ergebnisse an die Objektmetadaten jedes Frames an, wenn nachgelagerte Elemente der Pipeline Deepstream-Plugins sind.

Unten finden Sie den Snippet-Code für Zero-Copy mit DLPack:

frames = ()
for frame_meta in batch_meta.frame_items:
    t = torch.utils.dlpack.from_dlpack(buffer.extract(frame_meta.batch_id))
    frames.append
batch = torch.stack(frames, dim=0)

Vorverarbeitung der Eingabe

YOLO-Modelle, beim Durchlaufen von a torch.TensorErwarten Sie eine feste Eingabeform (N, 3, 640, 640) laut Dokumentation. Es lösen sich jedoch Rahmen nvstreammux wird die Auflösung haben, die Ihre Quelle hat. Der verwendete Ansatz ist Letterboxing: Skalieren Sie den Rahmen so, dass er in die Zielabmessungen passt und dabei das Seitenverhältnis beibehält, und füllen Sie dann den verbleibenden Raum auf. Die wichtigste Erkenntnis hierbei ist, dass wir dies vollständig auf der GPU und über den gesamten Stapel hinweg auf einmal tun können, ohne jemals den CPU-Speicher zu berühren.

Mit Body-Extraktion, Letterboxing, Inferenz und Koordinateninvertierung erfolgt alles in einem einzigen Schritt auf der GPU do_transform_ip Aufruf verhält sich das Plugin genauso nvinfer aus der Perspektive jedes Downstream-Parts, aber mit der vollen Flexibilität eines Python-Inferenzstapels darunter.

Von hier aus übernimmt der Relaxation der DeepStream-Pipeline: nvtracker vergibt IDs, nvdsosd zeichnet Überlagerungen und nvmsgconv Serialisiert Nutzdaten.

Praktische Erkenntnisse und nächste Schritte

Wenn Sie bis hierher gefolgt sind, haben Sie ein funktionierendes Muster zum Ersetzen nvinfer mit Ihrem eigenen Python-Inferenzelement, und was noch wichtiger ist, Sie verstehen Warum jedes Stück ist so wie es ist.

Das Muster verallgemeinert sich. Alles, was hier beschrieben wird: das Plugin-Gerüst, die Batch-Vorverarbeitung und der Metadatenanhang, ist modellunabhängig. Austausch von Ultralytics YOLO gegen RFDETR von Roboflow ist unkompliziert und der GStreamer und pyservicemaker Gerüst bleibt identisch. Dasselbe gilt auch für exotischere Architekturen: NVIDIAs eigene deepstream_reference_apps Das Repository enthält ein funktionierendes Beispiel für die Integration eines Imaginative and prescient-Language-Modells über vLLM unter Verwendung genau dieses Plugin-Ansatzes, den es sich zu studieren lohnt, wenn Sie über die Erkennung hinaus in das Videoverständnis vordringen.

Der vollständige Plugin-Code ist als verfügbar GitHub Gist. Wenn Sie etwas darauf aufbauen: ein anderes Modell, ein Multi-Stream-Setup oder eine VLM-Integration, wäre ich gespannt, wie es weitergeht. Viel Spaß beim Codieren!

[ad_2]

]]>
http://chatgpz.de/artificial-intelligence/erstellen-eines-benutzerdefinierten-gstreamer-plugins-fuer-nvidia-deepstream/feed/ 0 19400
Wenn es mit benutzerdefinierten Kalendern in tabellarischen Modellen seltsam wird http://chatgpz.de/machine-learning/wenn-es-mit-benutzerdefinierten-kalendern-in-tabellarischen-modellen-seltsam-wird/ http://chatgpz.de/machine-learning/wenn-es-mit-benutzerdefinierten-kalendern-in-tabellarischen-modellen-seltsam-wird/#respond Fri, 10 Apr 2026 20:50:58 +0000 https://chatgpz.de/machine-learning/wenn-es-mit-benutzerdefinierten-kalendern-in-tabellarischen-modellen-seltsam-wird/ [ad_1]

Einführung

Nach der anfänglichen Euphorie über die neue kalenderbasierte Zeitintelligenz begann ich, mich eingehender mit der neuen Funktion zu befassen, um zu sehen, was diese neuen Möglichkeiten in der realen Welt bedeuten.

Im Abschnitt „Referenzen“ am Ende dieses Artikels finden Sie mehrere Hyperlinks dazu, darunter einen SQLBI-Artikel, der Sie tief in das Thema einführt.

Ich empfehle dringend, diese Artikel zu lesen, um ein gutes Verständnis zu erlangen.

Aber mit der Zeit wurde mir klar, dass dieses glänzende neue Function auch Schattenseiten hat.

Nun zeige ich Ihnen vier Beispiele, bei denen ich interessante Effekte entdeckt habe.

Wenn möglich, werde ich für jedes Downside Problemumgehungen oder Lösungen anbieten.

Einrichtung der Kalender

Für diesen Artikel habe ich zwei Energy BI-Berichte mit jeweils zwei Datumstabellen verwendet, um Interferenzen zu vermeiden. Alle Datumstabellen haben dieselbe Quelltabelle.

Eine mögliche Interferenz zwischen Kalendern wird beschrieben Hier.

Für den gregorianischen Kalender habe ich diese Konfiguration verwendet:

Abbildung 1 – Konfiguration des Gregorianischen Kalenders (Abbildung vom Autor)

Für den wochenbasierten Kalender habe ich diese Konfiguration verwendet:

Abbildung 2 – Wochenbasierte Kalenderkonfiguration (Abbildung vom Autor)

Der Wochenkalender enthält die Spalte „YearOfWeek“ für die Kategorie „Jahr“.

Diese Spalte enthält die wochenbündige Jahresangabe, die für einen solchen Kalender benötigt wird. Diese Spalte basiert auf der ISO-Wochendefinition. Jedes Jahr beginnt am Montag der ersten Woche.

Eine Erklärung zur ISO-Woche finden Sie hier Hier.

Beide Energy BI-Datenmodelle verwendeten dieselbe Konfiguration.

Vorherige Monate und unterschiedliche Monatslängen

Okay, schauen wir uns zunächst Monate mit unterschiedlicher Länge an.

Ich beschreibe diesen Fall, um Ihnen die Unterschiede zur klassischen Zeit-Intelligenz-Logik bewusst zu machen.

Ich habe zwei Maßnahmen erstellt:

On-line Gross sales (PM) =

    CALCULATE((On-line Gross sales)

                ,DATEADD('Date'(Date), -1, MONTH)

                )

Und dieser verwendet den gregorianischen Kalender:

On-line Gross sales (PY Gregorian) =

    CALCULATE((On-line Gross sales)

                ,DATEADD('Gregorian Calendar', -1, YEAR)

                )

Ich habe beides zu einem Tabellenvisual hinzugefügt.

Schauen Sie sich nun die Unterschiede zwischen diesen beiden Maßnahmen für März an:

Abbildung 3 – Ergebnisse der beiden Maßnahmen für Ende März 2024. Beachten Sie die unterschiedlichen Ergebnisse für die letzten drei Termine. (Abbildung vom Autor)

Obwohl dieses Ergebnis sehr interessant ist, schauen Sie sich dieses an:

Abbildung 4 – Ergebnisse der beiden Maßnahmen für Ende Februar 2024. Beachten Sie die unterschiedlichen Ergebnisse für die letzten drei Termine. (Abbildung vom Autor)

In beiden Fällen ist das Ergebnis sehr unterschiedlich.

Während die Messung mit klassischer Zeitintelligenz den gleichen Wert für die letzten drei Tage im März zeigt, lassen die Ergebnisse für Februar die letzten Tage im Januar weg.

Die kalenderbasierte Messung schneidet viel besser ab.

Der entscheidende Punkt hierbei ist, dass die Zeilensummen der Summe entsprechen, die in der Zeile „Gesamt“ angezeigt wird.

Darüber hinaus ist die DATEADD() Die Funktion verfügt jetzt über zwei zusätzliche Parameter, die sich auf die Ergebnisse für Monate mit ungleicher Länge auswirken.

Obwohl es nicht seltsam ist, handelt es sich definitiv um ein anderes Verhalten der Funktion, dessen Sie sich bewusst sein müssen. Dies gilt überall dort, wo Perioden nicht gleich lang sind. Ich werde später darauf zurückkommen.

Was passiert mit dem Vorjahr?

Jetzt kommt die erste seltsame State of affairs.

Beachten Sie die folgende Tabelle unter Verwendung einer Kennzahl mit einem DATEADD()-Aufruf unter Verwendung des Gregorianischen Kalenders für PY:

Abbildung 5 – Vergleich der PY-Werte professional Tag für März 2022 vs. 2023 (Abbildung vom Autor)

Wie Sie sehen, sieht alles intestine aus.

Schauen Sie sich nun die Ergebnisse an, wenn Sie 2024 mit 2025 vergleichen:

Abbildung 6 – Schauen Sie sich nun die Ergebnisse an, wenn Sie die PJ-Werte für 2024 (das ein Schaltjahr warfare) und 2025 (Abbildung des Autors) vergleichen.

Wie Sie sehen können, sind die Vorjahreswerte für März 2025 um 1 Tag verschoben.

Das ist nicht korrekt.

Schlimmer noch: Wenn man die Gesamtwerte der Monate vergleicht, sind sie zwischen 2024 und dem Vorjahresmaß im Jahr 2025 gleich.

Dieser Effekt ist bis Dezember zu beobachten, wobei die Ergebnisse wie folgt lauten:

Abbildung 7 – Vergleich der Ergebnisse für Dezember 2024 und 2025. Wie Sie sehen können, fasst der DAX die letzten beiden Tage zusammen (Abbildung vom Autor)

Dies ist derselbe Effekt, den wir bei der zuvor gezeigten Kennzahl „Vormonat“ beobachten können, da diese beiden Jahre nicht gleich lang sind.

Dieser seltsame Effekt ist darauf zurückzuführen, wie DAX Ergebnisse basierend auf der Kalenderhierarchie berechnet.

Der Mechanismus heißt „Distance from Guardian“.

Aber das Guardian wird durch den dritten Parameter von DATEADD() definiert: Yr

Daher berechnet DATEADD() den Abstand vom Jahresanfang und gibt das Ergebnis unter Verwendung des gleichen Abstands für das vorherige Jahr zurück.

Eine Lösung für dieses Downside besteht darin, sicherzustellen, dass alle Monate gleich lang sind.

In meinem ersten Artikel über diese neue Funktion, der im Abschnitt „Referenzen“ weiter unten verlinkt ist, habe ich eine benutzerdefinierte Datumstabelle und einen Kalender mit 31 Tagen für alle Monate erstellt.

Wenn Sie denselben Vorgang mit diesem Kalender ausführen, verschwindet der Effekt:

Abbildung 8 – Jahresvergleich für 2024 und 2025 unter Verwendung des benutzerdefinierten Kalenders mit 31 Tagen für alle Monate (Abbildung vom Autor)

Dieser Ansatz funktioniert zwar einwandfrei, erfordert jedoch einen benutzerdefinierten Kalender, der andere Probleme verursachen oder bestimmte Anforderungen nicht erfüllen kann. Vor allem, weil die Datumsspalten keine echten Daten enthalten und die Spalte „date_real“ Lücken aufweist. Dies kann bei der Verwendung in benutzerdefinierten Berechnungen zu Problemen führen.

Eine andere Lösung besteht darin, das Geschäftsjahr um 12 Monate zurück zu berechnen:

On-line Gross sales (-12 M Gregorian) =

    CALCULATE((On-line Gross sales)

                ,DATEADD('Gregorian Calendar', -12, MONTH)

                )

Und das sind die Ergebnisse der neuen Maßnahme:

Abbildung 9 – Ergebnisse beim Vergleich der Verwendung von DATEADD() mit Jahr oder Monaten (Abbildung vom Autor)

In Rot sehen Sie die gleichen Ergebnisse wie zuvor, um einen Tag verschoben.

In Grün sehen Sie die Ergebnisse für die Kennzahl mit Monatsgranularität.

Interessanterweise stimmen auch die Summen für die Quartale und die Jahre.

Im Second sehe ich kein Downside darin, diesen Ansatz zu verwenden, und ich werde ihn in Zukunft verwenden und testen.

Wöchentliche Berechnungen – Kopfkratzen

Das ist eine sehr seltsame Sache.

Schauen Sie sich das folgende Bild mit derselben Tabelle in verschiedenen Zuständen nebeneinander an:

Abbildung 10 – Wöchentliche PY-Berechnung für 2023 in zwei verschiedenen Bundesstaaten (Abbildung vom Autor)

Auf der linken Seite sehen Sie, dass alle Zeilen für 2023 identisch sind, wenn 2022 ausgeblendet ist.

Rechts sehen Sie die korrekten Werte für 2023, sie werden jedoch nur angezeigt, wenn ich mindestens eine Woche von 2022 bis zum Datum erweitere.

Aber die Werte im Jahr 2022 sind wieder alle gleich.

Ich habe dies bereits erlebt und in meinem ersten Artikel über die Kalenderfunktion gezeigt (Hyperlink unten).

In diesem Fall habe ich das Downside gelöst, indem ich eine separate Tabelle für den Wochenkalender erstellt habe. Doch dieses Mal klappte es nicht.

Ich musste das Datenmodell von Grund auf neu erstellen und es funktionierte sofort:

Abbildung 11 – Arbeitsversion zur Berechnung des wöchentlichen PY-Werts mit einem neuen Datenmodell (Abbildung vom Autor)

Wie Sie sehen, sind die Ergebnisse korrekt.

Wenn Sie genau hinschauen, sind die PJ-Ergebnisse korrekt, um den PJ-Wert derselben Woche und desselben Wochentags des Vorjahres zu erhalten.

Ich habe keine Ahnung, was der Unterschied zwischen diesen beiden Setups ist.

Die Datumstabelle stammt in beiden Datenmodellen aus derselben Quelle und der Kalender wird mithilfe derselben Spalten definiert.

Aber ich mache mir darüber ein wenig Sorgen, weil ich den Grund nicht verstehe und keine Lösung habe. Selbst nachdem ich die TMDL-Datei für diese Tabelle überprüft hatte, konnte ich nichts finden, was auf die Ursache hindeutete.

Einen solchen Effekt habe ich nur bei wöchentlichen Berechnungen festgestellt.

Mischen wöchentlicher mit monatlicher Logik

Einer meiner Kunden möchte einen Bericht sehen, der die Tagesergebnisse für den aktuellen Monat im Vergleich zur gleichen Woche und zum gleichen Wochentag des Vorjahres zeigt.

Dies ist eine Mischung aus dem monatlichen (gregorianischen) Kalender und der wöchentlichen Logik.

Wie ich im nächsten Fall genauer zeigen werde, ordnet die Wochenlogik die Wochen und Wochentage korrekt dem Vorjahr zu. Daher sollte dies ein Downside sein.

Da die Wochen jedoch nicht mit den Monaten übereinstimmen, kann ich die Kategorie „Monat“ nicht hinzufügen. Ich erhalte bei der Validierung eine Fehlermeldung, wenn ich versuche, die Kategorie „Monat“ hinzuzufügen.

Daher kann ich keine MTD-Berechnung verwenden, da die Funktion die benötigte Kategorie nicht findet:

Abbildung 12 – Fehler bei der Verwendung von DATESMTD() mit einem Kalender ohne Monatskategorie (Abbildung vom Autor)

Ich kann der gleichen Datumstabelle keinen gregorianischen Kalender hinzufügen, da die Engine für alle Kalender in derselben Tabelle dieselbe Spalte für dieselbe Kategorie erwartet.

Siehe hier für die Stellungnahme von Microsoft hierzu.

Da ich die Spalte „YearForWeek“ für die Kategorie „Jahr“ verwende, funktioniert es nicht mit der Kategorie „Monat“, da sie nicht übereinstimmen.

Infolgedessen musste ich eine benutzerdefinierte Logik schreiben, um alle Anforderungen zu erfüllen.

Wöchentliche Berechnungen – Das ist interessant!

Um es positiv zu sagen: Ich kann Ihnen etwas zeigen, das sehr intestine funktioniert.

Erinnern Sie sich an das Downside mit den unterschiedlich langen Monaten und daran, wie sich die PJ-Werte verschoben haben?

Dieser Effekt tritt bei wöchentlichen Berechnungen nicht auf.

Abbildung 13 – Korrekte Abbildung des PY-Wertes bei der Berechnung für die Woche und die Wochentage (Abbildung vom Autor)

Wie Sie sehen, werden die Ergebnisse anhand der Woche und der richtigen Wochentage korrekt berechnet.

Wie erwartet werden die Werte nicht auf die Daten des Vorjahres abgebildet, sondern auf die Wochentage professional Woche.

Das ist es, was ich erwarte, wenn ich die Ergebnisse nach Woche und Wochentagen betrachte.

Der Grund dafür ist, dass jede Woche gleich lang ist und die Datumstabelle so aufgebaut ist, dass sie ein solches Szenario unterstützt.

Abschluss

Wie Sie sehen, sind die Ergebnisse gemischt.

Betrachtet man die Ergebnisse früherer Zeiträume unterschiedlicher Länge (Monate oder Jahre), verschieben sich die Ergebnisse.

Wenn die Zeiträume gleich lang sind (Wochen oder benutzerdefinierter Kalender), funktioniert alles wie erwartet.

Ich warfare äußerst überrascht und verärgert, als ich die Ergebnisse für die Schaltjahre sah.

Aber glücklicherweise lässt sich dieses Downside lösen, indem man versteht, wie die neue Logik funktioniert.

Das andere Downside, bei dem ich ein schlechtes Gefühl habe, ist die inkonsistente Funktionsweise des Wochenkalenders und der PJ-Berechnung.

Das ist beunruhigend, da es nicht immer so einfach ist, ein Datenmodell neu aufzubauen.

Ein weiteres Downside, das ich habe, ist, dass SQLBI in seinem Artikel potenzielle Probleme bei der Verwendung mehrerer Kalender in derselben Datumstabelle meldet. Ich habe unten einen Hyperlink dazu hinzugefügt.

Dies führt dazu, dass mehrere Datumstabellen im selben Datenmodell erforderlich sind.

Etwas, das ich nur ungern tue.

Ich kann mir vorstellen, dass sich dies auf mehrere visuelle Elemente in einem Bericht auswirkt, bei denen die Logik verschiedener Kalender, aber mit unterschiedlichen Kategorien verwendet wird.

Die Lösung dieses Issues kann schwierig sein.

Aber wir werden sehen, wie sich diese Funktion weiterentwickeln wird, da wir uns noch in der Vorschau befinden.

Referenzen

Der SQLBI-Artikel erläutert die kalenderbasierte Zeitintelligenzfunktion im Element:

https://www.sqlbi.com/articles/introducing-calendar-based-time-intelligence-in-dax

Der SQLBI-Artikel erklärt DATEADD() mit den neuen Parametern:

https://www.sqlbi.com/articles/understanding-dateadd-parameters-with-calendar-based-time-intelligence

Microsoft-Dokumentation zur neuen Funktion (URL kann sich im Laufe der Zeit ändern):

https://be taught.microsoft.com/en-us/power-bi/transform-model/desktop-time-intelligence#calendar-based-time-intelligence-preview

Mein Artikel mit drei realen Anwendungsfällen mit den neuen Kalendern:

Mein zweiter Artikel über kalenderbasierte Zeitintelligenz und gleitenden Durchschnitt:

Ein Blogbeitrag von Chris Webb über die Auswirkungen der kalenderbasierten Zeitintelligenz:

Definition der ISO-Woche basierend auf dem ISO8601-Commonplace

https://www.calendarz.com/weblog/iso-week-numbers-explained-week-1-week-53-and-year-boundaries

Wie in meinen vorherigen Artikeln verwende ich den Contoso-Beispieldatensatz. Sie können den ContosoRetailDW-Datensatz kostenlos von Microsoft herunterladen Hier.

Die Contoso-Daten können wie beschrieben unter der MIT-Lizenz frei verwendet werden in diesem Dokument. Ich habe den Datensatz aktualisiert, um die Daten auf aktuelle Daten zu übertragen, und alle für dieses Beispiel nicht benötigten Tabellen entfernt.

[ad_2]

]]>
http://chatgpz.de/machine-learning/wenn-es-mit-benutzerdefinierten-kalendern-in-tabellarischen-modellen-seltsam-wird/feed/ 0 17744
So erstellen und entwickeln Sie einen benutzerdefinierten OpenAI-Agenten mit A-Evolve unter Verwendung von Benchmarks, Fähigkeiten, Speicher und Arbeitsbereichsmutationen http://chatgpz.de/artificial-intelligence/so-erstellen-und-entwickeln-sie-einen-benutzerdefinierten-openai-agenten-mit-a-evolve-unter-verwendung-von-benchmarks-faehigkeiten-speicher-und-arbeitsbereichsmutationen/ http://chatgpz.de/artificial-intelligence/so-erstellen-und-entwickeln-sie-einen-benutzerdefinierten-openai-agenten-mit-a-evolve-unter-verwendung-von-benchmarks-faehigkeiten-speicher-und-arbeitsbereichsmutationen/#respond Tue, 31 Mar 2026 22:38:11 +0000 https://chatgpz.de/artificial-intelligence/so-erstellen-und-entwickeln-sie-einen-benutzerdefinierten-openai-agenten-mit-a-evolve-unter-verwendung-von-benchmarks-faehigkeiten-speicher-und-arbeitsbereichsmutationen/ [ad_1]

In diesem Tutorial arbeiten wir direkt mit dem A-Evolve Framework in Colab und erstellen Sie von Grund auf eine vollständige Pipeline für evolutionäre Agenten. Wir richten das Repository ein, konfigurieren einen OpenAI-basierten Agenten, definieren einen benutzerdefinierten Benchmark und bauen unsere eigene Evolutions-Engine, um zu sehen, wie A-Evolve einen Agenten durch iterative Arbeitsbereichsmutationen tatsächlich verbessert. Durch den Code nutzen wir die Kernabstraktionen des Frameworks für Eingabeaufforderungen, Fähigkeiten, Speicher, Benchmarking und Entwicklung, die uns nicht nur helfen, zu verstehen, wie A-Evolve ausgeführt wird, sondern auch, wie es auf praktische, Colab-freundliche Weise erweitert werden kann.

import os
import sys
import json
import textwrap
import subprocess
import shutil
from pathlib import Path
from getpass import getpass
from collections import Counter, defaultdict


subprocess.check_call((sys.executable, "-m", "pip", "set up", "-q", "openai>=1.30.0", "pyyaml>=6.0", "matplotlib>=3.8"))
REPO_DIR = Path("/content material/a-evolve")
if REPO_DIR.exists():
   shutil.rmtree(REPO_DIR)
subprocess.check_call(("git", "clone", "--depth", "1", "https://github.com/A-EVO-Lab/a-evolve.git", str(REPO_DIR)))
sys.path.insert(0, str(REPO_DIR))


if not os.environ.get("OPENAI_API_KEY"):
   os.environ("OPENAI_API_KEY") = getpass("Enter your OpenAI API key: ").strip()


OPENAI_MODEL = "gpt-4o-mini"


import yaml
import matplotlib.pyplot as plt


import agent_evolve as ae
from agent_evolve.protocol.base_agent import BaseAgent
from agent_evolve.benchmarks.base import BenchmarkAdapter
from agent_evolve.engine.base import EvolutionEngine
from agent_evolve.sorts import Process, Trajectory, Suggestions, StepResult
from agent_evolve.contract.workspace import AgentWorkspace
from openai import OpenAI


shopper = OpenAI(api_key=os.environ("OPENAI_API_KEY"))


WORKSPACE_ROOT = Path("/content material/a_evolve_demo_workspace")
if WORKSPACE_ROOT.exists():
   shutil.rmtree(WORKSPACE_ROOT)


(WORKSPACE_ROOT / "prompts").mkdir(dad and mom=True, exist_ok=True)
(WORKSPACE_ROOT / "expertise").mkdir(dad and mom=True, exist_ok=True)
(WORKSPACE_ROOT / "reminiscence").mkdir(dad and mom=True, exist_ok=True)
(WORKSPACE_ROOT / "instruments").mkdir(dad and mom=True, exist_ok=True)


manifest = {
   "title": "colab-aevolve-demo-agent",
   "model": "0.1.0",
   "contract_version": "1.0",
   "agent": {
       "kind": "customized",
       "entrypoint": None
   },
   "evolvable_layers": ("prompts", "expertise", "reminiscence"),
   "reload_strategy": "sizzling"
}
with open(WORKSPACE_ROOT / "manifest.yaml", "w") as f:
   yaml.dump(manifest, f, sort_keys=False)


initial_system_prompt = textwrap.dedent("""
You're a exact text-transformation agent.


Remedy the duty precisely.
Be concise.
Return solely the ultimate reply with no rationalization except the duty explicitly asks for JSON.
""").strip()


(WORKSPACE_ROOT / "prompts" / "system.md").write_text(initial_system_prompt)

Wir bereiten die vollständige Colab-Umgebung vor, die zum Ausführen des Tutorials von Anfang bis Ende erforderlich ist. Wir installieren die erforderlichen Pakete, klonen das A-Evolve-Repository, laden die Framework-Importe und erfassen sicher den OpenAI-API-Schlüssel für den Modellzugriff. Wir definieren auch die Arbeitsbereichsstruktur und initialisieren das Manifest und die Systemeingabeaufforderung, um unserem sich entwickelnden Agenten einen gültigen Ausgangspunkt innerhalb des A-Evolve-Frameworks zu bieten.

def build_dataset():
   prepare = (
       {
           "id": "train-01",
           "rule": "json_sum",
           "enter": "Numbers: 7, 11, 4",
           "reply": '{"sum":22}'
       },
       {
           "id": "train-02",
           "rule": "json_sum",
           "enter": "Numbers: 20, 5, 3, 2",
           "reply": '{"sum":30}'
       },
       {
           "id": "train-03",
           "rule": "acronym_upper",
           "enter": "Create the acronym from: retrieval augmented technology",
           "reply": "RAG"
       },
       {
           "id": "train-04",
           "rule": "acronym_upper",
           "enter": "Create the acronym from: giant language mannequin",
           "reply": "LLM"
       },
       banana,
       zebra"
       ,
       {
           "id": "train-07",
           "rule": "vowel_parity",
           "enter": "Phrase: equation",
           "reply": "EVEN"
       },
       {
           "id": "train-08",
           "rule": "vowel_parity",
           "enter": "Phrase: schooling",
           "reply": "ODD"
       },
   )


   holdout = (
       {
           "id": "holdout-01",
           "rule": "json_sum",
           "enter": "Numbers: 100, 1, 9",
           "reply": '{"sum":110}'
       },
       {
           "id": "holdout-02",
           "rule": "acronym_upper",
           "enter": "Create the acronym from: synthetic normal intelligence",
           "reply": "AGI"
       },
       berry,
       {
           "id": "holdout-04",
           "rule": "vowel_parity",
           "enter": "Phrase: aeroplane",
           "reply": "ODD"
       },
   )
   return prepare, holdout


TRAIN_DATA, HOLDOUT_DATA = build_dataset()


def normalize_text(x: str) -> str:
   return x.strip().substitute(" ", "")


class MiniTextBenchmark(BenchmarkAdapter):
   def __init__(self):
       self.prepare = TRAIN_DATA
       self.holdout = HOLDOUT_DATA


   def get_tasks(self, cut up: str = "prepare", restrict: int = 10):
       knowledge = self.prepare if cut up == "prepare" else self.holdout
       duties = ()
       for row in knowledge(:restrict):
           duties.append(
               Process(
                   id=row("id"),
                   enter=row("enter"),
                   metadata={
                       "rule": row("rule"),
                       "reply": row("reply")
                   }
               )
           )
       return duties


   def consider(self, job: Process, trajectory: Trajectory):
       pred = trajectory.output.strip()
       gold = job.metadata("reply").strip()
       success = normalize_text(pred) == normalize_text(gold)
       element = {
           "rule": job.metadata("rule"),
           "gold": gold,
           "pred": pred,
           "enter": job.enter,
           "success": success
       }
       rating = 1.0 if success else 0.0
       return Suggestions(
           success=success,
           rating=rating,
           element=json.dumps(element, ensure_ascii=False),
           uncooked=element
       )


SKILL_ROUTING = {
   "json_sum": ("json", "sum"),
   "acronym_upper": ("acronym", "uppercase"),
   "pipe_unique_sorted_lower": ("distinctive", "sorted", "lowercase", "pipe"),
   "vowel_parity": ("vowel", "odd", "even", "parity")
}

Wir definieren die Trainings- und Holdout-Datensätze, die zur Messung des Agenten vor und nach der Evolution verwendet werden. Wir erstellen eine benutzerdefinierte Benchmark-Klasse, die jedes Beispiel in A-Evolve-Aufgaben verpackt und Vorhersagen anhand der genau erwarteten Ergebnisse bewertet. Wir richten außerdem Weiterleitungshinweise für Fertigkeiten ein, die das System darauf vorbereiten, später im Arbeitsablauf verschiedene Aufgabentypen mit den richtigen Verhaltensmustern zu verbinden.

class ColabAEResolverAgent(BaseAgent):
   def __init__(self, workspace_dir: str | Path, mannequin: str = OPENAI_MODEL):
       self.mannequin = mannequin
       tremendous().__init__(workspace_dir)


   def _pick_relevant_skills(self, job: Process):
       rule = job.metadata.get("rule", "")
       chosen = ()
       for ability in self.expertise:
           hay = f"{ability.title} {ability.description}".decrease()
           if rule == "json_sum" and ("json" in hay or "sum" in hay):
               chosen.append(ability)
           elif rule == "acronym_upper" and ("acronym" in hay or "uppercase" in hay):
               chosen.append(ability)
           elif rule == "pipe_unique_sorted_lower" and any(okay in hay for okay in ("distinctive", "sorted", "lowercase", "pipe")):
               chosen.append(ability)
           elif rule == "vowel_parity" and any(okay in hay for okay in ("vowel", "odd", "even", "parity")):
               chosen.append(ability)
       return chosen(:3)


   def remedy(self, job: Process) -> Trajectory:
       relevant_skills = self._pick_relevant_skills(job)
       relevant_skill_texts = ()
       for s in relevant_skills:
           relevant_skill_texts.append(self.get_skill_content(s.title))


       memory_text = "n".be a part of(
           (f"- {m.get('content material', '')}" for m in self.recollections(-8:))
       ).strip()


       skill_block = "nn".be a part of(relevant_skill_texts).strip()
       if not skill_block:
           skill_block = "(no expertise loaded but)"


       if not memory_text:
           memory_text = "(no reminiscence but)"


       user_prompt = textwrap.dedent(f"""
       TASK RULE: {job.metadata.get("rule")}
       TASK INPUT:
       {job.enter}


       ACTIVE SYSTEM PROMPT:
       {self.system_prompt}


       RELEVANT SKILLS:
       {skill_block}


       RECENT MEMORIES:
       {memory_text}


       Remedy the duty precisely.
       Return solely the ultimate reply.
       """).strip()


       response = shopper.chat.completions.create(
           mannequin=self.mannequin,
           temperature=0,
           messages=(
               {"function": "system", "content material": "You might be a precise text-transformation agent."},
               {"function": "consumer", "content material": user_prompt}
           )
       )


       output = (response.decisions(0).message.content material or "").strip()


       self.keep in mind(
           content material=f"Process {job.id} beneath rule {job.metadata.get('rule')} produced output: {output}",
           class="episodic"
       )


       return Trajectory(
           task_id=job.id,
           output=output,
           steps=(
               {
                   "rule": job.metadata.get("rule"),
                   "used_skills": (s.title for s in relevant_skills),
                   "system_prompt_chars": len(self.system_prompt),
                   "memory_items_seen": len(self.recollections)
               }
           )
       )


SKILL_TEMPLATES = {
   "json_sum": textwrap.dedent("""
       ---
       title: json-sum-exact
       description: Add all integers and output strict compact JSON with the one key sum.
       ---
       # JSON Sum Precise


       Process:
       1. Extract all integers from the duty enter.
       2. Add them.
       3. Return precisely one compact JSON object on this format:
          {"sum":NUMBER}
       4. Don't add areas, explanations, markdown, or additional keys.
   """).strip(),


   "acronym_upper": textwrap.dedent("""
       ---
       title: acronym-upper-exact
       description: Construct an uppercase acronym by taking the primary letter of every phrase.
       ---
       # Acronym Higher Precise


       Process:
       1. Determine the phrase after the colon.
       2. Take the primary letter of every phrase.
       3. Convert each letter to uppercase.
       4. Return solely the ultimate acronym, with no punctuation or rationalization.
   """).strip(),


   "pipe_unique_sorted_lower": textwrap.dedent("""
       ---
       title: pipe-unique-sorted-lower
       description: Normalize tokens to lowercase, deduplicate them, type ascending, and be a part of them with pipes.
       ---
       # Pipe Distinctive Sorted Decrease


       Process:
       1. Learn the token checklist after the colon.
       2. Break up by commas.
       3. Trim areas and lowercase each token.
       4. Take away duplicates.
       5. Kind alphabetically ascending.
       6. Be part of with "|" and return solely the ultimate string.
   """).strip(),


   "vowel_parity": textwrap.dedent("""
       ---
       title: vowel-parity-exact
       description: Depend vowels within the phrase and output ODD or EVEN solely.
       ---
       # Vowel Parity Precise


       Process:
       1. Learn the goal phrase after the colon.
       2. Depend vowels utilizing a, e, i, o, u.
       3. If the rely is odd, output ODD.
       4. If the rely is even, output EVEN.
       5. Return solely ODD or EVEN with no additional textual content.
   """).strip(),
}


PROMPT_APPENDIX = textwrap.dedent("""
## STRICT OUTPUT CONTRACT
- Output solely the ultimate reply.
- By no means clarify your reasoning.
- If a job expects JSON, return compact JSON with precise keys solely.
- When a related ability exists, observe it actually.
- Precise format is extra essential than being conversational.
""").strip()

Wir implementieren den benutzerdefinierten A-Evolve-Agenten, der die aktiven Eingabeaufforderungen, Fähigkeiten und den Speicher aus dem Arbeitsbereich liest und OpenAI verwendet, um jede Aufgabe zu lösen. Wir entwerfen den Agenten so, dass er relevante Fähigkeiten auswählt, aktuellen Speicher einfügt und Trajektorien in der vom Framework erwarteten Struktur zurückgibt. Wir definieren auch die Talent-Vorlagen und den strengen Ausgabevertrag, die als Hauptzutaten dienen, die die Evolutions-Engine hinzufügen kann, um die Leistung im Laufe der Zeit zu verbessern.

class ColabMutationEngine(EvolutionEngine):
   def __init__(self):
       self.cycle_count = 0


   def step(self, workspace: AgentWorkspace, observations, historical past, trial):
       self.cycle_count += 1


       failed_by_rule = defaultdict(checklist)
       for obs in observations:
           if not obs.suggestions.success:
               failed_by_rule(obs.job.metadata("rule")).append({
                   "task_id": obs.job.id,
                   "enter": obs.job.enter,
                   "gold": obs.job.metadata("reply"),
                   "pred": obs.trajectory.output
               })


       mutated = False
       summaries = ()


       current_prompt = workspace.read_prompt()
       if "STRICT OUTPUT CONTRACT" not in current_prompt:
           workspace.write_prompt(current_prompt.rstrip() + "nn" + PROMPT_APPENDIX + "n")
           mutated = True
           summaries.append("immediate hardened")


       existing_skill_names = {s.title for s in workspace.list_skills()}


       needed_rule_to_skill_name = {
           "json_sum": "json-sum-exact",
           "acronym_upper": "acronym-upper-exact",
           "pipe_unique_sorted_lower": "pipe-unique-sorted-lower",
           "vowel_parity": "vowel-parity-exact",
       }


       for rule, fails in failed_by_rule.objects():
           skill_name = needed_rule_to_skill_name(rule)
           if skill_name not in existing_skill_names:
               workspace.write_skill(skill_name, SKILL_TEMPLATES(rule))
               mutated = True
               summaries.append(f"added ability {skill_name}")


           workspace.add_memory({
               "content material": f"Cycle {self.cycle_count}: rule={rule} failed {len(fails)} time(s). Frequent failure sample: output formatting or process mismatch. Gold examples have to be adopted precisely.",
               "rule": rule,
               "examples": fails(:2)
           }, class="episodic")


       if not failed_by_rule:
           workspace.add_memory({
               "content material": f"Cycle {self.cycle_count}: all present coaching duties succeeded. Protect precise formatting conduct."
           }, class="episodic")


       abstract = " | ".be a part of(summaries) if summaries else "no mutation wanted"
       return StepResult(
           mutated=mutated,
           abstract=abstract,
           metadata={
               "failed_rules": checklist(failed_by_rule.keys()),
               "num_failed_rules": len(failed_by_rule),
               "cycle": self.cycle_count
           }
       )


def evaluate_split(agent, benchmark, cut up="prepare"):
   duties = benchmark.get_tasks(cut up=cut up, restrict=100)
   rows = ()
   complete = 0
   right = 0
   for job in duties:
       traj = agent.remedy(job)
       fb = benchmark.consider(job, traj)
       rows.append({
           "task_id": job.id,
           "rule": job.metadata("rule"),
           "enter": job.enter,
           "gold": job.metadata("reply"),
           "pred": traj.output,
           "rating": fb.rating,
           "success": fb.success
       })
       complete += 1
       right += int(fb.success)
   rating = right / max(complete, 1)
   return rating, rows


def print_table(rows, title, max_rows=20):
   print("n" + "=" * 110)
   print(title)
   print("=" * 110)
   proven = rows(:max_rows)
   for r in proven:
       print(f"({r('task_id')}) rule={r('rule')}")
       print(f"  enter : {r('enter')}")
       print(f"  gold  : {r('gold')}")
       print(f"  pred  : {r('pred')}")
       print(f"  rating : {r('rating')}  success={r('success')}")
       print("-" * 110)


def show_workspace(root: Path):
   print("n" + "=" * 110)
   print("EVOLVED WORKSPACE SNAPSHOT")
   print("=" * 110)
   for path in sorted(root.rglob("*")):
       rel = path.relative_to(root)
       if path.is_dir():
           print(f"(DIR ) {rel}/")
       else:
           print(f"(FILE) {rel}")


def show_skill_contents(root: Path):
   skill_files = sorted((root / "expertise").glob("*/SKILL.md"))
   print("n" + "=" * 110)
   print("SKILL FILES")
   print("=" * 110)
   if not skill_files:
       print("No ability information but.")
   for sf in skill_files:
       print(f"n--- {sf.dad or mum.title}/SKILL.md ---")
       print(sf.read_text())

Wir erstellen eine benutzerdefinierte Evolutions-Engine, die Fehler untersucht und entscheidet, wie der Arbeitsbereich verändert wird. Wir verwenden es, um die Eingabeaufforderung zu verschärfen, fehlende Fähigkeiten hinzuzufügen und das episodische Gedächtnis zu speichern, damit der Agent über Zyklen hinweg nach und nach bessere Formatierungen und aufgabenspezifisches Verhalten lernt. Wir definieren außerdem Auswertungs- und Berichtsdienstprogramme, die uns helfen, den Agenten zu bewerten, Vorhersagen zu überprüfen und den entwickelten Arbeitsbereich klar anzuzeigen.

benchmark = MiniTextBenchmark()
agent = ColabAEResolverAgent(WORKSPACE_ROOT, mannequin=OPENAI_MODEL)
engine = ColabMutationEngine()


baseline_train_score, baseline_train_rows = evaluate_split(agent, benchmark, cut up="prepare")
baseline_holdout_score, baseline_holdout_rows = evaluate_split(agent, benchmark, cut up="holdout")


print(f"Baseline prepare rating   : {baseline_train_score:.3f}")
print(f"Baseline holdout rating : {baseline_holdout_score:.3f}")


print_table(baseline_train_rows, "BASELINE TRAIN RESULTS")
print_table(baseline_holdout_rows, "BASELINE HOLDOUT RESULTS")


config = ae.EvolveConfig(
   batch_size=8,
   max_cycles=4,
   egl_window=2
)


evolver = ae.Evolver(
   agent=agent,
   benchmark=benchmark,
   config=config,
   engine=engine
)


consequence = evolver.run(cycles=4)


print("n" + "=" * 110)
print("A-EVOLVE RUN SUMMARY")
print("=" * 110)
print(f"Cycles accomplished : {consequence.cycles_completed}")
print(f"Remaining prepare rating: {consequence.final_score:.3f}")
print(f"Rating historical past    : {consequence.score_history}")
print(f"Converged        : {consequence.converged}")


agent.reload_from_fs()
final_train_score, final_train_rows = evaluate_split(agent, benchmark, cut up="prepare")
final_holdout_score, final_holdout_rows = evaluate_split(agent, benchmark, cut up="holdout")


print(f"nFinal prepare rating   : {final_train_score:.3f}")
print(f"Remaining holdout rating : {final_holdout_score:.3f}")


print_table(final_train_rows, "FINAL TRAIN RESULTS")
print_table(final_holdout_rows, "FINAL HOLDOUT RESULTS")


show_workspace(WORKSPACE_ROOT)
show_skill_contents(WORKSPACE_ROOT)


print("n" + "=" * 110)
print("FINAL SYSTEM PROMPT")
print("=" * 110)
print((WORKSPACE_ROOT / "prompts" / "system.md").read_text())


episodic_path = WORKSPACE_ROOT / "reminiscence" / "episodic.jsonl"
if episodic_path.exists():
   print("n" + "=" * 110)
   print("RECENT EPISODIC MEMORY")
   print("=" * 110)
   strains = episodic_path.read_text().strip().splitlines()
   for line in strains(-10:):
       print(line)


plt.determine(figsize=(8, 4))
plt.plot(vary(1, len(consequence.score_history) + 1), consequence.score_history, marker="o")
plt.xlabel("Evolution cycle")
plt.ylabel("Prepare rating")
plt.title("A-Evolve rating historical past")
plt.grid(True)
plt.present()


print("n" + "=" * 110)
print("COMPARISON")
print("=" * 110)
print(f"Prepare   : {baseline_train_score:.3f} -> {final_train_score:.3f}")
print(f"Holdout : {baseline_holdout_score:.3f} -> {final_holdout_score:.3f}")


improved_rules = ()
for earlier than, after in zip(sorted(baseline_train_rows, key=lambda x: x("task_id")), sorted(final_train_rows, key=lambda x: x("task_id"))):
   if (not earlier than("success")) and after("success"):
       improved_rules.append(after("rule"))


print(f"Improved prepare circumstances by rule: {dict(Counter(improved_rules))}")


print("nDone. This pocket book used the true A-Evolve framework and demonstrated:")
print("1) a sound agent workspace")
print("2) a BaseAgent subclass")
print("3) a BenchmarkAdapter subclass")
print("4) an EvolutionEngine subclass")
print("5) immediate / ability / reminiscence mutations throughout A-Evolve cycles")

Wir stellen alles zusammen und führen den gesamten A-Evolve-Kreislauf von der Basisbewertung bis zur Publish-Evolution-Analyse durch. Wir messen den Agenten vor dem Coaching, führen mehrere Entwicklungszyklen durch, laden den Arbeitsbereich neu und vergleichen dann die endgültige Trainings- und Holdout-Leistung, um zu sehen, was sich verbessert. Wir untersuchen auch die entwickelten Eingabeaufforderungen, Fähigkeiten, das Gedächtnis und den Bewertungsverlauf, wodurch wir klar beobachten können, wie das Framework den Agenten Schritt für Schritt transformiert.

Zusammenfassend lässt sich sagen, dass wir erfolgreich einen vollständigen A-Evolve-Workflow aufgebaut und ausgeführt haben, anstatt das Repository nur auf oberflächlicher Ebene zu inspizieren. Wir haben einen gültigen Arbeitsbereich erstellt, einen benutzerdefinierten Agenten angeschlossen, ihn anhand strukturierter Aufgaben verglichen und dann sein Verhalten weiterentwickelt, indem wir Eingabeaufforderungen geändert, Fähigkeiten hinzugefügt und Speicher über Zyklen hinweg gespeichert haben. Außerdem haben wir gesehen, wie das Design von A-Evolve es uns ermöglicht, die Verbesserung von Wirkstoffen als einen wiederholbaren technischen Prozess zu behandeln, bei dem wir die Basisleistung messen, kontrollierte Mutationen anwenden und beobachten können, wie das System mit der Zeit genauer wird.


Schauen Sie sich das an Das vollständige Coding-Notizbuch finden Sie hier. Sie können uns auch gerne weiter folgen Twitter und vergessen Sie nicht, bei uns mitzumachen 120.000+ ML SubReddit und Abonnieren Unser Publication. Warten! Bist du im Telegram? Jetzt können Sie uns auch per Telegram kontaktieren.


[ad_2]

]]>
http://chatgpz.de/artificial-intelligence/so-erstellen-und-entwickeln-sie-einen-benutzerdefinierten-openai-agenten-mit-a-evolve-unter-verwendung-von-benchmarks-faehigkeiten-speicher-und-arbeitsbereichsmutationen/feed/ 0 17498
Erstellen eines benutzerdefinierten Sprachassistenten mit Verwirrung http://chatgpz.de/artificial-intelligence/erstellen-eines-benutzerdefinierten-sprachassistenten-mit-verwirrung/ http://chatgpz.de/artificial-intelligence/erstellen-eines-benutzerdefinierten-sprachassistenten-mit-verwirrung/#respond Mon, 01 Sep 2025 20:12:42 +0000 https://chatgpz.de/artificial-intelligence/erstellen-eines-benutzerdefinierten-sprachassistenten-mit-verwirrung/ [ad_1]

Alexa und Siri sind die dominierenden Sprachassistenten für den täglichen Gebrauch. Diese Assistenten sind in quick jedem Haus allgegenwärtig geworden und haben Aufgaben von der Heimautomatisierung, zur Einnahme von Hinweisen, zur Rezeptanleitung und zur Beantwortung einfacher Fragen aus. Wenn es jedoch darum geht, Fragen zu beantworten, kann im Zeitalter von LLMs eine prägnante und kontextbasierte Antwort dieser Sprachassistenten schwierig, wenn nicht nicht existent sein. Wenn Sie beispielsweise Google Assistant fragen, wie der Markt reagiert Jerome Powells Rede In Jackson Gap am 22. August wird einfach antworten, dass die Antwort nicht kennt und ein paar Hyperlinks angibt, die Sie durchsehen können. Wenn Sie den Bildschirmbasierten Google Assistant haben.

Oft möchten Sie nur eine schnelle Antwort auf aktuelle Ereignisse oder Sie möchten wissen, ob ein Apfelbaum den Winter in Ohio überleben würde, und oft Sprachassistenten wie Google und Siri haben eine befriedigende Antwort. Dies hat mich dafür interessiert, meinen eigenen Sprachassistenten aufzubauen, der mir eine einfache, einzelne Satzantwort geben würde, basierend auf der Suche im Internet.

Foto von Aerps.com An Unplash

Von den verschiedenen verfügbaren LLM -Suchmaschinen bin ich seit mehr als einem Jahr ein begeisterter Benutzer von Verwirrung und verwende es ausschließlich für alle meine Suchanfragen, mit Ausnahme einfacher, bei denen ich noch zu Google oder Bing zurückkehre. Verwirrung ermöglicht es zusätzlich zu seinem Reside-Webindex, dass er aktuelle, genaue und bezogene Antworten bereitstellt, über eine leistungsstarke API den Zugriff auf ihre Funktionalität auf ihre Funktionalität. Mit dieser Funktionalität und der Integration in einen einfachen Himbeer -Pi wollte ich einen Sprachassistenten erstellen, der:

  • Antwort auf ein Wake -Wort und sei bereit, meine Frage zu beantworten
  • Beantworten Sie meine Frage in einem einfachen, prägnanten Satz
  • Gehen Sie zurück zum passiven Zuhören, ohne meine Daten zu verkaufen oder meine unnötigen Anzeigen zu geben

Die {Hardware} für den Assistenten

Foto von Axel Richter An Unplash

Um unseren Sprachassistenten aufzubauen, sind einige wichtige Hardwarekomponenten erforderlich. Der Kern des Projekts ist a Raspberry Pi 5der als zentraler Prozessor für unsere Bewerbung dient. Für die Audioeingabe des Assistenten habe ich einen einfachen gewählt USB -Schwanenhals -Mikrofon. Diese Artwork von Mikrofon ist omnidirektional, was es effektiv macht, das Wake-Wort aus verschiedenen Teilen eines Raums zu hören, und die Plug-and-Play-Natur vereinfacht das Setup. Für die Ausgabe des Assistenten einen Kompakt USB-betriebener Sprecher Bietet die Audioausgabe. Ein wesentlicher Vorteil dieses Lautsprechers besteht darin, dass er ein einzelnes USB -Kabel sowohl für sein Strom- als auch für das Audiosignal verwendet, das die Kabel -Unordnung minimiert.

Blockdiagramm zeigt die Funktionalität des benutzerdefinierten Sprachassistents (Bild vom Autor)

Dieser Ansatz, leicht verfügbare USB -Peripheriegeräte zu verwenden, macht die {Hardware} -Montage unkompliziert und ermöglicht es uns, unsere Bemühungen auf die Software program zu konzentrieren.

Die Umwelt vorbereiten

Um Verwirrung mit benutzerdefinierten Abfragen zu befragen, und um ein Wake -Wort für den Sprachassistenten zu haben, müssen wir einige API -Schlüssel generieren. Um einen Verwirrungs -API -Schlüssel zu generieren, kann man sich für ein Verwirrungskonto anmelden, zum Einstellungsmenü, wählen Sie die Registerkarte API und klicken Sie auf „API -Schlüssel generieren“, um ihren persönlichen Schlüssel für die Verwendung in Anwendungen zu erstellen und zu kopieren. Der Zugriff auf die Generierung von API -Schlüssel erfordert in der Regel eine bezahlte Plan- oder Zahlungsmethode. Stellen Sie daher sicher, dass das Konto vor dem Fortschritt in Frage kommt.

Zu den Plattformen, die Wake Phrase -Anpassung anbieten, gehören Picovoice Porcupine, Sensory RealhandSfree und Snowboy, wobei Picovoice Porcupine eine einfache On-line -Konsole zum Generieren, Testen und Bereitstellen von benutzerdefinierten Wake -Wörtern auf Desktop-, Mobil- und eingebetteten Geräten bietet. Ein neuer Benutzer kann ein benutzerdefiniertes Wort für generieren Picovoice Porcupine Indem Sie sich für ein kostenloses Picovoice Console-Konto anmelden, zur Porcupine-Seite navigieren, die gewünschte Sprache auswählen, im benutzerdefinierten Wake-Wort eingeben und auf „Zug“ klicken, um die plattformspezifische Modelldatei (.PPN) zur Verwendung zu produzieren und herunterzuladen. Stellen Sie sicher, dass Sie das Wake -Wort für die Leistung vor der Fertigstellung testen, da dies eine zuverlässige Erkennung und minimale falsch optimistic Ergebnisse gewährleistet. Das Wake -Wort, das ich trainiert habe und das ich verwenden werde, ist „Hey Krishna“.

Codieren des Assistenten

Das vollständige Python -Skript für dieses Projekt ist in meinem GitHub verfügbar Repository. Schauen wir uns in diesem Abschnitt die Schlüsselkomponenten des Code an, um zu verstehen, wie der Assistent funktioniert.
Das Skript ist in einige Kernfunktionen organisiert, die die Sinne und Intelligenz des Assistenten übernehmen, die alle von einer zentralen Schleife verwaltet werden.

Konfiguration und Initialisierung

Der erste Teil des Skripts ist dem Setup gewidmet. Das Laden der erforderlichen API -Schlüssel, Modelldateien und die Initialisierung der Purchasers für die Dienste, die wir verwenden.

# --- 1. Configuration ---
load_dotenv()
PICOVOICE_ACCESS_KEY = os.environ.get("PICOVOICE_ACCESS_KEY")
PERPLEXITY_API_KEY = os.environ.get("PERPLEXITY_API_KEY")
KEYWORD_PATHS = ("Krishna_raspberry-pi.ppn") # My wake phrase pat
MODEL_NAME = "sonar"

Dieser Abschnitt verwendet die dotenv Bibliothek, um Ihre geheimen API -Schlüssel sicher von a zu laden .env Datei, eine beste Praxis, die sie aus Ihrem Quellcode fernhält. Es definiert auch wichtige Variablen wie den Pfad zu Ihrer benutzerdefinierten Wake -Phrase -Datei und das spezifische Verwirrungsmodell, das wir abfragen möchten.

Wake Phrase -Erkennung

Damit der Assistent wirklich freihändig ist, muss er kontinuierlich für ein bestimmtes Wake-Wort zuhören, ohne signifikante Systemressourcen zu verwenden. Dies wird von der behandelt whereas True: Schleife in der fundamental Funktion, die den Picovoice Porcupine Motor verwendet.

# That is the principle loop that runs repeatedly
whereas True:
    # Learn a small chunk of uncooked audio information from the microphone
    pcm = audio_stream.learn(porcupine.frame_length)
    pcm = struct.unpack_from("h" * porcupine.frame_length, pcm)
    
    # Feed the audio chunk into the Porcupine engine for evaluation
    keyword_index = porcupine.course of(pcm)

    if keyword_index >= 0:
        # Wake phrase was detected, proceed to deal with the command...
        print("Wake phrase detected!")

Diese Schleife ist das Herzstück des „Passiv Hörstaates des Assistenten“. Es liest kontinuierlich kleine, rohe Audiorahmen aus dem Mikrofonstrom. Jeder Body wird dann an die übergeben porcupine.course of() Funktion. Dies ist sehr effizient, offline Prozess, der das Audio für das spezifische akustische Muster Ihres benutzerdefinierten Wake -Wortes („Krishna“) analysiert. Wenn das Muster erkannt wird, porcupine.course of() Gibt eine nicht damaging Nummer zurück, und das Skript verläuft in die aktive Part des Hörens für einen vollständigen Befehl.

Sprach-zu-Textual content-Konvertieren von Benutzerfragen in Textual content

Nachdem das Wake -Wort erkannt wurde, muss der Assistent die Frage des Benutzers zuhören und verstehen. Dies wird durch die SPEIC-to-Textual content-Komponente (STT) behandelt.

# --- This logic is inside the principle 'if keyword_index >= 0:' block ---

print("Listening for command...")
frames = ()
# Report audio from the stream for a hard and fast length (~10 seconds)
for _ in vary(0, int(porcupine.sample_rate / porcupine.frame_length * 10)):
    frames.append(audio_stream.learn(porcupine.frame_length))

# Convert the uncooked audio frames into an object the library can use
audio_data = sr.AudioData(b"".be part of(frames), porcupine.sample_rate, 2)

attempt:
    # Ship the audio information to Google's service for transcription
    command = recognizer.recognize_google(audio_data)
    print(f"You (command): {command}")
besides sr.UnknownValueError:
    speak_text("Sorry, I did not catch that.")

Sobald das Wake -Wort erkannt wurde, zeichnet der Code Audio für ungefähr 10 Sekunden lang aktiv aus dem Mikrofon auf und erfasst den gesprochenen Befehl des Benutzers. Anschließend werden diese RAW -Audiodaten verpackt und sie an den Google -Spracherkennungsdienst mit dem gesendet speech_recognition Bibliothek. Der Service verarbeitet den Audio und gibt den transkribierten Textual content zurück, der dann in der gespeichert wird command Variable.

Antworten aus Verwirrung erhalten

Sobald der Befehl des Benutzers in Textual content konvertiert wurde, wird er an die Verwirrungs-API gesendet, um eine intelligente, aktuelle Antwort zu erhalten.

# --- This logic runs if a command was efficiently transcribed ---

if command:
    # Outline the directions and context for the AI
    messages = ({"position": "system", "content material": "You might be an AI assistant. You might be situated in Twinsburg, Ohio. All solutions should be related to Cleveland, Ohio until requested for in a different way by the consumer.  You MUST reply all questions in a single and VERY concise sentence."})
    messages.append({"position": "consumer", "content material": command})
    
    # Ship the request to the Perplexity API
    response = perplexity_client.chat.completions.create(
        mannequin=MODEL_NAME, 
        messages=messages
    )
    assistant_response_text = response.decisions(0).message.content material.strip()
    speak_text(assistant_response_text)

Dieser Codeblock ist das „Gehirn“ der Operation. Es konstruiert zuerst a messages LISTE, die eine kritische enthält Systemaufforderung. Diese Eingabeaufforderung gibt der KI ihre Persönlichkeit und Regeln, z. B. die Beantwortung eines einzelnen Satzes und die Bekanntheit ihres Standorts in Ohio. Der Befehl des Benutzers wird dann dieser Liste hinzugefügt und das gesamte Paket wird an die Verwirrungs -API gesendet. Das Skript extrahiert dann den Textual content aus der Antwort der KI und übergibt ihn an die speak_text Funktionsfunktion vorgelesen werden.

Textual content-to-Speech-Verwirrungsreaktion in die Stimme umwandeln

Der speak_text Funktion gibt dem Assistenten seine Stimme.

def speak_text(text_to_speak, lang='en'):
    # Outline a operate that converts textual content to speech, default language is English
    
    print(f"Assistant (talking): {text_to_speak}")
    # Print the textual content for reference so the consumer can see what's being spoken
    
    attempt:
        pygame.mixer.init()
        # Initialize the Pygame mixer module for audio playback
        
        tts = gTTS(textual content=text_to_speak, lang=lang, sluggish=False)
        # Create a Google Textual content-to-Speech (gTTS) object with the supplied textual content and language
        # 'sluggish=False' makes the speech sound extra pure (not slow-paced)
        
        mp3_filename = "response_audio.mp3"
        # Set the filename the place the generated speech will likely be saved
        
        tts.save(mp3_filename)
        # Save the generated speech as an MP3 file
        
        pygame.mixer.music.load(mp3_filename)
        # Load the MP3 file into Pygame's music participant for playback
        
        pygame.mixer.music.play()
        # Begin taking part in the speech audio
        
        whereas pygame.mixer.music.get_busy():
            pygame.time.Clock().tick(10)
        # Maintain this system working (by checking if playback is ongoing)
        # This prevents the script from ending earlier than the speech finishes
        # The clock.tick(10) ensures it checks 10 occasions per second
        
        pygame.mixer.give up()
        # Give up the Pygame mixer as soon as playback is full to free sources
        
        os.take away(mp3_filename)
        # Delete the short-term MP3 file after playback to wash up
        
    besides Exception as e:
        print(f"Error in Textual content-to-Speech: {e}")
        # Catch and show any errors that happen throughout the speech era or playback

Diese Funktion nimmt eine Textzeichenfolge aus, druckt sie als Referenz aus und verwendet dann die GTTS-Bibliothek (Google Textual content-to-Speech), um eine temporäre MP3-Audio-Datei zu generieren. Es spielt die Datei über die Lautsprecher des Techniques mit der Pygame -Bibliothek ab, wartet, bis die Wiedergabe fertig ist, und löscht dann die Datei. Fehlerbehandlung ist enthalten, um Probleme während des Prozesses zu fangen.

Testen des Assistenten

Unten finden Sie eine Demonstration der Funktionsweise des benutzerdefinierten Sprachassistenten. Um seine Leistung mit Google Assistant zu vergleichen, habe ich sowohl bei Google als auch vom benutzerdefinierten Assistenten dieselbe Frage gestellt.

https://www.youtube.com/watch?v=wc6kqpp-zqi

Wie Sie sehen können, bietet Google Hyperlinks zur Antwort, anstatt eine kurze Zusammenfassung dessen zu geben, was der Benutzer will. Der benutzerdefinierte Assistent geht weiter und bietet eine Zusammenfassung und ist hilfreicher und informativ.

Abschluss

In diesem Artikel haben wir uns mit dem Prozess des Aufbaus eines voll funktionsfähigen, freiverwöhnten Sprachassistenten auf einem Himbeer-PI angesehen. Durch die Kombination der Kraft eines benutzerdefinierten Wake -Wortes und der Verwirrungs -API unter Verwendung von Python haben wir ein einfaches Voice -Assistant -Gerät erstellt, das dazu beiträgt, Informationen schnell zu erhalten.

Der Hauptvorteil dieses LLM-basierten Ansatzes ist die Fähigkeit, direkte, synthetisierte Antworten auf komplexe und aktuelle Fragen zu liefern-eine Aufgabe, bei der Assistenten wie Google Assistent häufig eine Liste von Suchlinks bereitstellen. Anstatt als bloße Sprachschnittstelle für eine Suchmaschine zu fungieren, fungiert unser Assistent als echte Antwortmotor und analysiert Echtzeit-Webergebnisse, um eine einzige, präzise Antwort zu erzielen. Die Zukunft der Sprachassistenten liegt in dieser tieferen, intelligenteren Integration, und der Aufbau Ihrer eigenen ist der beste Weg, um sie zu erkunden.

[ad_2]

]]>
http://chatgpz.de/artificial-intelligence/erstellen-eines-benutzerdefinierten-sprachassistenten-mit-verwirrung/feed/ 0 12057
So trainieren Sie einen Chatbot mit Lappen und benutzerdefinierten Daten http://chatgpz.de/machine-learning/so-trainieren-sie-einen-chatbot-mit-lappen-und-benutzerdefinierten-daten/ http://chatgpz.de/machine-learning/so-trainieren-sie-einen-chatbot-mit-lappen-und-benutzerdefinierten-daten/#respond Wed, 25 Jun 2025 20:50:39 +0000 https://chatgpz.de/machine-learning/so-trainieren-sie-einen-chatbot-mit-lappen-und-benutzerdefinierten-daten/ [ad_1]

?

Rag, der für die Technology von Abrufen von Abrufen steht, beschreibt einen Prozess, durch den ein LLM (großes Sprachmodell) optimiert werden kann, indem er aus einer spezifischeren, kleineren Wissensbasis statt seiner riesigen ursprünglichen Foundation trainiert wird. In der Regel werden LLMs wie ChatGPT im gesamten Web geschult (Milliarden von Datenpunkten). Dies bedeutet, dass sie anfällig für kleine Fehler und Halluzinationen sind.

Hier ist ein Beispiel für eine State of affairs, in der Lag verwendet werden kann und hilfreich sein kann:

Ich möchte einen US State Tour Information Chat Bot bauen, der allgemeine Informationen über US -Bundesstaaten wie ihre Hauptstädte, Populationen und Haupttouristenattraktionen enthält. Dazu kann ich Wikipedia -Seiten dieser US -Bundesstaaten herunterladen und meine LLM mit Textual content von diesen spezifischen Seiten trainieren.

Erstellen Sie Ihren Lappen LLM

Eines der beliebtesten Werkzeuge zum Aufbau von Lappensystemen ist Llamaindexwelche:

  • Vereinfacht die Integration zwischen LLMs und externen Datenquellen
  • Ermöglicht es Entwicklern, ihre Daten auf eine Weise zu strukturieren, zu indexieren und zu strukturieren, die für den LLM -Verbrauch optimiert ist
  • Funktioniert mit vielen Arten von Daten, wie z. B. PDFs und Textdateien
  • Hilft einer Lappenpipeline, die relevante Datenbrocken abruft und injiziert, bevor sie sie für die Technology an die LLM weitergeben

Laden Sie Ihre Daten herunter

Erhalten Sie zunächst die Daten, mit denen Sie Ihr Modell trainieren möchten. PDFs von Wikipedia herunterladen (CC um 4.0) Stellen Sie im richtigen Format sicher, dass Sie drucken und dann als PDF speichern.

Exportieren Sie die Wikipedia nicht nur als PDF – Lama wird das Format nicht mögen, in dem es sich befindet, und lehnt Ihre Dateien ab.

Für die Zwecke dieses Artikels und um die Dinge einfach zu halten, werde ich nur die Seiten der folgenden 5 beliebten Staaten herunterladen:

  • Florida
  • Kalifornien
  • Washington DC
  • New York
  • Texas

Stellen Sie sicher, dass Sie diese alle in einem Ordner speichern, in dem Ihr Projekt problemlos darauf zugreifen kann. Ich habe sie in einem namens „Daten“ gespeichert.

Holen Sie sich die notwendigen API -Schlüssel

Bevor Sie Ihre benutzerdefinierte Standing -Datenbank erstellen, müssen Sie 2 API -Schlüssel generieren.

  • Eine von OpenAI, um auf eine Foundation -LLM zuzugreifen
  • Eine von Lama zum Zugriff auf die Indexdatenbank, auf die Sie benutzerdefinierte Daten hochladen

Sobald Sie diese API -Schlüssel haben, speichern Sie sie in einer .env -Datei in Ihrem Projekt.

#.env file
LLAMA_API_KEY = "<Your-Api-Key>"
OPENAI_API_KEY = "<Your-Api-Key>"

Erstellen Sie einen Index und laden Sie Ihre Daten hoch

Erstellen a Llamacloud Konto. Sobald Sie in der Index sind, finden Sie den Indexabschnitt und klicken Sie auf „Erstellen“, um einen neuen Index zu erstellen.

Screenshot vom Autor

Ein Index speichert und verwaltet Dokumentindizes aus der Ferne, damit sie über eine API abfragt werden können, ohne sie neu aufzubauen oder zu speichern.

So funktioniert es:

  1. Wenn Sie Ihren Index erstellen, gibt es einen Ort, an dem Sie Dateien hochladen können, um die Datenbank des Modells zu füttern. Laden Sie Ihre PDFs hier hoch.
  2. Llamaindex Parsen und Stücke die Dokumente.
  3. Es schafft eine Index (zB, Vektorindex, Schlüsselwortindex).
  4. Dieser Index ist in llamacloud gelagert.
  5. Du kannst dann Fragen Sie es ab Verwenden eines LLM durch die API.

Das nächste, was Sie tun müssen, ist, eine zu konfigurieren Einbettungsmodell. Ein Einbettungsmodell ist das LLM, das Ihrem Projekt zugrunde liegt und für das Abrufen der relevanten Informationen und für den Ausgabe von Textual content verantwortlich ist.

Wenn Sie einen neuen Index erstellen, möchten Sie auswählen „Erstellen Sie eine neue Openai -Einbettung“:

Screenshot vom Autor

Wenn Sie Ihre neue Einbettung erstellen, müssen Sie Ihren OpenAI -API -Schlüssel bereitstellen und Ihr Modell benennen.

Screenshot vom Autor

Sobald Sie Ihr Modell erstellt haben, lassen Sie die anderen Indexeinstellungen als Standardeinstellungen und klicken Sie unten auf „Index erstellen“.

Es kann einige Minuten dauern, bis alle Dokumente analysiert und gespeichert werden. Stellen Sie daher sicher, dass alle Dokumente bearbeitet wurden, bevor Sie versuchen, eine Abfrage auszuführen. Der Standing sollte auf der rechten Seite des Bildschirms angezeigt werden, wenn Sie Ihren Index in einem Feld mit der Aufschrift „Indexdateien Zusammenfassung“ erstellen.

Zugriff auf Ihr Modell über Code

Sobald Sie Ihren Index erstellt haben, erhalten Sie auch eine Organisations -ID. Fügen Sie für Cleaner -Code Ihre Organisations -ID und den Indexnamen Ihrer .env -Datei hinzu. Rufen Sie dann alle erforderlichen Variablen ab, um Ihren Index in Ihrem Code zu initialisieren:

index = LlamaCloudIndex(
  identify=os.getenv("INDEX_NAME"), 
  project_name="Default",
  organization_id=os.getenv("ORG_ID"),
  api_key=os.getenv("LLAMA_API_KEY")
)

Fragen Sie Ihren Index ab und stellen Sie eine Frage

Dazu müssen Sie eine Abfrage (Eingabeaufforderung) definieren und dann eine Antwort erstellen, indem Sie den Index als solches aufrufen:

question = "What state has the very best inhabitants?"
response = index.as_query_engine().question(question)

# Print out simply the textual content a part of the response
print(response.response)

Ein längeres Gespräch mit Ihrem Bot führen

Wenn Sie eine Antwort von der LLM so abfragen, wie wir es oben oben getan haben, können Sie aus den von Ihnen geladenen Dokumenten problemlos auf Informationen zugreifen. Wenn Sie jedoch eine Observe -up -Frage stellen, wie „Welches hat am wenigsten?“ Ohne Kontext erinnert sich das Modell nicht, was Ihre ursprüngliche Frage struggle. Dies liegt daran, dass wir es nicht programmiert haben, um den Chat -Geschichte zu verfolgen.

Um dies zu tun, müssen Sie:

  • Erstellen Sie den Speicher mit ChatMemoryBuffer Speicher
  • Erstellen Sie eine Chat -Engine und fügen Sie den erstellten Speicher mit ContextChatengine hinzu

So erstellen Sie eine Chat -Engine:

from llama_index.core.chat_engine import ContextChatEngine
from llama_index.core.reminiscence import ChatMemoryBuffer

# Create a retriever from the index
retriever = index.as_retriever()

# Arrange reminiscence
reminiscence = ChatMemoryBuffer.from_defaults(token_limit=2000)

# Create chat engine with reminiscence
chat_engine = ContextChatEngine.from_defaults(
    retriever=retriever,
    reminiscence=reminiscence,
    llm=OpenAI(mannequin="gpt-4o"),
)

Füttern Sie Ihre Abfrage als nächstes in Ihre Chat -Engine:

# To question:
response = chat_engine.chat("What's the inhabitants of New York?")
print(response.response)

Dies gibt die Antwort: „Ab 2024 beträgt die geschätzte Bevölkerung von New York 19.867.248.“

Ich kann dann eine Observe -up -Frage stellen:

response = chat_engine.chat("What about California?")
print(response.response)

Dies gibt die folgende Antwort: „Ab 2024 beträgt die Bevölkerung Kaliforniens 39.431.263.“ Wie Sie sehen können, erinnerte sich das Modell daran, dass das, wonach wir zuvor gefragt hatten, die Bevölkerung struggle und entsprechend reagierte.

Streamlit UI Chatbot App für US State Rag. Screenshot vom Autor

Abschluss

Abrufener Augmented Technology ist eine effiziente Möglichkeit, einen LLM für bestimmte Daten zu schulen. Llamacloud bietet eine einfache und einfache Möglichkeit, Ihr eigenes Rag -Framework aufzubauen und das darunter liegende Modell abzufragen.

Der Code, den ich für dieses Tutorial verwendet habe, wurde in ein Notizbuch geschrieben, kann aber auch in eine Streamlit -App eingewickelt werden, um ein natürlicheres Hin- und Her -Gespräch mit einem Chatbot zu erstellen. Ich habe den Streamlit -Code aufgenommen Hier auf meinem Github.

Danke fürs Lesen

  • Verbinde mich mit mir LinkedIn
  • Kaufen Sie mir einen Kaffee um meine Arbeit zu unterstützen!
  • Ich biete 1: 1 Datenwissenschaftsunterricht, Karriere -Teaching/Mentoring, Schreiben von Ratschlägen, Lebenslaufbewertungen und mehr auf Topmate!

[ad_2]

]]>
http://chatgpz.de/machine-learning/so-trainieren-sie-einen-chatbot-mit-lappen-und-benutzerdefinierten-daten/feed/ 0 10268
Erstellen eines benutzerdefinierten PDF -Parsers mit PYPDF und Langchain http://chatgpz.de/data-science/erstellen-eines-benutzerdefinierten-pdf-parsers-mit-pypdf-und-langchain/ http://chatgpz.de/data-science/erstellen-eines-benutzerdefinierten-pdf-parsers-mit-pypdf-und-langchain/#respond Fri, 13 Jun 2025 07:43:23 +0000 http://chatgpz.de/data-science/erstellen-eines-benutzerdefinierten-pdf-parsers-mit-pypdf-und-langchain/ [ad_1]

Erstellen eines benutzerdefinierten PDF -Parsers mit PYPDF und Langchain
Bild von Autor | Leinwand

PDF -Dateien sind überall. Sie haben sie wahrscheinlich an verschiedenen Orten wie Faculty -Papieren, Stromrechnungen, Büroverträgen, Produkthandbüchern und vielem mehr gesehen. Sie sind sehr verbreitet, aber mit ihnen zu arbeiten ist nicht so einfach wie es aussieht. Nehmen wir an, Sie möchten nützliche Informationen von einem PDF extrahieren, z. B. das Lesen des Textes, das Aufteilen in Abschnitte oder eine kurze Zusammenfassung. Dies magazine einfach klingen, aber Sie werden sehen, dass es nicht so glatt ist, wenn Sie es versucht haben.

Im Gegensatz zu Phrase- oder HTML -Dateien speichern PDFs Inhalte nicht auf eine nette, lesbare Weise. Stattdessen sind sie so konzipiert, dass sie intestine aussehen und nicht von Programmen gelesen werden können. Der Textual content kann überall sein, in seltsame Blöcke aufgeteilt, über die Seite verstreut oder mit Tabellen und Bildern gemischt werden. Dies macht es schwierig, saubere, strukturierte Daten von ihnen zu erhalten.

In diesem Artikel werden wir etwas erstellen, das mit diesem Durcheinander umgehen kann. Wir erstellen einen benutzerdefinierten PDF -Parser, der kann:

  • Extrahieren und reinigen Textual content von PDFs auf Seitenebene mit optionaler Structure -Erhaltung für eine bessere Formatierung
  • Gehen Sie die Bildmetadatenextraktion um
  • Entfernen Sie unerwünschte Header und Fußzeilen, indem Sie wiederholte Leitungen über Seiten erkennen, um das Geräusch zu reduzieren
  • Detaillierte Dokument- und Seitenebene-Metadaten wie Autor, Titel, Erstellungsdatum, Rotation und Seitengröße abrufen
  • Teilen Sie den Inhalt in überschaubare Teile für die weitere NLP- oder LLM -Verarbeitung ein

Fangen wir an.

Ordnerstruktur

Vor Beginn ist es intestine, Ihre Projektdateien für Klarheit und Skalierbarkeit zu organisieren.

custom_pdf_parser/
│
├── parser.py           
├── langchain_loader.py  
├── pipeline.py          
├── instance.py     
├── necessities.txt     # Dependencies record
└── __init__.py         # (Non-compulsory) to mark listing as Python bundle

Sie können das verlassen __init.py__ Datei leer, da ihr Hauptzweck nur darin besteht, anzuzeigen, dass dieses Verzeichnis als Python -Paket behandelt werden sollte. Ich werde den Zweck jedes der verbleibenden Dateien Schritt für Schritt erklären.

Instruments erforderlich (Anforderungen.txt)

Die erforderlichen Bibliotheken sind:

  • PYPDF: Eine reine Python -Bibliothek zum Lesen und Schreiben von PDF -Dateien. Es wird verwendet, um den Textual content aus PDF -Dateien zu extrahieren
  • Langchain: Ein Framework zum Erstellen von kontextbezogenen Anwendungen mit Sprachmodellen (wir verwenden es, um Dokumentaufgaben zu verarbeiten und zu ketten). Es wird verwendet, um den Textual content ordnungsgemäß zu verarbeiten und zu organisieren.

Installieren Sie sie mit:

pip set up pypdf langchain

Wenn Sie Abhängigkeiten ordentlich verwalten möchten, erstellen Sie a Anforderungen.txt Datei mit:

Und rennen:

pip set up -r necessities.txt

Schritt 1: Richten Sie den PDF -Parser ein (Parser.py)

Die Kernklasse CustomPDFParser Verwendet PYPDF, um Textual content und Metadaten aus jeder PDF -Seite zu extrahieren. Es enthält auch Methoden zum Reinigen von Textual content, Bildinformationen (optionally available) und wiederholte Header oder Fußzeilen, die häufig auf jeder Seite erscheinen.

  • Es unterstützt die Erhaltung der Structure -Formatierung
  • Es extrahiert Metadaten wie Seitenzahl, Rotation und Medienboxabmessungen
  • Es kann Seiten mit zu wenig Inhalt herausfiltern
  • Die Textreinigung beseitigt übermäßige Weißespace, während die Absätze beibehalten werden

Die Logik, die all dies implementiert, lautet:

import os
import logging
from pathlib import Path
from typing import Listing, Dict, Any
import pypdf
from pypdf import PdfReader
# Configure logging to point out data and above messages
logging.basicConfig(stage=logging.INFO)
logger = logging.getLogger(__name__)
class CustomPDFParser:
  def __init__(
      self,extract_images: bool = False,preserve_layout: bool = True,remove_headers_footers: bool = True,min_text_length: int = 10
  ):
      """
      Initialize the parser with choices to extract photographs, protect structure, take away repeated headers/footers, and minimal textual content size for pages.
      Args:
          extract_images: Whether or not to extract picture data from pages
          preserve_layout: Whether or not to maintain structure spacing in textual content extraction
          remove_headers_footers: Whether or not to detect and take away headers/footers
          min_text_length: Minimal size of textual content for a web page to be thought of legitimate
      """
      self.extract_images = extract_images
      self.preserve_layout = preserve_layout
      self.remove_headers_footers = remove_headers_footers
      self.min_text_length = min_text_length
  def extract_text_from_page(self, web page: pypdf.PageObject, page_num: int) -> Dict(str, Any):
      """
      Extract textual content and metadata from a single PDF web page.
      Args:
          web page: PyPDF web page object
          page_num: zero-based web page quantity
      Returns:
          dict with keys:
              - 'textual content': extracted and cleaned textual content string,
              - 'metadata': web page metadata dict,
              - 'word_count': variety of phrases in extracted textual content
      """
      attempt:
 # Extract textual content, optionally preserving the structure for higher formatting
          if self.preserve_layout:
              textual content = web page.extract_text(extraction_mode="structure")
          else:
              textual content = web page.extract_text()
        # Clear textual content: take away additional whitespace and normalize paragraphs
          textual content = self._clean_text(textual content)
        # Collect web page metadata (web page quantity, rotation angle, mediabox)
          metadata = {
              "page_number": page_num + 1,  # 1-based numbering
              "rotation": getattr(web page, "rotation", 0),
              "mediabox": str(getattr(web page, "mediabox", None)),
          }
          # Optionally, extract picture data from web page if requested
          if self.extract_images:
              metadata("photographs") = self._extract_image_info(web page)
          # Return dictionary with textual content and metadata for this web page
          return {
              "textual content": textual content,
              "metadata": metadata,
              "word_count": len(textual content.break up()) if textual content else 0
          }
      besides Exception as e:
          # Log error and return empty information for problematic pages
          logger.error(f"Error extracting web page {page_num}: {e}")
          return {
              "textual content": "",
              "metadata": {"page_number": page_num + 1, "error": str(e)},
              "word_count": 0
          }
  def _clean_text(self, textual content: str) -> str:
      """
      Clear and normalize extracted textual content, preserving paragraph breaks.
      Args:
          textual content: uncooked textual content extracted from PDF web page
      Returns:
          cleaned textual content string
      """
      if not textual content:
          return ""
      traces = textual content.break up('n')
      cleaned_lines = ()
      for line in traces:
          line = line.strip()  # Take away main/trailing whitespace
          if line:
              # Non-empty line; hold it
              cleaned_lines.append(line)
          elif cleaned_lines and cleaned_lines(-1):
              # Protect paragraph break by preserving empty line provided that earlier line exists
              cleaned_lines.append("")
      cleaned_text="n".be a part of(cleaned_lines)
#Cut back any situations of greater than two consecutive clean traces to 2
      whereas 'nnn' in cleaned_text:
          cleaned_text = cleaned_text.exchange('nnn', 'nn')
      return cleaned_text.strip()
  def _extract_image_info(self, web page: pypdf.PageObject) -> Listing(Dict(str, Any)):
      """
      Extract fundamental picture metadata from web page, if obtainable.
      Args:
          web page: PyPDF web page object
      Returns:
          Listing of dictionaries with picture data (index, identify, width, top)
      """
      photographs = ()
      attempt:
          # PyPDF pages can have an 'photographs' attribute itemizing embedded photographs
          if hasattr(web page, 'photographs'):
              for i, picture in enumerate(web page.photographs):
                  photographs.append({
                      "image_index": i,
                      "identify": getattr(picture, 'identify', f"image_{i}"),
                      "width": getattr(picture, 'width', None),
                      "top": getattr(picture, 'top', None)
                  })
      besides Exception as e:
          logger.warning(f"Picture extraction failed: {e}")
      return photographs

  def _remove_headers_footers(self, pages_data: Listing(Dict(str, Any))) -> Listing(Dict(str, Any)):
      """
      Take away repeated headers and footers that seem on many pages.
      That is accomplished by figuring out traces showing on over 50% of pages
      in the beginning or finish of web page textual content, then eradicating these traces.
      Args:
          pages_data: Listing of dictionaries representing every web page's extracted information.
      Returns:
          Up to date record of pages with headers/footers eliminated
      """
      # Solely try elimination if sufficient pages and possibility enabled
      if len(pages_data) < 3 or not self.remove_headers_footers:
          return pages_data
      # Acquire first and final traces from every web page's textual content for evaluation
      first_lines = (web page("textual content").break up('n')(0) if web page("textual content") else "" for web page in pages_data)
      last_lines = (web page("textual content").break up('n')(-1) if web page("textual content") else "" for web page in pages_data)
      threshold = len(pages_data) * 0.5  # Greater than 50% pages
      # Establish candidate headers and footers showing continuously
      potential_headers = (line for line in set(first_lines)
                          if first_lines.rely(line) > threshold and line.strip())
      potential_footers = (line for line in set(last_lines)
                          if last_lines.rely(line) > threshold and line.strip())
      # Take away recognized headers and footers from every web page's textual content
      for page_data in pages_data:
          traces = page_data("textual content").break up('n')
          # Take away header if it matches a frequent header
          if traces and potential_headers:
              for header in potential_headers:
                  if traces(0).strip() == header.strip():
                      traces = traces(1:)
                      break
          # Take away footer if it matches a frequent footer
          if traces and potential_footers:
              for footer in potential_footers:
                  if traces(-1).strip() == footer.strip():
                      traces = traces(:-1)
                      break

          page_data("textual content") = 'n'.be a part of(traces).strip()
      return pages_data
  def _extract_document_metadata(self, pdf_reader: PdfReader, pdf_path: str) -> Dict(str, Any):
      """
      Extract metadata from the PDF doc itself.
      Args:
          pdf_reader: PyPDF PdfReader occasion
          pdf_path: path to PDF file
      Returns:
          Dictionary of metadata together with file data and PDF doc metadata
      """
      metadata = {
          "file_path": pdf_path,
          "file_name": Path(pdf_path).identify,
          "file_size": os.path.getsize(pdf_path) if os.path.exists(pdf_path) else None,
      }
      attempt:
          if pdf_reader.metadata:
              # Extract widespread PDF metadata keys if obtainable
              metadata.replace({
                  "title": pdf_reader.metadata.get('/Title', ''),
                  "writer": pdf_reader.metadata.get('/Writer', ''),
                  "topic": pdf_reader.metadata.get('/Topic', ''),
                  "creator": pdf_reader.metadata.get('/Creator', ''),
                  "producer": pdf_reader.metadata.get('/Producer', ''),
                  "creation_date": str(pdf_reader.metadata.get('/CreationDate', '')),
                  "modification_date": str(pdf_reader.metadata.get('/ModDate', '')),
              })
      besides Exception as e:
          logger.warning(f"Metadata extraction failed: {e}")
      return metadata
  def parse_pdf(self, pdf_path: str) -> Dict(str, Any):
      """
      Parse your entire PDF file. Opens the file, extracts textual content and metadata web page by web page, removes headers/footers if configured, and aggregates outcomes.
      Args:
          pdf_path: Path to the PDF file
      Returns:
          Dictionary with keys:
              - 'full_text': mixed textual content from all pages,
              - 'pages': record of page-wise dicts with textual content and metadata,
              - 'document_metadata': file and PDF metadata,
              - 'total_pages': complete pages in PDF,
              - 'processed_pages': variety of pages stored after filtering,
              - 'total_words': complete phrase rely of parsed textual content
      """
      attempt:
          with open(pdf_path, 'rb') as file:
              pdf_reader = PdfReader(file)
              doc_metadata = self._extract_document_metadata(pdf_reader, pdf_path)
              pages_data = ()
              # Iterate over all pages and extract information
              for i, web page in enumerate(pdf_reader.pages):
                  page_data = self.extract_text_from_page(web page, i)
                  # Solely hold pages with adequate textual content size
                  if len(page_data("textual content")) >= self.min_text_length:
                      pages_data.append(page_data)
              # Take away repeated headers and footers
              pages_data = self._remove_headers_footers(pages_data)
           # Mix all web page texts with a double newline as a separator
              full_text="nn".be a part of(web page("textual content") for web page in pages_data if web page("textual content"))
              # Return closing structured information
              return {
                  "full_text": full_text,
                  "pages": pages_data,
                  "document_metadata": doc_metadata,
                  "total_pages": len(pdf_reader.pages),
                  "processed_pages": len(pages_data),
                  "total_words": sum(web page("word_count") for web page in pages_data)
              }
      besides Exception as e:
          logger.error(f"Did not parse PDF {pdf_path}: {e}")
          increase

Schritt 2: Integrieren Sie sich in Langchain (Langchain_loader.py)

Der LangChainpdfloader Die Klasse wickelt den benutzerdefinierten Parser und konvertiert Parsen -Seiten in Langchain Dokumentieren Objekte, die die Bausteine ​​für Langchain -Pipelines sind.

  • Es ermöglicht das Knacken von Dokumenten in kleinere Stücke mit Langchains RecursivecharactertextSplitter
  • Sie können die Stückegrößen anpassen und überlappen, um den nachgeschalteten LLM -Eingang
  • Dieser Lader unterstützt eine saubere Integration zwischen RAW -PDF -Inhalten und Langchains Dokumentabstraktion

Die Logik dahinter ist:

from typing import Listing, Non-compulsory, Dict, Any
from langchain.schema import Doc
from langchain.document_loaders.base import BaseLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from parser import CustomPDFParser  # import the parser outlined above
class LangChainPDFLoader(BaseLoader):
   def __init__(
       self,file_path: str,parser_config: Non-compulsory(Dict(str, Any)) = None,chunk_size: int = 500, chunk_overlap: int = 50
   ):
       """
       Initialize the loader with the PDF file path, parser configuration, and chunking parameters.
       Args:
           file_path: path to PDF file
           parser_config: dictionary of parser choices
           chunk_size: chunk dimension for splitting lengthy texts
           chunk_overlap: chunk overlap for splitting
       """
       self.file_path = file_path
       self.parser_config = parser_config or {}
       self.chunk_size = chunk_size
       self.chunk_overlap = chunk_overlap
       self.parser = CustomPDFParser(**self.parser_config)
   def load(self) -> Listing(Doc):
       """
       Load PDF, parse pages, and convert every web page to a LangChain Doc.
       Returns:
           Listing of Doc objects with web page textual content and mixed metadata.
       """
       parsed_data = self.parser.parse_pdf(self.file_path)
       paperwork = ()
       # Convert every web page dict to a LangChain Doc
       for page_data in parsed_data("pages"):
           if page_data("textual content"):
               # Merge document-level and page-level metadata
               metadata = {**parsed_data("document_metadata"), **page_data("metadata")}
               doc = Doc(page_content=page_data("textual content"), metadata=metadata)
               paperwork.append(doc)
       return paperwork
   def load_and_split(self) -> Listing(Doc):
       """
       Load the PDF and break up massive paperwork into smaller chunks.
       Returns:
           Listing of Doc objects after splitting massive texts.
       """
       paperwork = self.load()
       # Initialize a textual content splitter with the specified chunk dimension and overlap
       text_splitter = RecursiveCharacterTextSplitter(
           chunk_size=self.chunk_size,
           chunk_overlap=self.chunk_overlap,
           separators=("nn", "n", " ", "")  # hierarchical splitting
       )
       # Cut up paperwork into smaller chunks
       split_docs = text_splitter.split_documents(paperwork)
       return split_docs

Schritt 3: Erstellen Sie eine Verarbeitungspipeline (Pipeline.py)

Der PdfprocessingPipeline Die Klasse bietet eine höhere Schnittstelle für:

  • Verarbeitung eines einzelnen PDF
  • Auswahl des Ausgabeformates (RAW DICT, Langchain -Dokumente oder einfacher Textual content)
  • Aktivieren oder Deaktivieren des Knackens mit konfigurierbaren Stückgrößen
  • Handhabungsfehler und Protokollierung

Diese Abstraktion ermöglicht eine einfache Integration in größere Anwendungen oder Workflows. Die Logik dahinter ist:

from typing import Listing, Non-compulsory, Dict, Any
from langchain.schema import Doc
from parser import CustomPDFParser
from langchain_loader import LangChainPDFLoader
import logging
logger = logging.getLogger(__name__)
class PDFProcessingPipeline:
   def __init__(self, parser_config: Non-compulsory(Dict(str, Any)) = None):
       """
       Args:
          parser_config: dictionary of choices handed to CustomPDFParser
       """
       self.parser_config = parser_config or {}
   def process_single_pdf(
       self,pdf_path: str,output_format: str = "langchain",chunk_documents: bool = True,chunk_size: int = 500,chunk_overlap: int = 50
   ) -> Any:
       """
       Args:
           pdf_path: path to PDF file
           output_format: "uncooked" (dict), "langchain" (Paperwork), or "textual content" (string)
           chunk_documents: whether or not to separate LangChain paperwork into chunks
           chunk_size: chunk dimension for splitting
           chunk_overlap: chunk overlap for splitting
       Returns:
           Parsed content material within the requested format
       """
       if output_format == "uncooked":
           # Use uncooked CustomPDFParser output
           parser = CustomPDFParser(**self.parser_config)
           return parser.parse_pdf(pdf_path)
       elif output_format == "langchain":
           # Use LangChain loader, optionally chunked
           loader = LangChainPDFLoader(pdf_path, self.parser_config, chunk_size, chunk_overlap)
           if chunk_documents:
               return loader.load_and_split()
           else:
               return loader.load()
       elif output_format == "textual content":
           # Return mixed plain textual content solely
           parser = CustomPDFParser(**self.parser_config)
           parsed_data = parser.parse_pdf(pdf_path)
           return parsed_data.get("full_text", "")
       else:
           increase ValueError(f"Unknown output_format: {output_format}")

Schritt 4: Testen Sie den Parser (Beispiel.Py)

Testen wir den Parser wie folgt:

import os
from pathlib import Path
def principal():
   print("👋 Welcome to the Customized PDF Parser!")
   print("What would you love to do?")
   print("1. View full parsed uncooked information")
   print("2. Extract full plain textual content")
   print("3. Get LangChain paperwork (no chunking)")
   print("4. Get LangChain paperwork (with chunking)")
   print("5. Present doc metadata")
   print("6. Present per-page metadata")
   print("7. Present cleaned web page textual content (header/footer eliminated)")
   print("8. Present extracted picture metadata")
   alternative = enter("Enter the variety of your alternative: ").strip()
   if alternative not in {'1', '2', '3', '4', '5', '6', '7', '8'}:
       print("❌ Invalid possibility.")
       return
   file_path = enter("Enter the trail to your PDF file: ").strip()
   if not Path(file_path).exists():
       print("❌ File not discovered.")
       return
   # Initialize pipeline
   pipeline = PDFProcessingPipeline({
       "preserve_layout": False,
       "remove_headers_footers": True,
       "extract_images": True,
       "min_text_length": 20
   })
   # Uncooked information is required for many choices
   parsed = pipeline.process_single_pdf(file_path, output_format="uncooked")
   if alternative == '1':
       print("nFull Uncooked Parsed Output:")
       for okay, v in parsed.objects():
           print(f"{okay}: {str(v)(:300)}...")
   elif alternative == '2':
       print("nFull Cleaned Textual content (truncated preview):")
       print("Previewing the primary 1000 characters:n"+parsed("full_text")(:1000), "...")
   elif alternative == '3':
       docs = pipeline.process_single_pdf(file_path, output_format="langchain", chunk_documents=False)
       print(f"nLangChain Paperwork: {len(docs)}")
       print("Previewing the primary 500 characters:n", docs(0).page_content(:500), "...")
   elif alternative == '4':
       docs = pipeline.process_single_pdf(file_path, output_format="langchain", chunk_documents=True)
       print(f"nLangChain Chunks: {len(docs)}")
       print("Pattern chunk content material (first 500 chars):")
       print(docs(0).page_content(:500), "...")
   elif alternative == '5':
       print("nDocument Metadata:")
       for key, worth in parsed("document_metadata").objects():
           print(f"{key}: {worth}")
   elif alternative == '6':
       print("nPer-page Metadata:")
       for i, web page in enumerate(parsed("pages")):
           print(f"Web page {i+1}: {web page('metadata')}")
   elif alternative == '7':
       print("nCleaned Textual content After Header/Footer Removing.")
       print("Exhibiting the primary 3 pages and first 500 characters of the textual content from every web page.")
       for i, web page in enumerate(parsed("pages")(:3)):  # First 3 pages
           print(f"n--- Web page {i+1} ---")
           print(web page("textual content")(:500), "...")
   elif alternative == '8':
       print("nExtracted Picture Metadata (if obtainable):")
       discovered = False
       for i, web page in enumerate(parsed("pages")):
           photographs = web page("metadata").get("photographs", ())
           if photographs:
               discovered = True
               print(f"n--- Web page {i+1} ---")
               for img in photographs:
                   print(img)
       if not discovered:
           print("No picture metadata discovered.")
if __name__ == "__main__":
   principal()

Führen Sie dies aus und Sie werden angewiesen, die Wahl NO und den Pfad zum PDF einzugeben. Geben Sie das ein. Die von mir verwendete PDF ist öffentlich zugänglich und Sie können es mit dem herunterladen Hyperlink.

👋 Welcome to the Customized PDF Parser!
What would you love to do?
1. View full parsed uncooked information
2. Extract full plain textual content
3. Get LangChain paperwork (no chunking)
4. Get LangChain paperwork (with chunking)
5. Present doc metadata
6. Present per-page metadata
7. Present cleaned web page textual content (header/footer eliminated)
8. Present extracted picture metadata.
Enter the variety of your alternative: 5
Enter the trail to your PDF file: /content material/articles.pdf

Output:
LangChain Chunks: 16
First chunk preview:
San José State College Writing Heart
www.sjsu.edu/writingcenter
Written by Ben Aldridge

Articles (a/an/the), Spring 2014.                                                                                   1 of 4
Articles (a/an/the)

There are three articles within the English language: a, an, and the. They're positioned earlier than nouns
and present whether or not a given noun is common or particular.

Examples of Articles

Abschluss

In diesem Leitfaden haben Sie gelernt, wie man eine versatile und leistungsstarke PDF-Verarbeitungspipeline mit nur Open-Supply-Instruments erstellt. Da es modular ist, können Sie es problemlos erweitern, möglicherweise eine Suchleiste mit Streamlit hinzufügen, Teile in einer Vektor -Datenbank wie FAISS für intelligentere Such -Lookups speichern oder sogar in einen Chatbot anschließen. Sie müssen nichts wieder aufbauen, Sie verbinden einfach das nächste Stück. PDFs müssen sich nicht mehr wie gesperrte Kisten fühlen. Mit diesem Ansatz können Sie jedes Dokument in etwas verwandeln, das Sie zu Ihren Bedingungen lesen, suchen und verstehen können.

Kanwal Mehreen Kanwal ist ein Ingenieur für maschinelles Lernen und technischer Schriftsteller mit einer tiefgreifenden Leidenschaft für die Datenwissenschaft und die Schnittstelle von KI mit Medizin. Sie hat das eBook „Produktivität mit Chatgpt maximieren“. Als Google -Era -Gelehrte 2022 für APAC setzt sie sich für Vielfalt und akademische Exzellenz ein. Sie wird auch als Teradata -Vielfalt in Tech Scholar, MITACS Globalink Analysis Scholar und Harvard Wecode Scholar anerkannt. Kanwal ist ein leidenschaftlicher Verfechter der Veränderung, nachdem er Femcodes gegründet hat, um Frauen in STEM -Bereichen zu stärken.

[ad_2]

]]>
http://chatgpz.de/data-science/erstellen-eines-benutzerdefinierten-pdf-parsers-mit-pypdf-und-langchain/feed/ 0 9915
Steigern Sie die Modellbewertung mit benutzerdefinierten Metriken in LLaMA-Manufacturing unit http://chatgpz.de/data-analytics/steigern-sie-die-modellbewertung-mit-benutzerdefinierten-metriken-in-llama-manufacturing-unit/ http://chatgpz.de/data-analytics/steigern-sie-die-modellbewertung-mit-benutzerdefinierten-metriken-in-llama-manufacturing-unit/#respond Tue, 05 Nov 2024 22:28:58 +0000 https://chatgpz.de/data-analytics/steigern-sie-die-modellbewertung-mit-benutzerdefinierten-metriken-in-llama-factory/ [ad_1]

In diesem Leitfaden werde ich Sie durch den Prozess des Hinzufügens einer benutzerdefinierten Bewertungsmetrik zu LLaMA-Manufacturing unit führen. LLaMA-Manufacturing unit ist ein vielseitiges Instrument, das Benutzern eine Feinabstimmung ermöglicht große Sprachmodelle (LLMs) dank der benutzerfreundlichen WebUI und des umfassenden Satzes an Skripten zum Trainieren, Bereitstellen und Bewerten von Modellen problemlos. Ein Hauptmerkmal von LLaMA-Manufacturing unit ist das LLaMA Board, ein integriertes Dashboard, das auch Bewertungsmetriken anzeigt und so wertvolle Einblicke in die Modellleistung bietet. Während Standardmetriken standardmäßig verfügbar sind, können wir durch die Möglichkeit, benutzerdefinierte Metriken hinzuzufügen, Modelle auf eine Weise bewerten, die für unsere spezifischen Anwendungsfälle direkt related ist.

Wir behandeln auch die Schritte zum Erstellen, Integrieren und Visualisieren einer benutzerdefinierten Metrik Lama Planke. Wenn Sie diesem Leitfaden folgen, können Sie zusätzliche, auf Ihre Bedürfnisse zugeschnittene Metriken überwachen, unabhängig davon, ob Sie an domänenspezifischer Genauigkeit, differenzierten Fehlertypen oder benutzerzentrierten Auswertungen interessiert sind. Durch diese Anpassung können Sie die Modellleistung effektiver bewerten und sicherstellen, dass sie mit den individuellen Zielen Ihrer Anwendung übereinstimmt. Lass uns eintauchen!

Lernergebnisse

  • Verstehen Sie, wie Sie eine benutzerdefinierte Bewertungsmetrik in LLaMA-Manufacturing unit definieren und integrieren.
  • Erwerben Sie praktische Fähigkeiten im Modifizieren metric.py um benutzerdefinierte Metriken einzubeziehen.
  • Erfahren Sie, wie Sie benutzerdefinierte Metriken auf dem LLaMA Board visualisieren, um bessere Einblicke in das Modell zu erhalten.
  • Erwerben Sie Kenntnisse über die Anpassung von Modellbewertungen an spezifische Projektanforderungen.
  • Entdecken Sie Möglichkeiten zur Überwachung der domänenspezifischen Modellleistung mithilfe personalisierter Metriken.

Dieser Artikel wurde im Rahmen der veröffentlicht Knowledge Science-Blogathon.

Was ist LLaMA-Manufacturing unit?

LLaMA-Manufacturing unit, entwickelt von hiyouga, ist ein Open-Supply-Projekt, das Benutzern dies ermöglicht Feinabstimmung Sprachmodelle über eine benutzerfreundliche WebUI-Schnittstelle. Es bietet eine vollständige Suite von Instruments und Skripten für die Feinabstimmung, den Aufbau von Chatbots, die Bereitstellung und das Benchmarking von LLMs.

LLaMA-Manufacturing unit wurde speziell für Anfänger und technisch nicht versierte Benutzer entwickelt und vereinfacht den Prozess der Feinabstimmung von Open-Supply-LLMs auf benutzerdefinierten Datensätzen, sodass keine komplexen KI-Konzepte verstanden werden müssen. Benutzer können einfach ein Modell auswählen, ihren Datensatz hochladen und einige Einstellungen anpassen, um mit dem Coaching zu beginnen.

Nach der Fertigstellung ermöglicht die Webanwendung auch das Testen des Modells und bietet so eine schnelle und effiziente Möglichkeit zur Feinabstimmung von LLMs auf einem lokalen Pc.

Während Standardmetriken wertvolle Einblicke in die allgemeine Leistung eines fein abgestimmten Modells liefern, bieten benutzerdefinierte Metriken eine Möglichkeit, die Wirksamkeit eines Modells in Ihrem spezifischen Anwendungsfall direkt zu bewerten. Durch die Anpassung von Metriken können Sie besser beurteilen, wie intestine das Modell individuelle Anforderungen erfüllt, die bei generischen Metriken möglicherweise übersehen werden. Benutzerdefinierte Metriken sind von unschätzbarem Wert, da sie die Flexibilität bieten, Maßnahmen zu erstellen und zu verfolgen, die speziell auf praktische Anforderungen abgestimmt sind, und so eine kontinuierliche Verbesserung auf der Grundlage relevanter, messbarer Kriterien ermöglichen. Dieser Ansatz ermöglicht einen gezielten Fokus auf domänenspezifische Genauigkeit, gewichtete Wichtigkeit und Ausrichtung auf die Benutzererfahrung.

Erste Schritte mit LLaMA-Manufacturing unit

Für dieses Beispiel verwenden wir eine Python-Umgebung. Stellen Sie sicher, dass Sie Python 3.8 oder höher und die erforderlichen Abhängigkeiten gemäß den Repository-Anforderungen installiert haben.

Set up

Wir werden zunächst alle Anforderungen installieren.

git clone --depth 1 https://github.com/hiyouga/LLaMA-Manufacturing unit.git
cd LLaMA-Manufacturing unit
pip set up -e ".(torch,metrics)"

Feinabstimmung mit der LLaMA Board GUI (unterstützt von Gradio)

llamafactory-cli webui

Hinweis: Die offizielle Einrichtungsanleitung mit ausführlicheren Informationen finden Sie hier Github.

Bewertungsmetriken in LLaMA-Manufacturing unit verstehen

Erfahren Sie mehr über die von LLaMA-Manufacturing unit bereitgestellten Standardbewertungsmetriken, wie BLEU- und ROUGE-Scores, und warum sie für die Bewertung der Modellleistung unerlässlich sind. In diesem Abschnitt wird auch der Wert der Anpassung von Metriken vorgestellt.

BLEU-Rating

Der BLEU-Rating (Bilingual Analysis Understudy) ist eine Metrik zur Bewertung der Qualität von Texten, die von maschinellen Übersetzungsmodellen generiert werden, indem er mit einem Referenztext (oder einem von Menschen übersetzten Textual content) verglichen wird. Der BLEU-Rating beurteilt in erster Linie, wie ähnlich die generierte Übersetzung einer oder mehreren Referenzübersetzungen ist.

ROUGE-Punktzahl

Der ROUGE-Rating (Recall-Oriented Understudy for Gisting Analysis) ist eine Reihe von Metriken, die zur Bewertung der Qualität von Textzusammenfassungen durch Vergleich mit Referenzzusammenfassungen verwendet werden. Es wird häufig für Zusammenfassungsaufgaben verwendet und misst die Überlappung von Wörtern und Phrasen zwischen dem generierten Textual content und dem Referenztext.

Diese Metriken sind standardmäßig verfügbar, Sie können jedoch auch benutzerdefinierte Metriken hinzufügen, die auf Ihren spezifischen Anwendungsfall zugeschnitten sind.

Voraussetzungen für das Hinzufügen einer benutzerdefinierten Metrik

In dieser Anleitung wird davon ausgegangen, dass LLaMA-Manufacturing unit bereits auf Ihrem Pc eingerichtet ist. Wenn nicht, lesen Sie bitte die LLaMA-Manufacturing unit-Dokumentation zur Set up und Einrichtung.

In diesem Beispiel gibt die Funktion einen Zufallswert zwischen 0 und 1 zurück, um eine Genauigkeitsbewertung zu simulieren. Sie können dies jedoch durch Ihre eigene Auswertungslogik ersetzen, um einen Genauigkeitswert (oder eine andere Metrik) basierend auf Ihren spezifischen Anforderungen zu berechnen und zurückzugeben. Diese Flexibilität ermöglicht es Ihnen, benutzerdefinierte Bewertungskriterien zu definieren, die Ihren Anwendungsfall besser widerspiegeln.

Definieren Sie Ihre benutzerdefinierte Metrik

Erstellen wir zunächst eine Python-Datei mit dem Namen custom_metric.py und definieren Sie darin unsere benutzerdefinierte Metrikfunktion.

In diesem Beispiel heißt unsere benutzerdefinierte Metrik X_Punktzahl. Diese Metrik wird dauern preds (vorhergesagte Werte) und Etiketten (Grundwahrheitswerte) als Eingaben und geben eine Bewertung basierend auf Ihrer benutzerdefinierten Logik zurück.

import random

def cal_x_score(preds, labels):
    """
    Calculate a customized metric rating.

    Parameters:
    preds -- checklist of predicted values
    labels -- checklist of floor fact values

    Returns:
    rating -- a random worth or a customized calculation as per your requirement
    """
    # Customized metric calculation logic goes right here
    
    # Instance: return a random rating between 0 and 1
    return random.uniform(0, 1)

Sie können die Zufallsbewertung durch Ihre spezifische Berechnungslogik ersetzen.

Ändern von sft/metric.py zur Integration der benutzerdefinierten Metrik

Um sicherzustellen, dass das LLaMA-Board unsere neue Metrik erkennt, müssen wir sie in die Metrikberechnungspipeline integrieren src/llamafactory/prepare/sft/metric.py

Fügen Sie Ihre Metrik zum Rating-Wörterbuch hinzu:

  • Suchen Sie die ComputeSimilarity-Funktion darin sft/metric.py
  • Aktualisieren self.score_dict um Ihre neue Metrik wie folgt einzubinden:
self.score_dict = {
    "rouge-1": (),
    "rouge-2": (),
    "bleu-4": (),
    "x_score": ()  # Add your customized metric right here
}
Ändern von sft/metric.py zur Integration der benutzerdefinierten Metrik

Berechnen Sie die benutzerdefinierte Metrik und hängen Sie sie in der __call__-Methode an:

  • Innerhalb der __Anruf__ Berechnen Sie Ihre benutzerdefinierte Metrik und fügen Sie sie der Methode hinzu score_dict. Hier ist ein Beispiel dafür:
from .custom_metric import cal_x_score
def __call__(self, preds, labels):
    # Calculate the customized metric rating
    custom_score = cal_x_score(preds, labels)
    # Append the rating to 'extra_metric' within the rating dictionary
    self.score_dict("x_score").append(custom_score * 100)

Dieser Integrationsschritt ist wichtig, damit die benutzerdefinierte Metrik im LLaMA-Board angezeigt wird.

Lama-Brett Tab „Bewerten“.
Endergebnis

Der predict_x_score Die Metrik wird nun erfolgreich angezeigt und zeigt eine Genauigkeit von 93,75 % für dieses Modell und diesen Validierungsdatensatz. Diese Integration bietet Ihnen eine einfache Möglichkeit, jedes fein abgestimmte Modell direkt in der Evaluierungspipeline zu bewerten.

Abschluss

Nachdem Sie Ihre benutzerdefinierte Metrik eingerichtet haben, sollten Sie sie nach dem Ausführen der Evaluierungspipeline im LLaMA Board sehen. Die zusätzlichen Metrikwerte werden für jede Bewertung aktualisiert.

Mit diesen Schritten haben Sie erfolgreich eine benutzerdefinierte Bewertungsmetrik in LLaMA-Manufacturing unit integriert! Dieser Prozess gibt Ihnen die Flexibilität, über Standardmetriken hinauszugehen und Modellbewertungen an die individuellen Anforderungen Ihres Projekts anzupassen. Durch die Definition und Implementierung spezifischer Metriken für Ihren Anwendungsfall erhalten Sie aussagekräftigere Einblicke in die Modellleistung und heben Stärken und Verbesserungsbereiche auf die Weise hervor, die für Ihre Ziele am wichtigsten ist.

Das Hinzufügen benutzerdefinierter Metriken ermöglicht außerdem eine kontinuierliche Verbesserungsschleife. Wenn Sie Modelle anhand neuer Daten verfeinern und trainieren oder Parameter ändern, bieten diese personalisierten Metriken eine konsistente Möglichkeit, den Fortschritt zu bewerten. Unabhängig davon, ob Ihr Fokus auf domänenspezifischer Genauigkeit, Ausrichtung auf die Benutzererfahrung oder differenzierten Bewertungsmethoden liegt, bietet LLaMA Board eine visuelle und quantitative Möglichkeit, diese Ergebnisse im Zeitverlauf zu vergleichen und zu verfolgen.

Durch die Verbesserung der Modellbewertung mit benutzerdefinierten Metriken ermöglicht Ihnen LLaMA-Manufacturing unit, datengesteuerte Entscheidungen zu treffen, Modelle präzise zu verfeinern und die Ergebnisse besser an reale Anwendungen anzupassen. Mit dieser Anpassungsfunktion können Sie Modelle erstellen, die eine effektive Leistung erbringen, im Hinblick auf relevante Ziele optimiert werden und bei praktischen Einsätzen einen Mehrwert bieten.

Wichtige Erkenntnisse

  • Benutzerdefinierte Metriken in LLaMA-Manufacturing unit verbessern Modellbewertungen, indem sie sie an den individuellen Projektanforderungen ausrichten.
  • LLaMA Board ermöglicht die einfache Visualisierung benutzerdefinierter Metriken und bietet tiefere Einblicke in die Modellleistung.
  • Ändern metric.py ermöglicht die nahtlose Integration individueller Bewertungskriterien.
  • Personalisierte Metriken unterstützen die kontinuierliche Verbesserung und passen Bewertungen an sich entwickelnde Modellziele an.
  • Maßgeschneiderte Metriken ermöglichen datengesteuerte Entscheidungen und optimieren Modelle für reale Anwendungen.

Häufig gestellte Fragen

Q1. Was ist LLaMA-Manufacturing unit?

A. LLaMA-Manufacturing unit ist ein Open-Supply-Instrument zur Feinabstimmung großer Sprachmodelle über eine benutzerfreundliche WebUI mit Funktionen zum Trainieren, Bereitstellen und Bewerten von Modellen.

Q2. Warum eine benutzerdefinierte Bewertungsmetrik hinzufügen?

A. Mit benutzerdefinierten Metriken können Sie die Modellleistung anhand spezifischer Kriterien für Ihren Anwendungsfall bewerten und Erkenntnisse gewinnen, die mit Standardmetriken möglicherweise nicht erfasst werden.

Q3. Wie erstelle ich eine benutzerdefinierte Metrik?

A. Definieren Sie Ihre Metrik in einer Python-Datei und geben Sie die Logik an, wie die Leistung basierend auf Ihren Daten berechnet werden soll.

This fall. Wo integriere ich die benutzerdefinierte Metrik in LLaMA-Manufacturing unit?

A. Fügen Sie Ihre Metrik hinzu sft/metric.py Datei und aktualisieren Sie das Rating-Wörterbuch und die Berechnungspipeline, um sie einzuschließen.

F5. Wird meine benutzerdefinierte Metrik im LLaMA-Board angezeigt?

A. Ja, sobald Sie Ihre benutzerdefinierte Metrik integriert haben, zeigt LLaMA Board sie an, sodass Sie die Ergebnisse zusammen mit anderen Metriken visualisieren können.

Die in diesem Artikel gezeigten Medien sind nicht Eigentum von Analytics Vidhya und werden nach Ermessen des Autors verwendet.

[ad_2]

]]>
http://chatgpz.de/data-analytics/steigern-sie-die-modellbewertung-mit-benutzerdefinierten-metriken-in-llama-manufacturing-unit/feed/ 0 4985
Abstürze der NVIDIA-Systemsteuerung: Behebung von Fehlern bei der benutzerdefinierten Auflösung http://chatgpz.de/data-science/abstuerze-der-nvidia-systemsteuerung-behebung-von-fehlern-bei-der-benutzerdefinierten-aufloesung/ http://chatgpz.de/data-science/abstuerze-der-nvidia-systemsteuerung-behebung-von-fehlern-bei-der-benutzerdefinierten-aufloesung/#respond Mon, 21 Oct 2024 23:35:58 +0000 https://chatgpz.de/data-science/abstuerze-der-nvidia-systemsteuerung-behebung-von-fehlern-bei-der-benutzerdefinierten-aufloesung/ [ad_1]

Bei der Verwaltung benutzerdefinierter Monitorauflösungen über die NVIDIA-Systemsteuerung stoßen Benutzer manchmal auf frustrierende technische Probleme.

Eins Redditor namens TheLazyDucky berichteten kürzlich von ihrem Kampf mit einem bestimmten Drawback: Nach dem Einrichten einer benutzerdefinierten Auflösung für einen Hochformatmonitor erscheint die Auflösung gestreckt. Wenn sie versuchen, diese erweiterte Einstellung über die NVIDIA-Systemsteuerung zu deaktivieren, stürzt die Anwendung ab und verhindert, dass Änderungen gespeichert werden. Erschwerend kommt hinzu, dass das System einen Fehler protokolliert, der wenig Klarheit darüber bietet, wie das Drawback behoben werden kann.

Der Beitrag von :

„Ich habe für meinen Porträtmonitor eine benutzerdefinierte Auflösung hinzugefügt, die sich ausdehnt, und habe versucht, sie auszuschalten. Allerdings stürzt das Programm jedes Mal ab, wenn ich in der NVIDIA-Systemsteuerung die gestreckte Auflösung deaktiviere, wenn ich auf „Übernehmen“ klicke. Meine Änderungen werden nicht gespeichert und es wird ein Fehler in der Ereignisanzeige in der Kategorie „Anwendung“ ausgegeben.

Hier ist der Fehler, den ich erhalte:

Identify der fehlerhaften Anwendung: nvcplui.exe, Model: 8.1.940.0, Zeitstempel: 0x660c5657
Identify des fehlerhaften Moduls: nvcplui.exe, Model: 8.1.940.0, Zeitstempel: 0x660c5657
Ausnahmecode: 0xc0000409
Fehler-Offset: 0x0000000000295155
Fehlerhafte Prozess-ID: 0x441c
Startzeit der fehlerhaften Anwendung: 0x01db23afd187086f
Pfad der fehlerhaften Anwendung: C:ProgrammeWindowsAppsNVIDIACorp.NVIDIAControlPanel_8.1.966.0_x64__56jybvy8sckqjnvcplui.exe
Pfad des fehlerhaften Moduls: C:ProgrammeWindowsAppsNVIDIACorp.NVIDIAControlPanel_8.1.966.0_x64__56jybvy8sckqjnvcplui.exe
Berichts-ID: cded37f7-eecc-4808-97ef-6caa12186bca
Vollständiger Identify des fehlerhaften Pakets: NVIDIACorp.NVIDIAControlPanel_8.1.966.0_x64__56jybvy8sckqj
Fehlerhafte paketbezogene Anwendungs-ID: NVIDIACorp.NVIDIAControlPanel

Kennt jemand eine Lösung für dieses Drawback?“

Schnelle Lösungen für Probleme mit benutzerdefinierten Auflösungen in der NVIDIA-Systemsteuerung

Hier ist ein genauerer Blick auf einige mögliche Lösungen, die helfen könnten.

Installieren oder reparieren Sie die NVIDIA-Systemsteuerung neu

Manchmal kann eine Beschädigung der Systemsteuerungsanwendung solche Probleme verursachen. Versuchen Sie, die NVIDIA-Systemsteuerung aus dem Microsoft Retailer oder direkt von der NVIDIA-Web site neu zu installieren, um sicherzustellen, dass Sie über die neueste und unbeschädigte Model verfügen. Sie können auch versuchen, die App über die Apps & Funktionen-Einstellungen in Home windows zu reparieren.

Erstellen Sie die benutzerdefinierte Auflösung mithilfe der NVIDIA-Systemsteuerung neu

Das Drawback könnte darauf zurückzuführen sein, wie die benutzerdefinierte Auflösung erstellt wurde. Versuchen Sie, die aktuelle benutzerdefinierte Auflösung zu löschen und sie in der NVIDIA-Systemsteuerung von Grund auf neu zu erstellen. Testen Sie unbedingt mit unterschiedlichen Skalierungseinstellungen (z. B. keine Skalierung oder Beibehaltung des Seitenverhältnisses) und Aktualisierungsraten, um zu sehen, ob das Dehnungsproblem dadurch behoben wird.

Fehler bei der benutzerdefinierten Auflösung des NVIDIA-Bedienfelds
Fehler bei der benutzerdefinierten Auflösung des NVIDIA-Bedienfelds (Bildnachweis)

Suchen Sie nach GPU-Treiberaktualisierungen

Stellen Sie sicher, dass Ihre GPU-Treiber auf dem neuesten Stand sind, indem Sie die herunterladen Die neuesten Treiber finden Sie auf der NVIDIA-Web site. Häufig können Treiberprobleme die Ursache für solche Abstürze sein, insbesondere wenn benutzerdefinierte Auflösungen verwendet werden. Durch die Aktualisierung wird möglicherweise das zugrunde liegende Drawback behoben, das den Absturz verursacht hat.

Deaktivieren Sie NVIDIA-Overlay- oder Hintergrunddienste

NVIDIA GeForce Expertise und andere Hintergrunddienste könnten die Systemsteuerung beeinträchtigen. Deaktivieren Sie die Overlay-Funktion im Spiel in GeForce Expertise oder stoppen Sie andere NVIDIA-Hintergrundprozesse über den Process-Supervisor, um zu sehen, ob das Drawback dadurch behoben wird.

Rollback auf eine frühere Model

Wenn das Drawback nach einem kürzlich durchgeführten Replace aufgetreten ist, versuchen Sie, auf eine frühere Model des NVIDIA-Treibers oder der Systemsteuerungs-App zurückzusetzen. Manchmal führen neuere Versionen zu Fehlern, die möglicherweise noch nicht behoben wurden.


Hervorgehobener Bildnachweis: Kerem Gülen/Ideogramm

[ad_2]

]]>
http://chatgpz.de/data-science/abstuerze-der-nvidia-systemsteuerung-behebung-von-fehlern-bei-der-benutzerdefinierten-aufloesung/feed/ 0 4688