das Ihre Kennzahlen liest, Anomalien erkennt, vordefinierte Optimierungsregeln anwendet, Jobs bei Bedarf neu startet und jede Entscheidung protokolliert – ohne dass Sie um 2 Uhr morgens auf Verlustkurven starren müssen

In diesem Artikel stelle ich einen einfachen Agenten vor Entwickelt für Deep-Studying-Forscher und ML-Ingenieure das kann:

• Fehler automatisch erkennen
• Visuelle Argumentation über Leistungskennzahlen
• Wenden Sie Ihre vordefinierten Hyperparameter-Strategien an
• Jobs neu starten
• Dokumentieren Sie jede Aktion und jedes Ergebnis

Keine Architektursuche. Kein AutoML. Keine invasiven Umschreibungen Ihrer Codebasis.

Die Implementierung ist bewusst minimal: Containerisieren Sie Ihr Trainingsskript, fügen Sie einen kleinen LangChain-basierten Agenten hinzu, definieren Sie Hyperparameter in YAML und drücken Sie Präferenzen im Markdown aus. Wahrscheinlich machen Sie bereits 50 % davon.

Fügen Sie diesen Agenten in Ihr Handbuch ein practice.py Workflow und gehen Sie an einem einzigen Tag von 0️⃣ auf 💯.

Das Drawback mit Ihren bestehenden Experimenten

🤔 Du denkst endlos über Hyperparameter nach.

▶️ Sie führen practice.py aus.

🐛 Sie beheben den Fehler in practice.py.

🔁 Du Wiederholung practice.py

👀 Du starrst TensorBoard an.

🫠 Du hinterfragst die Realität.

🔄 Du wiederholst.

Jeder praktizierende Deep-Studying-/Machine-Studying-Ingenieur in diesem Bereich tut dies. Schäme dich nicht. Unique Foto von MART PRODUCTION über Pexels. Gif vorgestellt von Grok

Hören Sie auf, Ihr Modell anzustarren und Zahlen auszuspucken

Du bist kein Jedi. Kein Starren wird Sie auf magische Weise dazu bringen (Validierungsverlust | Klassifizierungsgenauigkeit | Verwirrung | jede andere Metrik, die Sie nennen können) Bewegen Sie sich in die gewünschte Richtung.

Mitten in der Nacht ein Mannequin für einen verschwindenden/explodierenden Farbverlauf babysitten NaN in einem tiefen transformatorbasierten Netzwerk, das Sie nicht aufspüren können – und das möglicherweise nie auftaucht? Auch ein hart nein.

Wie soll man echte Forschungsprobleme lösen, wenn man die meiste Zeit mit Arbeit verbringt, die technisch erledigt werden muss, aber nur sehr wenig zu tatsächlichen Erkenntnissen beiträgt?

Wenn 70 % Ihres Tages durch betriebliche Belastungen in Anspruch genommen werden, wann kommt die Überlegung dann zum Tragen?

Wechseln Sie zu agentengesteuerten Experimenten

Die meisten Deep-Studying-Ingenieure und Forscher, mit denen ich zusammenarbeite, führen Experimente immer noch manuell durch. Ein erheblicher Teil des Tages wird darauf verwendet, Weights & Biases oder TensorBoard nach dem Lauf der letzten Nacht zu durchsuchen, Läufe zu vergleichen, Metriken zu exportieren, Hyperparameter anzupassen, Notizen zu protokollieren und Jobs neu zu starten. Dann wird der Zyklus wiederholt.

Es ist eine trockene, mühsame und sich wiederholende Arbeit.

Wir werden Ihnen diese sich wiederholenden Aufgaben abnehmen, damit Sie sich auf hochwertige Arbeit konzentrieren können

Das Konzept von AutoML ist ehrlich gesagt lächerlich.

Dein (neu) Der Agent trifft keine Entscheidungen darüber, wie Sie Ihre Netzwerktopologie ändern oder komplexe Funktionen hinzufügen – das ist Ihre Aufgabe. Es wird die sich wiederholenden Klebearbeiten ersetzen, die wertvolle Zeit verschlingen und nur einen geringen Mehrwert bieten.

Agentengesteuerte Experimente (ADEs)

