Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Cree un agente de INTELIGENCIA ARTIFICIAL inteligente mediante Go y Azure DocumentDB. En este inicio rápido se muestra una arquitectura de dos agentes que realiza la búsqueda semántica de hoteles y genera recomendaciones personalizadas.
Importante
Este ejemplo es una implementación de referencia que muestra patrones agente en Go. Usa una arquitectura de agente personalizada en lugar de un marco de agente, que es el enfoque recomendado para las aplicaciones agente de producción.
Prerrequisitos
Puede usar la CLI para desarrolladores de Azure para crear los recursos de Azure necesarios mediante la ejecución de los azd comandos en el repositorio de ejemplo. Para más información, consulte Implementación de la infraestructura con la CLI para desarrolladores de Azure.
Recursos de Azure
Recurso de Azure OpenAI con las siguientes implementaciones de modelos en Microsoft Foundry:
-
gpt-4oimplementación (Agente de Síntesis) - Se recomienda una capacidad de 50 000 tokens por minuto (TPM) - Implementación de
gpt-4o-mini(Agente de planificador) - Recomendado: capacidad de 30 000 tokens por minuto (TPM) - Implementación de
text-embedding-3-small(inserciones) - Recomendado: capacidad de 10 000 tokens por minuto (TPM) -
Cuotas de token: configure un TPM suficiente para cada implementación para evitar la limitación de velocidad.
- Consulte Administración de cuotas de Azure OpenAI para la administración de cuotas.
- Si encuentra errores 429, aumente la cuota de TPM o reduzca la frecuencia de solicitud.
-
Clúster de Azure DocumentDB (con compatibilidad de MongoDB) con compatibilidad con la búsqueda vectorial:
-
Requisitos del nivel de clúster en función del algoritmo de índice vectorial:
- IVF (Índice de archivo invertido): M10 o superior (algoritmo predeterminado)
- HNSW (Hierarchical Navigable Small World): M30 o superior (basado en grafos)
- DiskANN: M40 o superior (optimizado para gran escala)
-
Configuración del firewall: OBLIGATORIO sin una configuración de firewall adecuada, se produce un error en los intentos de conexión.
- Agregue la dirección IP del cliente a las reglas de firewall del clúster. Para obtener más información, consulte Concesión de acceso desde la dirección IP.
- Para la autenticación sin contraseña, el control de acceso basado en rol (RBAC) está habilitado.
-
Requisitos del nivel de clúster en función del algoritmo de índice vectorial:
Herramientas de desarrollo
- Go 1.22 o posterior
- CLI de Azure para la autenticación
Architecture
En el ejemplo se usa una arquitectura de dos agentes donde cada agente tiene un rol específico.
En este ejemplo se usa una implementación personalizada con el SDK de OpenAI directamente, sin depender de un marco de agente. Aprovecha la llamada de funciones OpenAI para la integración de herramientas y sigue un flujo de trabajo lineal entre los agentes y la herramienta de búsqueda. La ejecución es sin estado y sin historial de conversaciones, lo que la convierte en adecuada para escenarios de consulta y respuesta de un solo turno.
Obtención del código de ejemplo
Clone o descargue el repositorio Ejemplos de Azure DocumentDB en la máquina local para seguir el inicio rápido.
Vaya al directorio del proyecto:
cd ai/vector-search-agent-go
Configuración de las variables de entorno
Cree un .env archivo en la raíz del proyecto para configurar variables de entorno. Puede crear una copia del .env.sample archivo desde el repositorio.
Edite el .env archivo y reemplace estos valores de marcador de posición:
En este inicio rápido se usa una arquitectura de dos agentes (planner + sintetizador) con tres implementaciones de modelos (dos modelos de chat + incrustaciones). Las variables de entorno se configuran para cada implementación del modelo.
-
AZURE_OPENAI_PLANNER_DEPLOYMENT: el nombre de la implementación gpt-4o-mini -
AZURE_OPENAI_SYNTH_DEPLOYMENT: el nombre de su implementación de gpt-4o -
AZURE_OPENAI_EMBEDDING_DEPLOYMENT: el nombre de la implementación de text-embedding-3-small
Puede elegir entre dos métodos de autenticación: autenticación sin contraseña mediante Azure Identity (recomendado) o cadena de conexión tradicional y clave de API.
Opción 1: Autenticación sin contraseña
Use la autenticación sin contraseña con Azure OpenAI y Azure DocumentDB. Establezca USE_PASSWORDLESS=true, AZURE_OPENAI_ENDPOINTy 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
Requisitos previos para la autenticación sin contraseña:
Asegúrese de que ha iniciado sesión en Azure:
az loginConceda a su identidad los roles siguientes:
-
Cognitive Services OpenAI Useren el recurso de Azure OpenAI -
DocumentDB Account ContributoryCosmos DB Account Reader Roleen el recurso de Azure DocumentDB
Para más información sobre cómo asignar roles, consulte Asignación de roles de Azure mediante Azure Portal.
-
Opción 2: Cadena de conexión y autenticación de clave de API
Use la autenticación basada en claves estableciendo USE_PASSWORDLESS=false (o omitiéndolo) y proporcionando los valores de AZURE_OPENAI_API_KEY y AZURE_DOCUMENTDB_CONNECTION_STRING en el archivo .env.
# 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
Estructura de proyecto
El proyecto sigue el diseño estándar del proyecto de Go. La estructura de directorios debe tener un aspecto similar a la estructura siguiente:
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
Exploración del código
En esta sección se describen los componentes principales del flujo de trabajo del agente de IA. Resalta cómo los agentes procesan las solicitudes, cómo las herramientas conectan la inteligencia artificial a la base de datos y cómo las indicaciones guían el comportamiento de la inteligencia artificial.
Aplicación de agente
El cmd/agent/main.go archivo organiza un sistema de recomendaciones de hoteles con tecnología de IA.
La aplicación usa dos servicios de Azure:
- Azure OpenAI que usa modelos de INTELIGENCIA ARTIFICIAL que comprenden las consultas y generan recomendaciones
- Azure DocumentDB que almacena datos de hotel y realiza búsquedas de similitud vectorial
Componentes de agente y herramienta
Los tres componentes funcionan juntos para procesar la solicitud de búsqueda del hotel:
- Agente de Planner : interpreta la solicitud y decide cómo buscar
- Herramienta de búsqueda de vectores - Busca hoteles similares a los que describe el agente planificador
- Agente de sintetizador : escribe una recomendación útil basada en los resultados de la búsqueda.
Flujo de trabajo de la aplicación
La aplicación procesa una solicitud de búsqueda de hotel en dos pasos:
- Planificación: El flujo de trabajo llama al agente del planificador, que analiza la consulta del usuario (como "hoteles cerca de caminos para correr") y busca en la base de datos los hoteles que coinciden.
- Sintetización: El flujo de trabajo llama al agente del sintetizador, que revisa los resultados de la búsqueda y escribe una recomendación personalizada que explica qué hoteles coinciden mejor con la solicitud.
// 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)
}
Agents
El internal/agents/agents.go archivo de origen implementa los agentes de planificación y síntesis que trabajan juntos para procesar las solicitudes de búsqueda de hoteles.
Agente de Planificador
El agente de planner es el responsable de la toma de decisiones que determina cómo buscar hoteles.
El agente de planner recibe la consulta de lenguaje natural del usuario y la envía a un modelo de IA junto con las herramientas disponibles que puede usar. La inteligencia artificial decide llamar a la herramienta de búsqueda de vectores y proporciona parámetros de búsqueda. A continuación, el agente extrae el nombre de la herramienta y los argumentos de la respuesta de la inteligencia artificial, ejecuta la herramienta de búsqueda y devuelve los hoteles coincidentes. En lugar de codificar la lógica de búsqueda de forma dura, la inteligencia artificial interpreta lo que el usuario quiere y elige cómo buscar, lo que hace que el sistema sea flexible para diferentes tipos de consultas.
// 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
}
Agente de sintetizador
El agente de sintetizador es el escritor que crea recomendaciones útiles.
El agente de sintetizador recibe la consulta de usuario original junto con los resultados de búsqueda del hotel. Envía todo a un modelo de IA con instrucciones para escribir recomendaciones. Devuelve una respuesta de lenguaje natural que compara hoteles y explica las mejores opciones. Este enfoque es importante porque los resultados de búsqueda sin procesar no son fáciles de usar. El sintetizador transforma los registros de base de datos en una recomendación conversacional que explica por qué determinados hoteles coinciden con las necesidades del usuario.
// 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
}
Herramientas del agente
El internal/agents/tools.go archivo de origen define la herramienta de búsqueda vectorial que usa el agente de Planner.
El archivo de herramientas define una herramienta de búsqueda que el agente de IA puede usar para buscar hoteles. Esta herramienta es cómo se conecta el agente a la base de datos. La inteligencia artificial no busca directamente la base de datos. Se pide que use la herramienta de búsqueda y la herramienta ejecuta la búsqueda real.
Definición de la herramienta
El GetToolDefinition método describe la herramienta para el modelo de IA en un formato que comprende. Especifica el nombre de la herramienta, una descripción de lo que hace la herramienta y los parámetros que definen las entradas que necesita la herramienta. Esta definición permite que la inteligencia artificial sepa que la herramienta existe y cómo usarla correctamente.
// 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,
},
},
}
}
Ejecución de herramientas
Cuando la inteligencia artificial llama a la herramienta, se ejecuta el Execute método . Genera una inserción convirtiendo la consulta de texto en un vector numérico mediante el modelo de inserción de Azure OpenAI. A continuación, busca en la base de datos enviando el vector a Azure DocumentDB, que busca hoteles con vectores similares que significan descripciones similares. Por último, da formato a los resultados convirtiendo los registros de la base de datos en texto legible que el agente de sintetizador puede comprender.
// 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
}
¿Por qué usar este patrón?
Separar la herramienta del agente proporciona flexibilidad. La inteligencia artificial decide cuándo buscar y qué buscar, mientras que la herramienta controla cómo buscar. Puede agregar más herramientas sin cambiar la lógica del agente.
Mensajes
El internal/prompts/prompts.go archivo de origen contiene avisos del sistema y definiciones de herramientas para los agentes.
El archivo prompts define las instrucciones y el contexto proporcionados a los modelos de IA para los agentes de planificador y sintetizador. Estas indicaciones guían el comportamiento de la inteligencia artificial y garantizan que comprende su rol en el flujo de trabajo.
La calidad de las respuestas de inteligencia artificial depende en gran medida de las instrucciones claras. Estos avisos establecen límites, definen el formato de salida y centran la inteligencia artificial en el objetivo del usuario de tomar una decisión. Puede personalizar estas indicaciones para cambiar el comportamiento de los agentes sin modificar ningún código.
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.`
Ejecución del ejemplo
Antes de ejecutar el agente, cargue los datos del hotel con inserciones. El
cmd/upload/main.gocomando carga hoteles desde el archivo JSON, genera incrustaciones para cada hotel mediantetext-embedding-3-small, inserta documentos en Azure DocumentDB y crea un índice vectorial.go run cmd/upload/main.goEjecute el agente de recomendación de hotel mediante el
cmd/agent/main.gocomando . El agente llama al agente de planificación, al vector de búsqueda y al agente sintetizador. La salida incluye puntuaciones de similitud y el análisis comparativo del agente sintetizador con recomendaciones.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.
Visualización y administración de datos en Visual Studio Code
Seleccione la extensión DocumentDB en Visual Studio Code para conectarse a la cuenta de Azure DocumentDB.
Vea los datos e índices en la base de datos Hotels.
Limpieza de recursos
Use el comando cleanup para eliminar la base de datos de prueba cuando haya terminado. Ejecute el siguiente comando:
go run cmd/cleanup/main.go
Elimine el grupo de recursos, la cuenta de DocumentDB y el recurso de Azure OpenAI cuando no los necesite para evitar costos adicionales.