Das Paradigma „Textual content in, Textual content out“ führt Sie nur so weit.

Reale Anwendungen, die den tatsächlichen Wert liefern, sollten in der Lage sein, Visuals, Vernunft durch komplexe Probleme zu untersuchen und Ergebnisse zu erzielen, die Systeme tatsächlich verwenden können.

In diesem Beitrag werden wir diesen Stapel entwerfen, indem wir drei leistungsstarke Funktionen zusammenbringen: multimodale Eingabe, Argumentation, Und strukturierter Ausgang.

Um dies zu veranschaulichen, gehen wir durch ein praktisches Beispiel: Bauen a zeitreiche Anomalie-Erkennungssystem Für E-Commerce-Auftragsdaten verwenden Openais O3 -Modell. Insbesondere zeigen wir, wie die Argumentationsfunktion von O3 mit Bildeingabe und validiertes JSON abgibt, damit das nachgelagerte System es leicht konsumieren kann.

Am Ende wird unsere App:

  • Sehen: Analysieren Sie Diagramme der E-Commerce-Bestellvolumenzeitreihe
  • Denken: Identifizieren Sie ungewöhnliche Muster
  • Integrieren: Ausgabe eines strukturierten Anomalieberichts

Sie gehen mit Funktionscode ab, die Sie für verschiedene Anwendungsfälle wiederverwenden können, die über die Erkennung von nur Anomalie hinausgehen.

Lassen Sie uns eintauchen.

Möchten Sie die breitere Landschaft darüber lernen, wie LLMs zur Erkennung von Anomalie angewendet werden? Schauen Sie sich meinen vorherigen Beitrag an: Steigern Sie Ihre Anomalie -Erkennung mit LLMsAnwesend wo ich 7 aufkommende Anwendungsmuster zusammengefasst habe Das sollten Sie nicht verpassen.


1. Fallstudie

In diesem Beitrag wollen wir eine Anomalie-Erkennungslösung zur Identifizierung abnormaler Muster in E-Commerce-Auftragszeitreihendaten erstellen.

Für diese Fallstudie haben wir drei Sätze von generiert Synthetik Tägliche Auftragsdaten. Die Datensätze stellen drei verschiedene Profile der täglichen Bestellung über ungefähr einen Monat dar. Um die Saisonalität offensichtlich zu machen, haben wir die Wochenenden beschattet. Die X-Achse zeigt den Wochentag.

Abbildung 1. Datensatz 1, wobei die schattierten Regionen die Wochenenden sind. (Bild des Autors)
Abbildung 2. Datensatz 2, wobei die schattierten Regionen die Wochenenden sind. (Bild des Autors)
Abbildung 3. Dataset 3, wobei die schattierten Regionen die Wochenenden sind. (Bild des Autors)

Jede Abbildung enthält eine bestimmte Artwork von Anomalie (Kannst du sie finden?). Wir werden später diese Zahlen verwenden, um unsere Anomalie -Erkennungslösung zu testen und zu prüfen, ob diese Anomalien genau wiederhergestellt werden kann.

2. Unsere Lösung

2.1 Übersicht

Im Gegensatz zu den traditionellen Ansätzen für maschinelles Lernen, die mühsames Characteristic -Engineering und Modelltraining erfordern, ist unser aktueller Ansatz viel einfacher. Es funktioniert mit den folgenden Schritten:

  1. Wir bereiten die Abbildung zur Visualisierung der E-Commerce-Auftragszeitreihendaten vor.
  2. Wir fordern das Argumentationsmodell O3 auf, bitten ihn, das Zeitreihenbild genauer zu betrachten, das wir ihm gefüttert haben, und feststellen, ob ein ungewöhnliches Muster existiert.
  3. Das O3-Modell gibt dann seine Ergebnisse in einem vordefinierten JSON-Format aus.

Und das battle’s. Einfach.

Um diese Lösung zu liefern, müssen wir das O3 -Modell natürlich ermöglichen, Bildeingabe zu nehmen und die strukturierte Ausgabe zu emittieren. Wir werden sehen, wie man das in Kürze macht.

2.2 Einrichten des Argumentationsmodells

Wie bereits erwähnt, werden wir das O3-Modell verwenden, das das Flaggschiff-Argumentationsmodell von OpenAI ist, das komplexe mehrstufige Probleme mit der Leistung auf der neuesten Nutzung angehen kann. Insbesondere verwenden wir den Azure OpenAI -Endpunkt, um das Modell aufzurufen.

Stellen Sie sicher .env Datei können wir dann mit dem Einrichten des LLM -Purchasers fortfahren:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