Der Wechsel von manuellen Experimenten zu einem agentengesteuerten Workflow ist einfacher, als es zunächst scheint. Kein Umschreiben Ihres Stacks, keine schweren Systeme, keine technischen Schulden.

Bild vom Autor

Im Kern erfordert eine ADE drei Schritte:

  1. Containerisieren Sie Ihr vorhandenes Trainingsskript
    • Wickeln Sie Ihren Strom ein practice.py in einem Docker-Container. Kein Refactoring der Modelllogik. Keine architektonischen Änderungen. Nur eine reproduzierbare Ausführungsgrenze.
  2. Fügen Sie einen leichten Agenten hinzu
    • Führen Sie ein kleines LangChain-basiertes Skript ein, das Metriken aus Ihrem Dashboard liest, Ihre Präferenzen anwendet, entscheidet, wann und wo neu gestartet, angehalten oder dokumentiert werden soll, und es mit cron oder einem anderen Jobplaner plant
  3. Definieren Sie Verhalten und Vorlieben mit natürlicher Sprache
    • Verwenden Sie eine YAML-Datei für Konfiguration und Hyperparameter
    • Verwenden Sie ein Markdown-Dokument, um mit Ihrem Agenten zu kommunizieren

Das ist das gesamte System. Sehen wir uns nun jeden Schritt noch einmal an.

Containerisieren Sie Ihr Trainingsskript

Man könnte argumentieren, dass Sie dies trotzdem tun sollten. Dies erleichtert den Neustart und die Planung erheblich, und wenn Sie zum Coaching auf einen Kubernetes-Cluster umsteigen, ist die Unterbrechung Ihres bestehenden Prozesses viel geringer.

Wenn Sie dies bereits tun, fahren Sie mit dem nächsten Abschnitt fort. Wenn nicht, finden Sie hier einige hilfreiche Codes, die Sie für den Einstieg verwenden können.

Definieren wir zunächst eine Projektstruktur, die mit Docker funktioniert.

your experiment/
├── scripts/
│   ├── practice.py                 # Major coaching script
│   └── health_server.py         # Well being verify server
├── necessities.txt             # Python dependencies
├── Dockerfile                   # Container definition
└── run.sh                       # Script to start out coaching + well being verify

Wir müssen sicherstellen, dass Ihr practice.py Das Skript kann eine Konfigurationsdatei aus der Cloud laden, sodass der Agent sie bei Bedarf bearbeiten kann.

Ich empfehle hierfür GitHub. Hier ist ein Beispiel für das Lesen einer Distant-Konfigurationsdatei. Der Agent verfügt über ein entsprechendes Software zum Lesen und Ändern dieser Konfigurationsdatei.

import os
import requests
import yaml
from field import Field

# add this to `practice.py`
GITHUB_RAW = (
    "https://uncooked.githubusercontent.com/"
    "{proprietor}/{repo}/{ref}/{path}"
)

def load_config_from_github(proprietor, repo, path, ref="principal", token=None):
    url = GITHUB_RAW.format(proprietor=proprietor, repo=repo, ref=ref, path=path)

    headers = {}
    if token:
        headers("Authorization") = f"Bearer {token}"

    r = requests.get(url, headers=headers, timeout=10)
    r.raise_for_status()

    return Field(yaml.safe_load(r.textual content))


config = load_yaml_from_github(...)

# use params all through your `practice.py` script
optimizer = Adam(lr=config.lr)

Wir integrieren auch einen Well being-Verify-Server, der neben dem Hauptprozess läuft. Dadurch können Container-Supervisor wie Kubernetes oder Ihr Agent den Standing des Jobs überwachen ohne Inspektion von Protokollen.

Wenn sich der Zustand des Containers unerwartet ändert, kann er automatisch neu gestartet werden. Dies vereinfacht die Agenteninspektion, da das Lesen und Zusammenfassen von Protokolldateien in Tokens kostspieliger sein kann als nur die Überprüfung des Zustands eines Containers.

# health_server.py
import time
from pathlib import Path
from fastapi import FastAPI, Response

app = FastAPI()

HEARTBEAT = Path("/tmp/heartbeat")
STATUS = Path("/tmp/standing.json")  # non-compulsory richer state
MAX_AGE = 300  # seconds

def last_heartbeat_age():
    if not HEARTBEAT.exists():
        return float("inf")
    return time.time() - float(HEARTBEAT.read_text())

