Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Kits de développement logiciel (SDK) officiels pour l’API Web IQ Microsoft, disponibles dans Python et TypeScript. Ces SDK donnent à vos applications un accès en temps réel à la recherche web, à la recherche de vidéos, à la navigation, à la recherche d’actualités et à la recherche d’images — conçus pour étayer les réponses des LLM avec des informations précises et à jour.
| Python | TypeScript | |
|---|---|---|
| Paquet | pip install webiq |
npm install @microsoft/webiq |
| Durée | Python 3.11+ | Node.js 22+ |
| License | MIT | MIT |
Installation
Python
pip install webiq
TypeScript
npm install @microsoft/webiq
Quickstart
Guide 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)
TypeScript Guide
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
Clé 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
Transmettez n’importe quel Azure Identity 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(),
});
Ressources et méthodes du Kit de développement logiciel (SDK)
Le client expose cinq espaces de noms de ressources : web, videos, browse, news, et images.
Web Search
client.web.search() — Recherchez sur le Web et obtenez le contenu de la page pour l’ancrage.
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 }
Recherche de vidéos
client.videos.search() : recherchez du contenu vidéo pertinent avec prise en charge facultative de la playlist.
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[] }
Parcourir
client.browse.fetch() — Extraire du contenu de n’importe quelle URL. Prend en charge l’exploration en direct et le rendu 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() — Obtenez les derniers articles d’actualités avec les passages les plus pertinents pour la requête.
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() : recherchez des images avec filtrage par rapport d’aspect, taille et recherche sécurisée.
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
Les méthodes TypeScript utilisent les mêmes paramètres en camelCase (par exemple, maxResults, contentFormat, liveCrawl, aspectRatio). Consultez le guide de démarrage rapide TypeScript ci-dessus pour la convention d’appel.
Prise en charge asynchrone
Prise en charge de 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())
Prise en charge de TypeScript
TypeScript est nativement asynchrone. Utiliser Promise.all pour l’accès concurrentiel :
const [web, news, videos] = await Promise.all([
client.web.search('TypeScript'),
client.news.search('programming'),
client.videos.search('tutorial'),
]);
Configuration
Expiration et réessai
Le client accepte retry et timeout comme options de premier niveau. Le paramètre timeout par appel sur chaque méthode de ressource remplace la valeur par défaut au niveau du client. Le SDK relance automatiquement 408, 500, 502, 504, 503 avec une temporisation exponentielle et de la gigue ; si le corps de la réponse inclut un champ retryAfter (par exemple "30s"), le SDK attend cet indicateur au lieu du délai de temporisation.
429 et 430ne sont jamais retentés automatiquement, ils apparaissent immédiatement comme RateLimitError pour que votre application puisse appliquer sa propre stratégie de temporisation. Les délais d’expiration côté client ne sont pas non plus relancés (ils génèrent l’exception 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,
}),
});
Client HTTP personnalisé (proxy, TLS, ...)
Pour les paramètres HTTP avancés : proxy, TLS personnalisé, regroupement de connexions, etc. Le Kit de développement logiciel (SDK) ne ferme pas les clients appartenant à l’appelant.
# 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 }),
});
Annulation (TypeScript)
Chaque méthode de ressource TypeScript accepte un AbortSignal via options.signal. Lorsque le signal est interrompu, la requête en cours est annulée, les nouvelles tentatives s’arrêtent et le signal APIConnectionError est levé de nouveau tel quel (sans encapsulation dans reason).
// 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)]),
});
Point d’ancrage de télémétrie
Surveillez chaque demande/réponse pour la journalisation, les métriques ou le débogage.
# 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)`);
},
});
Les TelemetryEvent champs sont les suivants :
-
Python (snake_case) :
method,status_code,request_id,attempt,path,transport,trace_id,retry_after,error,elapsed_ms,error_body -
TypeScript (camelCase) :
method,transport,path,attempt,traceId,requestId,retryAfter,statusCode,error,elapsedMs,errorBody
Gestion des erreurs
Les deux kits SDK fournissent des exceptions typées pour la gestion structurée des erreurs. Toutes les erreurs héritent de WebIQError.
| Exception | État HTTP | Déclenchement |
|---|---|---|
AuthenticationError |
401 | Clé API non valide ou manquante |
PermissionDeniedError |
403 | Authentifié mais non autorisé pour la ressource |
RateLimitError |
429, 430 | Limite de taux / limite de requête simultanée dépassée |
APIStatusError |
400, 404, 500, 503, 504, ... | Toutes les autres erreurs HTTP |
APIConnectionError |
— | Problèmes réseau, échecs DNS, délais d’expiration |
WebIQError |
— | Classe de base pour toutes les erreurs du Kit de développement logiciel (SDK) |
PermissionDeniedError et RateLimitError sont les deux sous-classes de APIStatusError, donc un gestionnaire plus large sur APIStatusError les intercepte toujours. Le SDK ne pas réessaie automatiquement 429 / 430 les réponses — l'indication de temporisation du serveur est exposée sur error.retry_after (Python) / error.retryAfter (TypeScript) pour que votre application agisse en conséquence.
# 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);
}
}
Examen des détails de l’erreur
Toutes les instances APIStatusError (y compris PermissionDeniedError et RateLimitError) exposent le corps complet de la réponse d’erreur. La plupart des problèmes de validation d’entrée sur le sdk Python (par exemplemax_results, hors plage, videquery) sont interceptés côté client par Pydantic et déclenchent pydantic.ValidationError avant l’envoi d’une demande ; le schéma ci-dessous s’applique lorsque le serveur rejette une demande.
browse.fetch est un moyen pratique d’en déclencher une : une URL manquante ou filtrée se manifeste sous la forme d’une erreur structurée :
# 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);
Conseils de débogage
-
traceId— chaque réponse inclut un champtraceIdpour le débogage de bout en bout. Incluez-le lors du contact avec le support technique. - Hook de télémétrie : attachez un rappel pour journaliser chaque tentative de requête, code d’état et minutage.
-
Corps d’erreur —
APIStatusError.bodycontient la réponse complète du serveur, y compriserrorCode,errorCategory,technicalDetailsettraceId.