Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Erstellen Sie einen intelligenten KI-Agent mithilfe von Go und Azure DocumentDB. Diese Schnellstartanleitung veranschaulicht eine Zwei-Agent-Architektur, die die semantische Hotelsuche durchführt und personalisierte Empfehlungen generiert.
Von Bedeutung
Dieses Beispiel ist eine Referenzimplementierung, die agentische Muster in Go veranschaulicht. Es verwendet eine benutzerdefinierte Agentarchitektur anstelle eines Agentframeworks, was der empfohlene Ansatz für agentische Produktionsanwendungen ist.
Voraussetzungen
Sie können die Azure Developer CLI verwenden, um die erforderlichen Azure-Ressourcen zu erstellen, indem Sie die azd Befehle im Beispiel-Repository ausführen. Weitere Informationen finden Sie unter Deploy Infrastructure with Azure Developer CLI.
Azure-Ressourcen
Azure OpenAI-Ressource mit den folgenden Modellbereitstellungen in Microsoft Foundry:
-
gpt-4oBereitstellung (Synthesizer Agent) - Empfohlen: 50.000 Token pro Minute (TPM) Kapazität -
gpt-4o-miniBereitstellung (Planner Agent) – Empfohlen: 30.000 Token pro Minute (TPM) Kapazität -
text-embedding-3-smallBereitstellung (Embeddings) - Empfohlen: 10.000 Token pro Minute (TPM) Kapazität -
Tokenkontingente: Konfigurieren Sie für jede Bereitstellung ausreichende TPM, um eine Ratenbeschränkung zu vermeiden.
- Siehe Verwalten von Azure OpenAI-Kontingenten für die Kontingentverwaltung
- Wenn 429 Fehler auftreten, erhöhen Sie ihr TPM-Kontingent, oder verringern Sie die Anforderungshäufigkeit.
-
Azure DocumentDB (mit MongoDB-Kompatibilität) Cluster mit Vektorsuchunterstützung:
-
Anforderungen der Clusterebene basierend auf dem Vektorindexalgorithmus:
- IVF (Invertierter Dateiindex): M10 oder höher (Standardalgorithmus)
- HNSW (hierarchische navigierbare Kleine Welt): M30 oder höher (graphbasiert)
- DiskANN: M40 oder höher (optimiert für groß angelegte Anwendungen)
-
Firewallkonfiguration: ERFORDERLICH Ohne ordnungsgemäße Firewallkonfiguration schlagen Verbindungsversuche fehl.
- Fügen Sie Ihre Client-IP-Adresse zu den Firewallregeln des Clusters hinzu. Weitere Informationen finden Sie unter Gewähren des Zugriffs von Ihrer IP-Adresse.
- Für die kennwortlose Authentifizierung ist die rollenbasierte Zugriffssteuerung (Role Based Access Control, RBAC) aktiviert.
-
Anforderungen der Clusterebene basierend auf dem Vektorindexalgorithmus:
Entwicklungstools
Architektur
Im Beispiel wird eine Zwei-Agent-Architektur verwendet, in der jeder Agent eine bestimmte Rolle hat.
In diesem Beispiel wird eine benutzerdefinierte Implementierung mit dem OpenAI SDK direkt verwendet, ohne sich auf ein Agentframework zu verlassen. Es nutzt OpenAI-Funktionsaufrufe für die Tool-Integration und folgt einem linearen Workflow zwischen den Agenten und dem Such-Tool. Die Ausführung erfolgt statuslos und ohne Historie der Kommunikation, so dass sie sich für Abfrage- und Antwortszenarien mit nur einem Durchgang eignet.
Holen Sie sich den Beispielcode
Klonen Sie oder laden Sie das Repository Azure DocumentDB Samples auf Ihren lokalen Computer herunter, um den Schnellstartanweisungen zu folgen.
Navigieren Sie zum Projektverzeichnis:
cd ai/vector-search-agent-go
Umgebungsvariablen konfigurieren
Erstellen Sie eine .env Datei im Projektstamm, um Umgebungsvariablen zu konfigurieren. Sie können eine Kopie der .env.sample Datei aus dem Repository erstellen.
Bearbeiten Sie die .env Datei, und ersetzen Sie diese Platzhalterwerte:
Diese Schnellstartanleitung verwendet eine Zwei-Agent-Architektur (Planner + Synthesizer) mit drei Modellbereitstellungen (zwei Chatmodelle + Einbettungen). Die Umgebungsvariablen werden für jede Modellbereitstellung konfiguriert.
-
AZURE_OPENAI_PLANNER_DEPLOYMENT: Ihr gpt-4o-mini Bereitstellungsname -
AZURE_OPENAI_SYNTH_DEPLOYMENT: Ihr gpt-4o-Bereitstellungsname -
AZURE_OPENAI_EMBEDDING_DEPLOYMENT: Ihr text-embedding-3-small Name für die Bereitstellung
Sie können zwischen zwei Authentifizierungsmethoden wählen: kennwortlose Authentifizierung mit Azure Identity (empfohlen) oder herkömmlicher Verbindungszeichenfolge und API-Schlüssel.
Option 1: Kennwortlose Authentifizierung
Verwenden Sie kennwortlose Authentifizierung mit Azure OpenAI und Azure DocumentDB. Set USE_PASSWORDLESS=true, AZURE_OPENAI_ENDPOINT und AZURE_DOCUMENTDB_CLUSTER.
# Enable passwordless authentication
USE_PASSWORDLESS=true
# Azure OpenAI Configuration (passwordless)
AZURE_OPENAI_ENDPOINT=your-openai-endpoint
# Azure DocumentDB (passwordless)
AZURE_DOCUMENTDB_CLUSTER=your-mongo-cluster-name
AZURE_DOCUMENTDB_DATABASENAME=Hotels
AZURE_DOCUMENTDB_COLLECTION=hotel_data
AZURE_DOCUMENTDB_INDEX_NAME=vectorIndex
Voraussetzungen für die kennwortlose Authentifizierung:
Stellen Sie sicher, dass Sie bei Azure angemeldet sind:
az loginGewähren Sie Ihrer Identität die folgenden Rollen:
-
Cognitive Services OpenAI Userauf der Azure OpenAI-Ressource -
DocumentDB Account ContributorundCosmos DB Account Reader Roleauf der Azure DocumentDB-Ressource
Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zuweisen von Azure-Rollen mithilfe des Azure-Portals.
-
Option 2: Verbindungszeichenfolge und API-Schlüsselauthentifizierung
Verwenden Sie die schlüsselbasierte Authentifizierung, indem Sie USE_PASSWORDLESS=false festlegen (oder weglassen) und die Werte AZURE_OPENAI_API_KEY und AZURE_DOCUMENTDB_CONNECTION_STRING in Ihrer .env-Datei bereitstellen.
# Disable passwordless authentication
USE_PASSWORDLESS=false
# Azure OpenAI Configuration (API key)
AZURE_OPENAI_ENDPOINT=your-openai-endpoint
AZURE_OPENAI_API_KEY=your-azure-openai-api-key
# Azure DocumentDB (connection string)
AZURE_DOCUMENTDB_CONNECTION_STRING=mongodb+srv://username:password@cluster.mongocluster.cosmos.azure.com/
AZURE_DOCUMENTDB_DATABASENAME=Hotels
AZURE_DOCUMENTDB_COLLECTION=hotel_data
AZURE_DOCUMENTDB_INDEX_NAME=vectorIndex
Projektstruktur
Das Projekt folgt dem standardmäßigen Go-Projektlayout. Die Verzeichnisstruktur sollte wie die folgende Struktur aussehen:
mongo-vcore-agent-go/
├── cmd/
│ ├── agent/ # Main agent application
│ │ └── main.go
│ ├── upload/ # Data upload utility
│ │ └── main.go
│ └── cleanup/ # Database cleanup utility
│ └── main.go
├── internal/
│ ├── agents/ # Agent and tool implementations
│ │ ├── agents.go # Planner and synthesizer agents
│ │ └── tools.go # Vector search tool
│ ├── clients/ # Azure OpenAI client
│ │ └── openai.go
│ ├── models/ # Hotel data models
│ │ └── hotel.go
│ ├── prompts/ # System prompts and tool definitions
│ │ └── prompts.go
│ └── vectorstore/ # Azure DocumentDB vector store operations
│ └── store.go
├── .env # Environment variable configuration
├── go.mod # Go module file
└── go.sum # Go module checksum file
Den Code erkunden
In diesem Abschnitt werden die Kernkomponenten des AI-Agent-Workflows erläutert. Es hebt hervor, wie die Agents Anforderungen verarbeiten, wie Tools die KI mit der Datenbank verbinden und wie Aufforderungen das Verhalten der KI leiten.
Agentanwendung
Die cmd/agent/main.go Datei orchestriert ein KI-gestütztes Hotelempfehlungssystem.
Die Anwendung verwendet zwei Azure-Dienste:
- Azure OpenAI, das KI-Modelle verwendet, die Abfragen verstehen und Empfehlungen generieren
- Azure DocumentDB, das Hoteldaten speichert und Vektor-Ähnlichkeitssuchen durchführt
Agent- und Toolkomponenten
Die drei Komponenten arbeiten zusammen, um die Hotelsuchanfrage zu verarbeiten:
- Planner-Agent – Interpretiert die Anfrage und entscheidet, wie gesucht werden soll
- Vektorsuchtool – Findet Hotels, die dem entsprechen, was der Planer-Agent beschreibt.
- Synthesizer-Agent - Schreibt eine hilfreiche Empfehlung basierend auf Suchergebnissen
Anwendungsablauf
Die Anwendung verarbeitet eine Hotelsuchanfrage in zwei Schritten:
- Planung: Der Workflow ruft den Planer-Agent auf, der die Abfrage des Benutzers analysiert (z. B. "Hotels in der Nähe von Laufpfaden"), und durchsucht die Datenbank nach übereinstimmenden Hotels.
- Synthese: Der Workflow ruft den Synthesizer-Agent auf, der die Suchergebnisse überprüft und eine personalisierte Empfehlung schreibt, in der erläutert wird, welche Hotels am besten mit der Anforderung übereinstimmen.
// Run planner agent
hotelContext, err := plannerAgent.Run(ctx, query, nearestNeighbors)
if err != nil {
log.Fatalf("Planner agent failed: %v", err)
}
if debug {
fmt.Printf("\n--- HOTEL CONTEXT ---\n%s\n", hotelContext)
}
// Run synthesizer agent
finalAnswer, err := synthesizerAgent.Run(ctx, query, hotelContext)
if err != nil {
log.Fatalf("Synthesizer agent failed: %v", err)
}
Agenten
Die internal/agents/agents.go Quelldatei implementiert die Planner- und Synthesizer-Agents, die zusammenarbeiten, um Hotelsuchanfragen zu verarbeiten.
Planungsagent
Der Planner-Agent ist der Entscheidungsträger , der bestimmt, wie nach Hotels gesucht wird.
Der Planner-Agent empfängt die Abfrage der natürlichen Sprache des Benutzers und sendet sie an ein KI-Modell zusammen mit verfügbaren Tools, die er verwenden kann. Die KI entscheidet, das Vektorsuchtool aufzurufen und Stellt Suchparameter bereit. Der Agent extrahiert dann den Toolnamen und die Argumente aus der Antwort der KI, führt das Suchtool aus und gibt die übereinstimmenden Hotels zurück. Anstatt die Suchlogik fest zu programmieren, interpretiert die KI, was der Benutzer möchte, und wählt die Suchmethode aus, wodurch das System flexibel für verschiedene Arten von Abfragen wird.
// PlannerAgent orchestrates the tool calling
type PlannerAgent struct {
openAIClients *clients.OpenAIClients
searchTool *VectorSearchTool
debug bool
}
// NewPlannerAgent creates a new planner agent
func NewPlannerAgent(openaiClients *clients.OpenAIClients, searchTool *VectorSearchTool, debug bool) *PlannerAgent {
return &PlannerAgent{
openAIClients: openaiClients,
searchTool: searchTool,
debug: debug,
}
}
// Run executes the planner agent workflow
func (a *PlannerAgent) Run(ctx context.Context, userQuery string, nearestNeighbors int) (string, error) {
fmt.Println("\n--- PLANNER ---")
userMessage := fmt.Sprintf(
`Search for hotels matching this request: "%s". Use nearestNeighbors=%d.`,
userQuery,
nearestNeighbors,
)
// Get tool definition
toolDef := a.searchTool.GetToolDefinition()
// Call planner with tool definitions
resp, err := a.openAIClients.ChatCompletionWithTools(ctx, prompts.PlannerSystemPrompt, userMessage, []openai.ChatCompletionToolUnionParam{toolDef})
if err != nil {
return "", fmt.Errorf("planner failed: %w", err)
}
// Extract tool call
toolName, argsMap, err := clients.ExtractToolCall(resp)
if err != nil {
return "", fmt.Errorf("failed to extract tool call: %w", err)
}
if toolName != prompts.ToolName {
return "", fmt.Errorf("unexpected tool called: %s", toolName)
}
// Parse arguments using typed struct
args, err := parseToolArgumentsFromMap(argsMap)
if err != nil {
return "", fmt.Errorf("failed to parse tool arguments: %w", err)
}
// Use default if nearestNeighbors not provided
if args.NearestNeighbors == 0 {
args.NearestNeighbors = nearestNeighbors
}
fmt.Printf("Tool: %s\n", toolName)
fmt.Printf("Query: %s\n", args.Query)
fmt.Printf("K: %d\n", args.NearestNeighbors)
// Execute the tool
searchResults, err := a.searchTool.Execute(ctx, args.Query, args.NearestNeighbors)
if err != nil {
return "", fmt.Errorf("search tool execution failed: %w", err)
}
return searchResults, nil
}
Synthesizer Agent
Der Synthesizer-Agent ist der Autor , der hilfreiche Empfehlungen erstellt.
Der Synthesizer-Agent empfängt die ursprüngliche Benutzerabfrage zusammen mit den Suchergebnissen des Hotels. Es sendet alles an ein KI-Modell mit Anweisungen zum Schreiben von Empfehlungen. Sie gibt eine Natürliche Sprachantwort zurück, die Hotels vergleicht und die besten Optionen erläutert. Dieser Ansatz ist wichtig, da unformatierte Suchergebnisse nicht benutzerfreundlich sind. Der Synthesizer wandelt Datenbankdatensätze in eine Unterhaltungsempfehlung um, die erklärt, warum bestimmte Hotels den Anforderungen des Benutzers entsprechen.
// NewSynthesizerAgent creates a new synthesizer agent
func NewSynthesizerAgent(openaiClients *clients.OpenAIClients, debug bool) *SynthesizerAgent {
return &SynthesizerAgent{
openAIClients: openaiClients,
debug: debug,
}
}
// Run executes the synthesizer agent workflow
func (a *SynthesizerAgent) Run(ctx context.Context, userQuery, hotelContext string) (string, error) {
fmt.Println("\n--- SYNTHESIZER ---")
fmt.Printf("Context size: %d characters\n", len(hotelContext))
userMessage := prompts.CreateSynthesizerUserPrompt(userQuery, hotelContext)
// Call synthesizer (no tools)
finalAnswer, err := a.openAIClients.ChatCompletion(ctx, prompts.SynthesizerSystemPrompt, userMessage)
if err != nil {
return "", fmt.Errorf("synthesizer failed: %w", err)
}
return finalAnswer, nil
}
Agentenwerkzeuge
Die internal/agents/tools.go Quelldatei definiert das Vektorsuchtool, das der Planner-Agent verwendet.
Die Toolsdatei definiert ein Suchtool, mit dem der KI-Agent Hotels finden kann. Dieses Tool zeigt, wie der Agent eine Verbindung mit der Datenbank herstellt. Die KI durchsucht die Datenbank nicht direkt. Es wird aufgefordert, das Suchtool zu verwenden, und das Tool führt die eigentliche Suche aus.
Tool-Definition
Die GetToolDefinition Methode beschreibt das Tool für das KI-Modell in einem format, das es versteht. Es gibt den Namen des Tools, eine Beschreibung der Funktionsweise des Tools und die Parameter an, die definieren, welche Eingaben das Tool benötigt. Diese Definition informiert die KI darüber, dass das Tool vorhanden ist und wie es richtig verwendet wird.
// GetToolDefinition returns the Azure OpenAI tool definition
func (t *VectorSearchTool) GetToolDefinition() openai.ChatCompletionToolUnionParam {
paramSchema := map[string]any{
"type": "object",
"properties": map[string]any{
"query": map[string]any{
"type": "string",
"description": "Natural language search query describing desired hotel characteristics",
},
"nearestNeighbors": map[string]any{
"type": "integer",
"description": "Number of results to return (1-20)",
"default": 5,
},
},
"required": []string{"query", "nearestNeighbors"},
}
return openai.ChatCompletionToolUnionParam{
OfFunction: &openai.ChatCompletionFunctionToolParam{
Function: openai.FunctionDefinitionParam{
Name: prompts.ToolName,
Description: openai.String(prompts.ToolDescription),
Parameters: paramSchema,
},
},
}
}
Ausführung des Tools
Wenn die KI das Tool aufruft, wird die Execute Methode ausgeführt. Es generiert eine Einbettung, indem die Textabfrage mithilfe des Einbettungsmodells von Azure OpenAI in einen numerischen Vektor konvertiert wird. Anschließend durchsucht sie die Datenbank, indem sie den Vektor an Azure DocumentDB sendet, der Hotels mit ähnlichen Vektoren findet, was ähnliche Beschreibungen bedeutet. Schließlich werden Ergebnisse formatiert, indem die Datenbankdatensätze in lesbaren Text konvertiert werden, den der Synthesizer-Agent verstehen kann.
// Execute performs the vector search
func (t *VectorSearchTool) Execute(ctx context.Context, query string, nearestNeighbors int) (string, error) {
// Generate embedding for query
queryVector, err := t.openAIClients.GenerateEmbedding(ctx, query)
if err != nil {
return "", fmt.Errorf("failed to generate embedding: %w", err)
}
// Perform vector search
results, err := t.vectorStore.VectorSearch(ctx, queryVector, nearestNeighbors)
if err != nil {
return "", fmt.Errorf("vector search failed: %w", err)
}
// Format results for synthesizer
var formattedResults []string
for i, result := range results {
fmt.Printf("Hotel #%d: %s, Score: %.6f\n", i+1, result.Hotel.HotelName, result.Score)
formattedResults = append(formattedResults, vectorstore.FormatHotelForSynthesizer(result))
}
return strings.Join(formattedResults, "\n\n"), nil
}
Warum dieses Muster verwenden?
Das Trennen des Tools vom Agenten bietet Flexibilität. Die KI entscheidet, wann gesucht und was gesucht werden soll, während das Tool die Suche behandelt. Sie können weitere Tools hinzufügen, ohne die Agentlogik zu ändern.
Aufforderungen
Die internal/prompts/prompts.go Quelldatei enthält Systemaufforderungen und Tooldefinitionen für die Agents.
Die Prompt-Datei definiert die Anweisungen und den Kontext, die den KI-Modellen für die Planer- und Synthesizer-Agenten bereitgestellt werden. Diese Hinweise lenken das Verhalten der KI und stellen sicher, dass sie ihre Rolle im Arbeitsablauf versteht.
Die Qualität der KI-Antworten hängt stark von klaren Anweisungen ab. Diese Eingabeaufforderungen legen Grenzen fest, definieren das Ausgabeformat und konzentrieren die KI auf das Ziel des Benutzers, eine Entscheidung zu treffen. Sie können diese Eingabeaufforderungen anpassen, um zu ändern, wie sich die Agents verhalten, ohne Code zu ändern.
const PlannerSystemPrompt = `You are a hotel search planner. Your job is to help users find hotels by calling the search tool.
CRITICAL INSTRUCTION: You MUST call the "search_hotels_collection" tool for every request. This is the ONLY way to search the database.
When you call the tool, use these parameters:
- query: A clear, detailed natural language description of what the user is looking for. Expand vague requests (e.g., "nice hotel" → "hotel with high ratings, good reviews, and quality amenities").
- nearestNeighbors: Number of results (1-20). Use 3-5 for specific requests, 10-15 for broader searches.
EXAMPLES of how you should call the tool:
- User: "cheap hotel" → Call tool with query: "budget-friendly hotel with good value and affordable rates", nearestNeighbors: 10
- User: "hotel near downtown with parking" → Call tool with query: "hotel near downtown with good parking and wifi", nearestNeighbors: 5
IMPORTANT: Always call the tool. Do not provide answers without calling the tool first.`
const SynthesizerSystemPrompt = `You are an expert hotel recommendation assistant using vector search results.
Only use the TOP 3 results provided. Do not request additional searches or call other tools.
GOAL: Provide a concise comparative recommendation to help the user choose between the top 3 options.
REQUIREMENTS:
- Compare only the top 3 results across the most important attributes: rating, score, location, price-level (if available), and key tags (parking, wifi, pool).
- Identify the main tradeoffs in one short sentence per tradeoff.
- Give a single clear recommendation with one short justification sentence.
- Provide up to two alternative picks (one sentence each) explaining when they are preferable.
FORMAT CONSTRAINTS:
- Plain text only (no markdown).
- Keep the entire response under 220 words.
- Use simple bullets (•) or numbered lists and short sentences (preferably <25 words per sentence).
- Preserve hotel names exactly as provided in the tool summary.
Do not add extra commentary, marketing language, or follow-up questions. If information is missing and necessary to choose, state it in one sentence and still provide the best recommendation based on available data.`
Beispiel ausführen
Bevor Sie den Agenten ausführen, laden Sie Hoteldaten mit Einbettungen hoch. Der
cmd/upload/main.goBefehl lädt Hotels aus der JSON-Datei, generiert Einbettungen für jedes Hotel, fügt Dokumente in Azure DocumentDB ein, und erstellt einen Vektorindex.go run cmd/upload/main.goFühren Sie den Hotelempfehlungs-Agent mithilfe des
cmd/agent/main.goBefehls aus. Der Agent ruft den Planner-Agenten, die Vektorsuche und den Synthesizer-Agenten auf. Die Ausgabe umfasst Ähnlichkeitsscores und die vergleichende Analyse des Synthesizer Agents mit Empfehlungen.go run cmd/agent/main.goQuery: quintessential lodging near running trails, eateries, retail Nearest Neighbors: 5 --- PLANNER --- Tool: search_hotels_collection Query: quintessential lodging near running trails, eateries, and retail shops with good amenities and access to outdoor activities K: 5 Hotel #1: Nordick's Valley Motel, Score: 0.498665 Hotel #2: White Mountain Lodge & Suites, Score: 0.487320 Hotel #3: Trails End Motel, Score: 0.479854 Hotel #4: Country Comfort Inn, Score: 0.474320 Hotel #5: Lakefront Captain Inn, Score: 0.457873 --- SYNTHESIZER --- Context size: 3233 characters --- FINAL ANSWER --- 1. COMPARISON SUMMARY: • Nordick's Valley Motel has the highest rating (4.5) and offers free parking, air conditioning, and continental breakfast. It is located in Washington D.C., near historic attractions and trails. • White Mountain Lodge & Suites is a resort with unique amenities like a pool, restaurant, and meditation gardens, but has the lowest rating (2.4). It is located in Denver, surrounded by forest trails. • Trails End Motel is budget-friendly with a moderate rating (3.2), free parking, free wifi, and a restaurant. It is close to downtown Scottsdale and eateries. Key tradeoffs: - Nordick's Valley Motel excels in rating and proximity to historic attractions but lacks a pool or free wifi. - White Mountain Lodge & Suites offers resort-style amenities and forest trails but has the lowest rating. - Trails End Motel balances affordability and essential amenities but has fewer unique features compared to the others. 2. BEST OVERALL: Nordick's Valley Motel is the best choice for its high rating, proximity to trails and attractions, and free parking. 3. ALTERNATIVE PICKS: • Choose White Mountain Lodge & Suites if you prioritize resort amenities and forest trails over rating. • Choose Trails End Motel if affordability and proximity to downtown Scottsdale are your main concerns.
Anzeigen und Verwalten von Daten in Visual Studio Code
Wählen Sie die DocumentDB-Erweiterung in Visual Studio Code aus, um eine Verbindung mit Ihrem Azure DocumentDB-Konto herzustellen.
Zeigen Sie die Daten und Indizes der Datenbank "Hotels" an.
Bereinigen von Ressourcen
Verwenden Sie den Bereinigungsbefehl, um die Testdatenbank zu löschen, wenn Sie fertig sind. Führen Sie den folgenden Befehl aus:
go run cmd/cleanup/main.go
Löschen Sie die Ressourcengruppe, das DocumentDB-Konto und die Azure OpenAI-Ressource, wenn Sie sie nicht benötigen, um zusätzliche Kosten zu vermeiden.