from openai import AzureOpenAI
from dotenv import load_dotenv
import os

load_dotenv()

# Setup LLM consumer
endpoint = os.getenv("api_base")
api_key = os.getenv("o3_API_KEY")
api_version = "2025-04-01-preview"
model_name = "o3"
deployment = os.getenv("deployment_name")

LLM_client = AzureOpenAI(
    api_key=api_key,  
    api_version=api_version,
    azure_endpoint=endpoint
)

Wir verwenden die folgende Anweisung als Systemnachricht für das O3-Modell (abgestimmt von GPT-5):

instruction = f"""

(Function)
You're a meticulous information analyst.

(Process)
You'll be given a line chart picture associated to day by day e-commerce orders. 
Your process is to determine outstanding anomalies within the information.

(Guidelines)
The anomaly varieties will be spike, drop, level_shift, or seasonal_outlier.
A level_shift is a sustained baseline change (≥ 5 consecutive days), not a single level.
A seasonal_outlier occurs if a weekend/weekday behaves not like friends in its class. 
For instance, weekend orders are normally decrease than the weekdays'.
Learn dates/values from axes; if you happen to can’t learn precisely, snap to the closest tick and word uncertainty in clarification.
The weekends are shaded within the determine.
"""

In der obigen Anweisung haben wir die Rolle der LLM, die Aufgabe, die die LLM ausführen sollte, und die Regeln, die die LLM befolgen sollte, klar definiert.

Um die Komplexität unserer Fallstudie zu begrenzen, haben wir absichtlich nur vier Anomalie -Typen festgelegt, die LLM identifizieren muss. Wir haben auch klare Definitionen dieser Anomalie -Typen zur Verfügung gestellt, um Unklarheiten zu beseitigen.

Schließlich haben wir ein bisschen Domänenwissen über E-Commerce-Muster injiziert, dh niedrigere Wochenendbestellungen werden im Vergleich zu Wochentagen erwartet. Das Einbeziehen von Area-Know-how wird im Allgemeinen als eine gute Praxis für die Führung des analytischen Prozesss des Modells angesehen.

Nachdem wir unser Modell eingerichtet haben, diskutieren wir, wie das Bild für das O3 -Modell vorbereitet werden soll.

2.3 Bildvorbereitung

Um die multimodalen Funktionen von O3 zu ermöglichen, müssen wir Zahlen in einem bestimmten Format bereitstellen, dh entweder öffentlich zugängliche Net-URLs oder als Basis64-kodierte Daten-URLs. Da unsere Zahlen lokal erzeugt werden, werden wir den zweiten Ansatz verwenden.

Was ist Base64 -Codierung überhaupt? Base64 ist eine Möglichkeit, binäre Daten (wie unsere Bilddateien) nur mit Textzeichen darzustellen, die sicher über das Web übertragen werden. Es wandelt Binärbilddaten in eine Zeichenfolge, Zahlen und einige Symbole um.

Und was ist mit Daten -URL? Eine Daten -URL ist eine Artwork von URL, die den Dateiinhalt direkt in die URL -Zeichenfolge einbettet, anstatt auf einen Dateispeicherort zu zeigen.

Wir können die folgende Funktion verwenden, um diese Konvertierung automatisch zu behandeln:

import io
import base64

def fig_to_data_url(fig, fmt="png"):
    """
    Converts a Matplotlib determine to a base64 information URL with out saving to disk.

    Args:
    -----
    fig (matplotlib.determine.Determine): The determine to transform.
    fmt (str): The format of the picture ("png", "jpeg", and so forth.)

    Returns:
    --------
    str: The information URL representing the determine.
    """

    buf = io.BytesIO()
    fig.savefig(buf, format=fmt, bbox_inches="tight")
    buf.search(0)
    
    base64_encoded_data = base64.b64encode(buf.learn()).decode("utf-8")
    mime_type = f"picture/{fmt.decrease()}"
    
    return f"information:{mime_type};base64,{base64_encoded_data}"

Im Wesentlichen speichert unsere Funktion zuerst die Matplotlib -Figur in einem Speicherpuffer. Anschließend codiert es die binären PNG -Daten als Base64 -Textual content und wickelt sie in das gewünschte Daten -URL -Format ein.

Angenommen, wir haben Zugriff auf die Daten der synthetischen täglichen Ordnung, können die folgende Funktion verwenden, um das Diagramm zu generieren und in einem GO in ein ordnungsgemäßes Daten -URL -Format umzuwandeln:

def create_fig(df):
    """
    Create a Matplotlib determine and convert it to a base64 information URL.
    Weekends (Sat–Solar) are shaded.

    Args:
    -----
    df: dataframe incorporates one profile of day by day order time sequence. 
        dataframe has "date" and "orders" columns.

    Returns:
    --------
    image_url: The information URL representing the determine.
    """

    df = df.copy()
    df('date') = pd.to_datetime(df('date'))

    fig, ax = plt.subplots(figsize=(8, 4.5))
    ax.plot(df("date"), df("orders"), linewidth=2)
    ax.set_xlabel('Date', fontsize=14)
    ax.set_ylabel('Every day Orders', fontsize=14)

    # Weekend shading
    begin = df("date").min().normalize()
    finish   = df("date").max().normalize()
    cur = begin
    whereas cur <= finish:
        if cur.weekday() == 5:  # Saturday 00:00
            span_start = cur                                      # Sat 00:00
            span_end   = cur + pd.Timedelta(days=1)               # Mon 00:00
            ax.axvspan(span_start, span_end, alpha=0.12, zorder=0)
            cur += pd.Timedelta(days=2)                           # skip Sunday 
        else:
            cur += pd.Timedelta(days=1)

    # Title
    title = f'Every day Orders: {df("date").min():%b %d, %Y} - {df("date").max():%b %d, %Y}'
    ax.set_title(title, fontsize=16)

    # Format x-axis dates
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %d')) 
    ax.xaxis.set_major_locator(mdates.WeekdayLocator(interval=1))

    plt.tight_layout()

    # Acquire url
    image_url = fig_to_data_url(fig)

    return image_url

Die Abbildungen 1-3 werden durch die obige Darstellung von Routine erzeugt.

2.4 strukturierter Ausgang

Lassen Sie uns in diesem Abschnitt erörtern, wie das O3-Modell ein konsistentes JSON-Format anstelle von Freiformtext ausgibt. Dies ist das, was als „strukturierte Ausgabe“ bezeichnet wird, und es ist einer der wichtigsten Ermöglicher für die Integration von LLMs in vorhandene automatische Workflows.

Um dies zu erreichen, definieren wir zunächst das Schema, das die erwartete Ausgangsstruktur regelt. Wir werden ein pydantisches Modell verwenden:

from pydantic import BaseModel, Discipline
from typing import Literal
from datetime import date

AnomalyKind = Literal("spike", "drop", "level_shift", "seasonal_outlier")

class DateWindow(BaseModel):
    begin: date = Discipline(description="Earliest believable date the anomaly begins (ISO YYYY-MM-DD)")
    finish: date = Discipline(description="Newest believable date the anomaly ends, inclusive (ISO YYYY-MM-DD)")

class AnomalyReport(BaseModel):
    when: DateWindow = Discipline(
        description=(
            "Minimal window that incorporates the anomaly. "
            "For single-point anomalies, use the interval that covers studying uncertainty, if the tick labels are unclear"
        )
    )
    y: int = Discipline(description="Approx worth on the anomaly’s most consultant day (peak/lowest), rounded")
    sort: AnomalyKind = Discipline(description="The kind of the anomaly")
    why: str = Discipline(description="One-sentence purpose for why this window is uncommon")
    date_confidence: Literal("low","medium","excessive") = Discipline(
        default="medium", description="Confidence that the window localization is right"
    )

Unser pydantisches Schema versucht, sowohl die quantitativen als auch die qualitativen Aspekte der erkannten Anomalien zu erfassen. Für jedes Feld geben wir seinen Datentyp an (z. B., z. B., int für numerische Werte, Literal für eine feste Auswahl usw.).

Außerdem verwenden wir Discipline Funktion zur Bereitstellung detaillierter Beschreibungen jedes Schlüssels. Diese Beschreibungen sind besonders wichtig, da sie effektiv als Inline -Anweisungen für O3 dienen, so dass sie die semantische Bedeutung jeder Komponente versteht.

Jetzt haben wir den multimodalen Eingang und die strukturierte Ausgabe abgedeckt, um sie in einem LLM -Aufruf zusammenzustellen.

2,5 O3 Modellaufruf

Um mit O3 mithilfe von multimodalem Eingang und strukturierten Ausgang mit O3 zu interagieren, verwenden wir LLM_client.beta.chat.completions.parse() API. Einige der wichtigsten Argumente umfassen:

  • mannequin: Der Einsatzname;
  • messages: das an das O3 -Modell gesendete Nachrichtenobjekt;
  • max_completion_token: Die maximale Anzahl von Token, die das Modell in seiner endgültigen Antwort erzeugen kann. Beachten Sie, dass sie für Argumentationsmodelle wie O3 argumentation_tokens intern erzeugen werden, um das Drawback zu „nachdenken“. Die jetzige max_completion_token Begrenzt nur die sichtbaren Ausgabe -Token, die Benutzer erhalten.
  • response_format: Das pydantische Modell, das die erwartete JSON -Schemastruktur definiert;
  • reasoning_effort: Ein Kontrollknopf, der vorschreibt, wie viel Rechenaufwand O3 für die Argumentation verwenden sollte. Die verfügbaren Optionen umfassen niedrig, mittel und hoch.