@app.get("/well being")
def well being():
    age = last_heartbeat_age()

    # stale -> coaching probably hung
    if age > MAX_AGE:
        return Response("stalled", status_code=500)

    # non-compulsory: detect NaNs or failure flags written by coach
    if STATUS.exists() and "failed" in STATUS.read_text():
        return Response("failed", status_code=500)

    return {"standing": "okay", "heartbeat_age": age}

Ein kleines Shell-Skript, run.shwas die startet health_server Prozess neben dem practice.py

#!/bin/bash

# Begin well being verify server within the background
python scripts/health_server.py &
# Seize its PID if you wish to terminate later
HEALTH_PID=$!
# Begin the primary coaching script
python scripts/practice.py

Und natürlich unsere Docker-Datei, die auf dem Foundation-Picture von NVIDIA basiert, sodass Ihr Container den Beschleuniger des Hosts reibungslos nutzen kann. Dieses Beispiel ist für Pytorch, aber Sie können es bei Bedarf einfach auf Jax oder Tensorflow erweitern.

FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu20.04

RUN apt-get replace && apt-get set up -y 
    python3 python3-pip git

RUN python3 -m pip set up --upgrade pip

# Set up PyTorch with CUDA help
RUN pip3 set up torch torchvision torchaudio --extra-index-url https://obtain.pytorch.org/whl/cu121

WORKDIR /app

COPY . /app

CMD ("sh", "run.sh")

✅ Du bist containerisiert. Einfach und minimalistisch.

Fügen Sie einen leichten Agenten hinzu

Es stehen viele Agenten-Frameworks zur Auswahl. Für diesen Agenten gefällt mir Langchain.

LangChain ist ein Framework zum Aufbau LLM-gesteuerter Systeme, die Argumentation und Ausführung kombinieren. Es vereinfacht die Verkettung von Modellaufrufen, die Speicherverwaltung und die Integration externer Funktionen, sodass Ihr LLM mehr kann als nur Textual content generieren.

In LangChain, Werkzeuge sind explizit definierte, schemagebundene Funktionen, die das Modell aufrufen kann. Jedes Software ist eine idempotente Fähigkeit oder Aufgabe (z. B. das Lesen einer Datei, das Abfragen einer API, das Ändern des Standing).

Damit unser Agent funktioniert, müssen wir zunächst die Instruments definieren, die er zur Erreichung unseres Ziels verwenden kann.

Werkzeugdefinitionen

  1. read_preferences
    • Liest Benutzereinstellungen und Experimentnotizen aus einem Markdown-Dokument ein
  2. check_tensorboard
    • Verwendet Selenium mit einem Chrome-Webtreiber, um Screenshots von Metriken zu erstellen
  3. analysieren_metrisch
    • Verwendet multimodale LLM-Argumentation, um zu verstehen, was im Screenshot passiert
  4. check_container_health
    • Überprüft unser Container-Experiment mithilfe eines Gesundheitschecks
  5. restart_container
    • Startet das Experiment neu, wenn es fehlerhaft ist oder ein Hyperparameter geändert werden muss
  6. modifizieren_config
    • Ändert eine Distant-Konfigurationsdatei und überträgt sie an Github
  7. write_memory
    • Schreibt eine Aktionskette in einen persistenten Speicher (Markdown)

Diese Instruments definieren die operativen Grenzen unseres Agenten. Die gesamte Interaktion mit unserem Experiment erfolgt über diese Instruments, wodurch das Verhalten kontrollierbar und hoffentlich vorhersehbar wird.

Anstatt diese Instruments on-line bereitzustellen, finden Sie hier eine Github Kern Enthält alle oben beschriebenen Werkzeuge. Sie können diese in Ihren Agenten integrieren oder nach Belieben ändern.

Der Agent

Um ganz ehrlich zu sein: Als ich zum ersten Mal versuchte, die offizielle Langchain-Dokumentation durchzulesen, battle ich von der Idee sofort abgeschreckt.

Es ist zu ausführlich und komplexer als nötig. Wenn Sie mit Agenten noch nicht vertraut sind oder einfach nicht durch das Labyrinth der Langchain-Dokumentation navigieren möchten, lesen Sie bitte weiter unten.

Langsmith? Zufällige Nebenbemerkungen? Überall kleine Tooltips? Ich werde darauf verzichten, diesen würdigen Feind zu besiegen. Vorgestellt von Grok

