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.
SDK oficiales para la API de Microsoft Web IQ, disponible en Python y TypeScript. Estos SDK proporcionan a las aplicaciones acceso en tiempo real a la búsqueda web, búsqueda de vídeos, navegación, búsqueda de noticias y búsqueda de imágenes, diseñados para fundamentar las respuestas de los LLM con información precisa y actualizada.
| Python | TypeScript | |
|---|---|---|
| Paquete | pip install webiq |
npm install @microsoft/webiq |
| Tiempo de ejecución | Python 3.11+ | Node.js 22+ |
| Licencia | MIT | MIT |
Installation
Python
pip install webiq
TypeScript
npm install @microsoft/webiq
Quickstart
Guía de Python
import os
from webiq import WebIQClient
from webiq.types import BrowseContentFormat, ContentFormat
with WebIQClient(api_key=os.environ["WEBIQ_API_KEY"]) as client:
# Web search
web = client.web.search(
"Python programming",
max_results=5,
content_format=ContentFormat.passage,
)
for r in web.webResults or []:
print(r.title, r.url)
# Videos search
videos = client.videos.search("machine learning tutorial", max_results=5)
for v in videos.videoResults or []:
print(v.title, v.length)
# Browse a URL
page = client.browse.fetch("https://www.microsoft.com", content_format=BrowseContentFormat.markdown)
print(page.content)
# News search
news = client.news.search("technology", max_results=5)
for item in news.newsResults or []:
print(item.title, "-", item.source)
# Image search
images = client.images.search("golden gate bridge", max_results=5)
for img in images.imageResults or []:
print(img.title, img.url)
Guía de TypeScript
import { WebIQClient, BrowseContentFormat, ContentFormat } from '@microsoft/webiq';
async function main() {
const client = new WebIQClient({ apiKey: process.env.WEBIQ_API_KEY });
// Web search
const web = await client.web.search('TypeScript programming', {
maxResults: 5,
contentFormat: ContentFormat.PASSAGE,
});
for (const r of web.webResults ?? []) console.log(r.title, r.url);
// Videos search
const videos = await client.videos.search('machine learning tutorial');
for (const v of videos.videoResults ?? []) console.log(v.title, v.length);
// Browse a URL
const page = await client.browse.fetch('https://www.microsoft.com', {
contentFormat: BrowseContentFormat.MARKDOWN,
});
console.log(page.content);
// News search
const news = await client.news.search('technology', { maxResults: 5 });
for (const item of news.newsResults ?? []) console.log(item.title, '-', item.source);
// Image search
const images = await client.images.search('golden gate bridge', { maxResults: 5 });
for (const img of images.imageResults ?? []) console.log(img.title, img.url);
await client.close();
}
main().catch(console.error);
Authentication
Clave de API
# Python
import os
from webiq import WebIQClient
client = WebIQClient(api_key=os.environ["WEBIQ_API_KEY"])
// TypeScript
import { WebIQClient } from '@microsoft/webiq';
const client = new WebIQClient({ apiKey: process.env.WEBIQ_API_KEY });
Microsoft Entra ID
Pase o proporcione cualquier identidad de Azure TokenCredential.
# Python — uses `azure-identity`
from azure.identity import DefaultAzureCredential
from webiq import WebIQClient
client = WebIQClient(credential=DefaultAzureCredential())
// TypeScript — uses `@azure/identity`
import { DefaultAzureCredential } from '@azure/identity';
import { WebIQClient } from '@microsoft/webiq';
const client = new WebIQClient({
credential: new DefaultAzureCredential(),
});
Recursos y métodos del SDK
El cliente expone cinco espacios de nombres de recursos: web, videos, browse, newsy images.
Web Search
client.web.search() — Busque en la web y obtenga contenido de la página para la fundamentación.
response = client.web.search(
query="search terms", # Required, 1–1000 chars
max_results=10, # 1–50 (default 10)
language="en", # ISO 639-1 code
region="US", # Country/region code
location="lat:40.7;long:-74.0", # Optional
content_format=ContentFormat.passage, # passage (default) | text | html | markdown (full-page content)
max_length=3000, # Max content chars (default 3000)
)
# response.webResults → list of { title, url, content, lastUpdatedAt, crawledAt, language, isAdult }
Búsqueda de vídeos
client.videos.search() — Busque contenido de vídeo relevante con compatibilidad opcional con listas de reproducción.
response = client.videos.search(
query="search terms", # Required, 1–1000 chars
max_results=30, # 1–30 (default 30)
language="en",
region="US",
enable_playlist=True, # Include playlist results
freshness="month", # week | month | year
)
# response.videoResults → list of { title, url, description, length, viewCount, moments[], thumbnailUrl, ... }
# response.playlists → list of { title, videos[] }
Navegar
client.browse.fetch() : extraiga contenido de cualquier dirección URL. Admite el rastreo en tiempo real y el renderizado de JavaScript.
response = client.browse.fetch(
url="https://www.microsoft.com", # Required
max_length=10000, # Max content chars, 1–500000
live_crawl="fallback", # "none" (cached only, default) | "fallback" (crawl if not cached) | "force" (always crawl, bypass cache)
include_web_links=True, # Include outbound hyperlinks
include_image_links=True, # Include image URLs
render_dynamic_pages=False, # JS rendering (requires live_crawl="fallback")
content_format=BrowseContentFormat.markdown, # text | html | markdown
)
# response → { url, title, content, isAdult, lastUpdatedAt, crawledAt, retryAfter, traceId }
News Search
client.news.search() — Obtenga los artículos de noticias más recientes con los pasajes más relevantes para la consulta.
response = client.news.search(
query="search terms", # Required, 1–1000 chars
max_results=10, # 1–20 (default 10)
language="en",
region="US",
location="lat:40.7;long:-74.0", # Optional
content_format=ContentFormat.passage,
max_length=3000,
)
# response.newsResults → list of { title, url, content, source, lastUpdatedAt, thumbnail, isAdult }
Image Search
client.images.search() : busque imágenes con filtrado por relación de aspecto, tamaño y búsqueda segura.
from webiq.types import ImageAspectRatio, ImageSize, SafeSearch
response = client.images.search(
query="search terms", # Required, 1–1000 chars
max_results=30, # 1–30 (default 30)
language="en",
region="US",
aspect_ratio=ImageAspectRatio.wide, # square | wide | tall
image_size=ImageSize.large, # small | medium | large | extraLarge
safe_search=SafeSearch.strict, # off | strict
watermark_free=True,
)
# response.imageResults → list of { title, url, hostPageUrl, caption, width, height, thumbnailUrl, ... }
Note
Los métodos TypeScript usan los mismos parámetros en camelCase (por ejemplo, maxResults, contentFormat, liveCrawl, aspectRatio). Consulte el inicio rápido de TypeScript anterior para obtener la convención de llamada.
Soporte asíncrono
Soporte para Python
import asyncio
from webiq import WebIQAsyncClient
async def main():
async with WebIQAsyncClient(api_key="your-api-key") as client:
web, news = await asyncio.gather(
client.web.search("async Python"),
client.news.search("programming"),
)
for r in web.webResults or []:
print(r.title)
asyncio.run(main())
Compatibilidad con TypeScript
TypeScript es asincrónico de forma nativa. Utilice Promise.all para simultaneidad:
const [web, news, videos] = await Promise.all([
client.web.search('TypeScript'),
client.news.search('programming'),
client.videos.search('tutorial'),
]);
Configuration
Tiempo de espera y reintento
El cliente acepta timeout y retry como opciones de nivel superior. La configuración por llamada timeout de cada método de recurso invalida el valor predeterminado del cliente. El SDK reintenta automáticamente 408, 500, 502, 503, 504 con retroceso exponencial y variación aleatoria; si el cuerpo de la respuesta incluye un campo retryAfter (por ejemplo "30s"), el SDK espera esa indicación en lugar del retraso de retroceso.
429 y 430nunca se reintentan automáticamente; aparecen inmediatamente como RateLimitError para que la aplicación pueda aplicar su propia directiva de retroceso. Los tiempos de espera del lado cliente tampoco se reintentan (generan APIConnectionError).
# Python
from webiq import WebIQClient, RetryPolicy
client = WebIQClient(
api_key="your-api-key",
timeout=10.0, # seconds (default: 10.0)
retry=RetryPolicy(
max_retries=2, # defaults shown
base_delay_s=0.25,
max_delay_s=4.0,
),
)
# Per-call override
response = client.web.search("query", language="de", region="DE", timeout=30.0)
// TypeScript
import { WebIQClient, RetryPolicy } from '@microsoft/webiq';
const client = new WebIQClient({
apiKey: 'your-api-key',
timeout: 10000, // milliseconds (default: 10000)
retry: new RetryPolicy({
maxRetries: 2, // defaults shown
baseDelaySeconds: 0.25,
maxDelaySeconds: 4.0,
}),
});
Cliente HTTP personalizado (proxy, TLS, ...)
Para la configuración avanzada de HTTP: proxy, TLS personalizado, agrupación de conexiones, etc. El SDK no cierra los clientes propiedad del llamador.
# Python — pass a pre-configured `httpx.Client` via `http_client`
import httpx
from webiq import WebIQClient, WebIQAsyncClient
# sync
http_client = httpx.Client(
base_url="https://api.microsoft.ai/v3",
proxy="http://proxy:8080",
)
client = WebIQClient(api_key="your-api-key", http_client=http_client)
# async
http_client = httpx.AsyncClient(
base_url="https://api.microsoft.ai/v3",
proxy="http://proxy:8080",
)
client = WebIQAsyncClient(api_key="your-api-key", http_client=http_client)
// TypeScript — pass a custom `fetchFn` that wraps the global `fetch`
import { ProxyAgent } from 'undici';
import { WebIQClient } from '@microsoft/webiq';
const proxyAgent = new ProxyAgent('http://my-proxy:8080');
const client = new WebIQClient({
apiKey: 'your-api-key',
// Spread `init` so headers, body, and the SDK's internal `AbortSignal` are preserved.
fetchFn: (url, init) => fetch(url, { ...init, dispatcher: proxyAgent }),
});
Cancelación (TypeScript)
Cada método de recurso typeScript acepta una AbortSignal a través de options.signal. Cuando se anula la señal, se cancela la solicitud en curso, se detiene el reintento y el/la reason de la señal se vuelve a lanzar sin cambios (sin encapsulado APIConnectionError).
// Apply a wall-clock budget that includes retries (the `timeout` option is per attempt only)
const result = await client.web.search('latest news', {
signal: AbortSignal.timeout(5_000),
});
// Combine signals (e.g. an inbound request signal plus a wall-clock cap)
const result2 = await client.web.search('latest news', {
signal: AbortSignal.any([req.signal, AbortSignal.timeout(5_000)]),
});
Gancho de telemetría
Monitoree todas las solicitudes y respuestas para el registro, las métricas o la depuración.
# Python
from webiq import WebIQClient, TelemetryEvent
def on_request(event: TelemetryEvent):
print(f"{event.method} {event.path} → {event.status_code} ({event.elapsed_ms}ms)")
client = WebIQClient(api_key="your-api-key", telemetry_hook=on_request)
// TypeScript
import { WebIQClient, TelemetryEvent } from '@microsoft/webiq';
const client = new WebIQClient({
apiKey: 'your-api-key',
telemetryHook: (event: TelemetryEvent) => {
console.log(`${event.method} ${event.path} → ${event.statusCode} (${event.elapsedMs}ms)`);
},
});
Los TelemetryEvent campos son:
-
Python (snake_case):
method,transport,path,attempt,elapsed_ms,request_id,status_code,trace_id,retry_after,error,error_body -
TypeScript (camelCase):
method,path,statusCode,transport,attempt,requestId,traceId,retryAfter,elapsedMs,error,errorBody
Tratamiento de errores
Ambos SDK proporcionan excepciones con tipo para el control de errores estructurados. Todos los errores heredan de WebIQError.
| Exception | Estado HTTP | Trigger |
|---|---|---|
AuthenticationError |
401 | Clave de API no válida o que falta |
PermissionDeniedError |
403 | Autenticado pero no autorizado para el recurso |
RateLimitError |
429, 430 | Límite de tasa/límite de solicitudes simultáneas superado |
APIStatusError |
400, 404, 500, 503, 504, ... | Todos los demás errores HTTP |
APIConnectionError |
— | Problemas de red, errores de DNS, tiempos de espera |
WebIQError |
— | Clase base para todos los errores del SDK |
PermissionDeniedError y RateLimitError son subclases de APIStatusError, por lo que un controlador más amplio en APIStatusError todavía los captura. El SDK no reintenta automáticamente las respuestas 429 / 430: la sugerencia de retroceso del servidor se muestra en error.retry_after (Python) / error.retryAfter (TypeScript) para que la aplicación actúe.
# Python
from webiq import (
WebIQError,
APIConnectionError,
APIStatusError,
AuthenticationError,
PermissionDeniedError,
RateLimitError,
)
try:
response = client.web.search("test")
except PermissionDeniedError as e:
# 403 — authenticated, but not allowed to call this resource
print(f"Forbidden (HTTP {e.status_code}): {e}")
except AuthenticationError as e:
# 401 — invalid or missing API key
print(f"Auth failed (HTTP {e.status_code}): {e}")
except RateLimitError as e:
# 429 or 430 — rate limit / concurrent-request limit (never auto-retried)
print(f"Rate limited. Retry after: {e.retry_after}")
except APIStatusError as e:
print(f"API error (HTTP {e.status_code}): {e}")
except APIConnectionError as e:
print(f"Connection failed: {e}")
except WebIQError as e:
print(f"SDK error: {e}")
// TypeScript
import {
WebIQError,
APIConnectionError,
APIStatusError,
AuthenticationError,
PermissionDeniedError,
RateLimitError,
} from '@microsoft/webiq';
try {
const results = await client.web.search('test');
} catch (error) {
if (error instanceof PermissionDeniedError) {
// 403 — authenticated, but not allowed to call this resource
console.error(`Forbidden (HTTP ${error.statusCode}):`, error.message);
} else if (error instanceof AuthenticationError) {
// 401 — invalid or missing API key
console.error(`Auth failed (HTTP ${error.statusCode}):`, error.message);
} else if (error instanceof RateLimitError) {
// 429 or 430 — rate limit / concurrent-request limit (never auto-retried)
console.error(`Rate limited. Retry after: ${error.retryAfter}`);
} else if (error instanceof APIStatusError) {
console.error(`API error (HTTP ${error.statusCode}):`, error.message);
} else if (error instanceof APIConnectionError) {
console.error('Connection failed:', error.message);
}
}
Inspeccionando los detalles del error
Todas las APIStatusError instancias (incluidas PermissionDeniedError y RateLimitError) exponen el cuerpo de respuesta de error completo. La mayoría de los problemas de validación de entrada en el SDK de Python (p. ej., max_results fuera de rango, query vacío) se detectan en el lado cliente de Pydantic y generan pydantic.ValidationError antes de enviar cualquier solicitud; el patrón siguiente se aplica cuando el servidor rechaza una solicitud.
browse.fetch es una manera cómoda de desencadenar una: una URL ausente o filtrada aparece como un error estructurado:
# Python
from webiq import WebIQClient
from webiq.errors import APIStatusError
client = WebIQClient(api_key="your-api-key")
try:
response = client.browse.fetch("https://www.not-microsoft.com")
except APIStatusError as e:
print(f"Status: {e.status_code}") # e.g. 404
print(f"Message: {e}") # e.g. "No result is found"
if isinstance(e.body, dict):
print(f"Error code: {e.body.get('errorCode')}") # e.g. "BrowseApiDocNotFound"
print(f"Category: {e.body.get('errorCategory')}") # e.g. "UserError"
print(f"Details: {e.body.get('technicalDetails')}") # e.g. "NotFound"
print(f"Trace ID: {e.body.get('traceId')}")
print(f"Retry after: {e.body.get('retryAfter')}")
// TypeScript
import { WebIQClient, APIStatusError } from '@microsoft/webiq';
async function main() {
const client = new WebIQClient({ apiKey: 'your-api-key' });
try {
await client.browse.fetch('https://www.not-microsoft.com');
} catch (error) {
if (error instanceof APIStatusError) {
console.error(`Status: ${error.statusCode}`); // e.g. 404
console.error(`Message: ${error.message}`); // e.g. "No result is found"
// Full error body from the API response
if (error.body && typeof error.body === 'object') {
const body = error.body as Record<string, unknown>;
console.error(`Error code: ${body.errorCode}`); // e.g. "BrowseApiDocNotFound"
console.error(`Category: ${body.errorCategory}`); // e.g. "UserError"
console.error(`Details: ${body.technicalDetails}`); // e.g. "NotFound"
console.error(`Trace ID: ${body.traceId}`); // for debugging with support
console.error(`Retry after: ${body.retryAfter}`); // for retryable errors
}
}
}
}
main().catch(console.error);
Sugerencias de depuración
-
traceId— cada respuesta incluye un campotraceIdpara la depuración de extremo a extremo. Inclúyala al ponerse en contacto con el soporte técnico. - hook de telemetría — adjunte una función de callback para registrar todos los intentos de solicitud, el código de estado y el tiempo.
-
Cuerpo del error :
APIStatusError.bodycontiene la respuesta completa del servidor, incluidoserrorCode,errorCategory,technicalDetailsytraceId.