Wir können eine Helferfunktion definieren, um mit dem O3 -Modell zu interagieren:

def anomaly_detection(instruction, fig_path, 
                      response_format, immediate=None, 
                      deployment="o3", reasoning_effort="excessive"):

    # Compose messages
    messages=(
            { "function": "system", "content material": instruction},
            { "function": "person", "content material": (  
                { 
                    "kind": "image_url",
                    "image_url": {
                        "url": fig_path,
                        "element": "excessive"
                    }
                },
            )} 
    )

    # Add immediate whether it is given
    if immediate just isn't None:
        messages(1)("content material").append({"kind": "textual content", "textual content": immediate})

    # Invoke LLM API
    response = LLM_client.beta.chat.completions.parse(
        mannequin=deployment,
        messages=messages,
        max_completion_tokens=4000,
        reasoning_effort=reasoning_effort,
        response_format=response_format
    )

    return response.decisions(0).message.parsed.model_dump()

Beachten Sie, dass die messages Objekt akzeptiert sowohl Textual content- als auch Bildinhalt. Da wir ausschließlich Zahlen verwenden, um das Modell aufzufordern, ist die Textaufforderung optionally available.

Wir setzen die "element": "excessive" Um eine hochauflösende Bildverarbeitung zu ermöglichen. Für unsere aktuelle Fallstudie ist dies höchstwahrscheinlich erforderlich, da wir O3 benötigen, um feine Particulars wie Axis Tick -Etiketten, Datenpunktwerte und subtile visuelle Muster besser zu lesen. Beachten Sie jedoch, dass eine hohe Element-Verarbeitung mehr Token und höhere API-Kosten verursachen würde.

Schließlich durch Verwendung .parsed.model_dump()Wir verwandeln die JSON -Ausgabe in ein übliches Python -Wörterbuch.

Das ist es für die Implementierung. Lassen Sie uns als nächstes einige Ergebnisse sehen.


3. Ergebnisse

In diesem Abschnitt geben wir die zuvor erzeugten Zahlen in das O3 -Modell ein und bitten es, potenzielle Anomalien zu identifizieren.

3.1 Spike -Anomalie

# df_spike_anomaly is the dataframe of the primary set of artificial information (Determine 1)
spike_anomaly_url = create_fig(df_spike_anomaly)

# Anomaly detection
end result = anomaly_detection(instruction,
                          spike_anomaly_url,
                          response_format=AnomalyReport,
                          reasoning_effort="medium")
print(end result)

Im obigen Anruf die spike_anomaly_url ist die Daten -URL für Abbildung 1. Die Ausgabe des Ergebniss ist unten dargestellt:

{
  'when': {'begin': datetime.date(2025, 8, 19), 'finish': datetime.date(2025, 8, 21)}, 
  'y': 166, 
  'sort': 'spike', 
  'why': 'Single day orders bounce to ~166, far above adjoining days that sit close to 120–130.', 
  'date_confidence': 'medium'
}

Wir sehen, dass das O3 -Modell die Ausgabe genau in dem von uns entworfenen Format zurückgegeben hat. Jetzt können wir dieses Ergebnis erzielen und programmgesteuert eine Visualisierung erstellen:

# Create picture
fig, ax = plt.subplots(figsize=(8, 4.5))
df_spike_anomaly('date') = pd.to_datetime(df_spike_anomaly('date'))
ax.plot(df_spike_anomaly("date"), df_spike_anomaly("orders"), linewidth=2)
ax.set_xlabel('Date', fontsize=14)
ax.set_ylabel('Every day Orders', fontsize=14)

# Format x-axis dates
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %d'))  
ax.xaxis.set_major_locator(mdates.WeekdayLocator(interval=1)) 

# Add anomaly overlay
start_date = pd.to_datetime(end result('when')('begin'))
end_date = pd.to_datetime(end result('when')('finish'))

# Add shaded area
ax.axvspan(start_date, end_date, alpha=0.3, colour='crimson', label=f"Anomaly ({end result('sort')})")