Kurz gesagt, so funktionieren Langchain-Agenten:

Unser Agent verwendet a immediate um jeweils zu entscheiden, was zu tun ist Schritt.

Schritte werden dynamisch erstellt, indem die Eingabeaufforderung mit dem aktuellen Kontext und früheren Ausgaben gefüllt wird. Jeder LLM-Aufruf (+ optionaler Software-Aufruf) ist ein Schritt, und seine Ausgabe wird in den nächsten eingespeist und bildet einen Kette.

Benutze dies konzeptionell rekursive Schleifekann der Agent über alle erforderlichen Schritte hinweg die richtige beabsichtigte Aktion begründen und ausführen. Die Anzahl der Schritte hängt von der Denkfähigkeit des Agenten ab und davon, wie klar die Abbruchbedingung definiert ist.

Es ist eine Lang-Kette. Bekomme es? 🤗

Die Aufforderung

Wie bereits erwähnt, ist die Eingabeaufforderung der rekursive Klebstoff, der den Kontext über LLM- und Software-Aufrufe hinweg aufrechterhält. Sie sehen Platzhalter (unten definiert), die bei der ersten Initialisierung des Agenten verwendet werden.

Wir verwenden einen Teil der integrierten Speicherabstraktionen von LangChain, die in jedem Software-Aufruf enthalten sind. Darüber hinaus füllt der Agent die Lücken und entscheidet sowohl über den nächsten Schritt als auch darüber, welches Software aufgerufen werden soll.

Zur besseren Lesbarkeit finden Sie unten die Hauptaufforderung. Sie können es entweder direkt in das Agent-Skript einbinden oder es vor der Ausführung aus dem Dateisystem laden.

"You're an experiment automation agent answerable for monitoring 
and sustaining ML experiments.

Present context:
{chat_history}

Your workflow:
1. First, learn preferences from preferences.md to know thresholds and settings
2. Verify TensorBoard on the specified URL and seize a screenshot
3. Analyze key metrics (validation loss, coaching loss, accuracy) from the screenshot
4. Verify Docker container well being for the coaching container
5. Take corrective actions based mostly on evaluation:
   - Restart unhealthy containers
   - Modify hyperparameters in response to person preferences 
     and anomalous patterns, restarting the experiment if vital
6. Log all observations and actions to reminiscence

Vital pointers:
- At all times learn preferences first to get present configuration
- Use visible evaluation to know metric tendencies
- Be conservative with config adjustments (solely modify if clearly wanted)
- Write detailed reminiscence entries for future reference
- Verify container well being earlier than and after any restart
- When modifying config, use acceptable values from preferences

Accessible instruments: {tool_names}
Software descriptions: {instruments}

Present job: {enter}

Suppose step-by-step and use instruments to finish the workflow.
"""

Jetzt mit ca. 100 Leitungen haben wir unseren Agenten. Der Agent wird initialisiert, dann definieren wir eine Reihe von Schritten. Für jeden Schritt wird die current_task Die Direktive wird in unserer Eingabeaufforderung ausgefüllt und jedes Software aktualisiert eine Shared-Reminiscence-Instanz ConverstationSummaryBufferMemory

Wir werden OpenAI für diesen Agenten verwenden, Langchain bietet jedoch Alternativen, einschließlich des Hostens Ihrer eigenen. Wenn die Kosten eine Rolle spielen, gibt es Open-Supply-Modelle, die hier verwendet werden können.

import os
from datetime import datetime
from pathlib import Path
from langchain.brokers import AgentExecutor, create_react_agent
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.reminiscence import ConversationSummaryBufferMemory

# Import instruments from instruments.py
from instruments import (
    read_preferences,
    check_tensorboard,
    analyze_metric,
    check_container_health,
    restart_container,
    modify_config,
    write_memory
)

PROMPT=open("immediate.txt").learn()
class ExperimentAutomation:
    def __init__(self, openai_key=None):
        """Initialize the agent"""
        self.llm = ChatOpenAI(
            temperature=0.8,
            mannequin="gpt-4-turbo-preview",
            api_key=openai_key or os.getenv('OPENAI_API_KEY')
        )

        # Initialize reminiscence for dialog context
        self.reminiscence = ConversationSummaryBufferMemory(
            llm=self.llm,
            max_token_limit=32000,
            memory_key="chat_history",
            return_messages=True
        )

    def create_agent(self):
        """Create LangChain agent with imported instruments"""
        instruments = (
            lambda **kwargs: read_preferences(reminiscence=self.reminiscence, **kwargs),
            lambda **kwargs: check_tensorboard(reminiscence=self.reminiscence, **kwargs),
            lambda **kwargs: analyze_metric(reminiscence=self.reminiscence, **kwargs),
            lambda **kwargs: check_container_health(reminiscence=self.reminiscence, **kwargs),
            lambda **kwargs: restart_container(reminiscence=self.reminiscence, **kwargs),
            lambda **kwargs: modify_config(reminiscence=self.reminiscence, **kwargs),
            lambda **kwargs: write_memory(reminiscence=self.reminiscence, **kwargs)
        )

        # Create the immediate template
        immediate = PromptTemplate.from_template(PROMPT)

        agent = create_react_agent(
            llm=self.llm,
            instruments=instruments,
            immediate=immediate
        )

        # Create agent executor with reminiscence
        return AgentExecutor(
            agent=agent,
            instruments=instruments,
            reminiscence=self.reminiscence,
            verbose=True,
            max_iterations=15,
            handle_parsing_errors=True,
            return_intermediate_steps=True
        )

    def run_automation_cycle(self):
        """Execute the complete automation cycle step-by-step"""
        write_memory(
            entry="Automation cycle began",
            class="SYSTEM",
            reminiscence=self.reminiscence
        )

        attempt:
            agent = self.create_agent()

            # Outline the workflow as particular person steps
            workflow_steps = (
                "Learn preferences from preferences.md to seize thresholds and settings",
                "Verify TensorBoard on the specified URL and seize a screenshot",
                "Analyze validation loss, coaching loss, and accuracy from the screenshot",
                "Verify Docker container well being for the coaching container",
                "Restart unhealthy containers if wanted",
                "Modify hyperparameters in response to preferences and restart container if vital",
                "Write all observations and actions to reminiscence"
            )

            # Execute every step individually
            for step in workflow_steps:
                consequence = agent.invoke({"enter": step})

                # Write step output to reminiscence
                if consequence.get("output"):
                    memory_summary = f"Step: {step}nOutput: {consequence('output')}"
                    write_memory(entry=memory_summary, class="STEP", reminiscence=self.reminiscence)

            write_memory(
                entry="Automation cycle accomplished efficiently",
                class="SYSTEM",
                reminiscence=self.reminiscence
            )

            return consequence

        besides Exception as e:
            error_msg = f"Automation cycle failed: {str(e)}"
            write_memory(entry=error_msg, class="ERROR", reminiscence=self.reminiscence)
            increase


def principal():
    attempt:
        automation = ExperimentAutomation(openai_key=os.environ("OPENAI_API_KEY"))
        consequence = automation.run_automation_cycle()

        if consequence.get('output'):
            print(f"nFinal Output:n{consequence('output')}")

        if consequence.get('intermediate_steps'):
            print(f"nSteps Executed: {len(consequence('intermediate_steps'))}")

        print("n✓ Automation cycle accomplished efficiently")

    besides Exception as e:
        print(f"n✗ Automation failed: {e}")
        write_memory(entry=f"Important failure: {str(e)}", class="ERROR")
        import sys
        sys.exit(1)


if __name__ == "__main__":
    principal()

Nachdem wir nun unseren Agenten und unsere Werkzeuge haben, wollen wir besprechen, wie wir unsere Meinung tatsächlich ausdrücken Absicht als Forscher – das wichtigste Stück.

Definieren Sie Verhalten und Vorlieben mit natürlicher Sprache

Wie bereits beschrieben, ist es entscheidend, zu Beginn eines Experiments zu definieren, wonach wir suchen, um das richtige Verhalten eines Agenten zu erzielen.

Obwohl Picture-Argument-Modelle ziemlich weit gekommen sind und über einen guten Kontext verfügen, müssen sie noch einen weiten Weg zurücklegen, bevor sie verstehen können, wie eine gute Coverage-Loss-Kurve bei der hierarchischen Coverage-Optimierung aussieht oder wie die Ratlosigkeit des Codebuchs in a aussehen sollte Vektorquantisierter Variations-Autoencoderetwas, das ich in der letzten Woche optimiert habe.

Dazu initialisieren wir jede automatisierte Argumentation mit a preferences.md.

Beginnen wir mit einigen allgemeinen Einstellungen

# Experiment Preferences

This file defines my preferences for this experiment.
The agent ought to all the time learn this primary earlier than taking any motion.

---

## Common Settings

- experiment_name: vqvae
- container_name: vqvae-train
- tensorboard_url: http://localhost:6006
- memory_file: reminiscence.md
- maximum_adjustments_per_run: 4
---
## Extra particulars
You possibly can all the time add extra sections right here. The read_preferences job will parse
and cause over every part. 

Lassen Sie uns nun die interessierenden Metriken definieren. Dies ist besonders wichtig beim visuellen Denken.

Definieren Sie im Markdown-Dokument yaml Blöcke, die vom Agenten mithilfe von analysiert werden read_preferences Werkzeug. Das Hinzufügen dieser Struktur ist hilfreich, um Einstellungen als Argumente für andere Instruments zu verwenden.

```yaml
metrics:
  - title: perplexity
    sample: ought to stay excessive by way of the course of coaching
    restart_condition: untimely collapse to zero
    hyperparameters: |
        if collapse, enhance `perplexity_weight` from present worth to 0.2
  - title: prediction_loss
    sample: ought to lower over the course of coaching
    restart_condition: will increase or stalls
    hyperparameters: |
        if will increase, enhance the `prediction_weight` worth from present to 0.4
  - title: codebook_usage
    sample: ought to stay mounted at > 90%
    restart_condition: drops under 90% for a lot of epochs
    hyperparameters: |
        lower the `codebook_size` param from 512 to 256. 

```

Die Schlüsselidee ist, dass die preferences.md bereitstellen sollte genügend strukturierte und beschreibende Particulars So kann der Agent:

Vergleichen Sie die Analyse mit Ihrer Absichtz. B. wenn der Agent einen Validierungsverlust = 0,6 sieht, die Präferenzen jedoch sagen val_loss_threshold needs to be 0.5weiß es, was die Korrekturmaßnahme sein sollte

Lesen Sie die Schwellenwerte und Einschränkungen (YAML oder Schlüsselwert) für Metriken, Hyperparameter und Containerverwaltung.

Absichten oder Absichtsmuster verstehen in für Menschen lesbaren Abschnitten beschrieben, wie zum Beispiel „Passen Sie die Lernrate nur an, wenn der Validierungsverlust den Schwellenwert überschreitet und die Genauigkeit stagniert.“

Alles zusammen verkabeln

Da wir nun ein Containerexperiment + einen Agenten haben, müssen wir den Agenten planen. Dies ist so einfach wie das Ausführen des Agentenprozesses über a cron Aufgabe. Dadurch wird unser Agent einmal professional Stunde ausgeführt, wodurch ein Kompromiss zwischen Kosten (in Token) und betrieblicher Effizienz erzielt wird.

0 * * * * /usr/bin/python3 /path/to/agent.py >> /var/log/agent.log 2>&1

Ich habe festgestellt, dass dieser Agent nicht das neueste Argumentationsmodell benötigt und mit den vorherigen Generationen von Anthropic und OpenAI intestine funktioniert.

Einpacken

Wenn die Forschungszeit begrenzt ist, sollte sie für die Forschung und nicht für Babysitting-Experimente aufgewendet werden.

Ihr Agent sollte die Überwachung, Neustarts und Parameteranpassungen ohne ständige Aufsicht durchführen. Wenn der Widerstand verschwindet, bleibt die eigentliche Arbeit: Hypothesen aufstellen, bessere Modelle entwerfen und Ideen testen, die wichtig sind.

Hoffentlich gibt Ihnen dieser Agent etwas Freiraum, um sich die nächste große Idee auszudenken. Genießen.

Referenzen

Müller, T., Smith, J. & Li, Okay. (2023). LangChain: Ein Framework zur Entwicklung von Anwendungen mit großen Sprachmodellen. GitHub-Repository. https://github.com/hwchase17/langchain

OpenAI. (2023). OpenAI-API-Dokumentation. https://platform.openai.com/docs

Von admin

Schreibe einen Kommentar

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