# Add textual content annotation
mid_date = start_date + (end_date - start_date) / 2  # Center of anomaly window
ax.annotate(
    end result('why'), 
    xy=(mid_date, end result('y')), 
    xytext=(10, 20),  # Offset from the purpose
    textcoords='offset factors',
    bbox=dict(boxstyle='spherical,pad=0.5', fc='yellow', alpha=0.7),
    arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0.1'),
    fontsize=10,
    wrap=True
)

# Add legend
ax.legend()

plt.xticks(rotation=0)
plt.tight_layout()

Die generierte Visualisierung sieht so aus:

Abbildung 4. Die Anomalie -Erkennungsergebnisse für Abbildung 1. (Bild des Autors)

Wir können sehen, dass das O3 -Modell die in diesem erste Satz von synthetische Daten vorgestellte Spike -Anomalie korrekt identifiziert hat.

Nicht schlecht, besonders wenn man bedenkt, dass wir kein herkömmliches Modelltraining durchgeführt haben, nur indem wir ein LLM beantragt.

3.2 Schichtanomalie der Ebene

# df_level_shift_anomaly is the dataframe of the 2nd set of artificial information (Determine 2)
level_shift_anomaly_url = create_fig(df_level_shift_anomaly)

# Anomaly detection
end result = anomaly_detection(instruction,
                          level_shift_anomaly_url,
                          response_format=AnomalyReport,
                          reasoning_effort="medium")
print(end result)

Die Ausgabe des Ergebnisses ist unten dargestellt:

{
  'when': {'begin': datetime.date(2025, 8, 26), 'finish': datetime.date(2025, 9, 2)}, 
  'y': 150, 
  'sort': 'level_shift', 
  'why': 'Orders instantly bounce from the 120-135 vary to ~150 on Aug 26 and stay elevated for all subsequent days, indicating a sustained baseline change.', 
  'date_confidence': 'excessive'
}

Auch hier sehen wir, dass das Modell genau identifiziert hat, dass eine Anomalie von „Level_shift“ im Diagramm vorhanden ist:

Abbildung 5. Die Anomalie -Erkennungsergebnisse für Abbildung 2. (Bild des Autors)

3.3 Saisonalitätsanomalie

# df_seasonality_anomaly is the dataframe of the third set of artificial information (Determine 3)
seasonality_anomaly_url = create_fig(df_seasonality_anomaly)

# Anomaly detection
end result = anomaly_detection(instruction,
                          seasonality_anomaly_url,
                          response_format=AnomalyReport,
                          reasoning_effort="medium")
print(end result)

Die Ausgabe des Ergebnisses ist unten dargestellt:

{
  'when': {'begin': datetime.date(2025, 8, 23), 'finish': datetime.date(2025, 8, 24)}, 
  'y': 132, 
  'sort': 'seasonal_outlier', 
  'why': 'Weekend of Aug 23-24 reveals order volumes (~130+) on par with surrounding weekdays, whereas different weekends constantly drop to ~115, making it an out-of-season spike.', 
  'date_confidence': 'excessive'
}

Dies ist ein herausfordernder Fall. Dennoch gelang es unser O3 -Modell, es mit genauer Lokalisierung und einer klaren Argumentationsspur ordnungsgemäß anzugehen. Ziemlich beeindruckend:

Abbildung 6.

4. Zusammenfassung

Glückwunsch! Wir haben erfolgreich eine Anomalie-Erkennungslösung für Zeitreihendaten erstellt, die vollständig durch Visualisierung und Aufforderung funktionierten.

Durch die Fütterung der täglichen Bestellungsdiagramme in das O3 -Argumentationsmodell und die Einschränkung seiner Ausgabe auf ein JSON -Schema gelang es der LLM, drei verschiedene Anomalentypen mit genauer Lokalisierung zu identifizieren. All dies wurde ohne Coaching eines ML -Modells erreicht. Beeindruckend!

Wenn wir einen Schritt zurück treten, können wir sehen, dass die von uns erstellte Lösung das breitere Muster der Kombination von drei Funktionen zeigt:

  • Sehen: Multimodale Eingabe, um das Modell die Zahlen direkt konsumieren zu lassen.
  • Denken: Schritt-für-Schritt-Argumentationsfähigkeit, um komplexe Probleme anzugehen.
  • Integrieren: Strukturierte Ausgabe, die nachgeschaltete Systeme leicht konsumieren können (z. B. Visualisierungen erzeugen).

Die Kombination aus multimodaler Eingabe + Argumentation + strukturierter Ausgabe erzeugt wirklich eine vielseitige Grundlage für nützliche LLM -Anwendungen.

Sie haben jetzt die Bausteine ​​bereit. Was möchten Sie als nächstes bauen?

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert