Discover Models with the Python SDK and REST API
Explore the OCI Generative AI model catalog, filter models for your application, and inspect model metadata with signed Python SDK and REST requests.
Overview
The Model Discovery API brings model identifiers, capabilities, API compatibility, configuration parameters, and regional availability together. Use this metadata to choose models for a chat assistant, search application, or multimodal workflow before writing an inference request.
Applications can query the catalog to build model-selection interfaces and refresh the available choices. Regional lifecycle information helps you plan upgrades and evaluate reported replacements.
| Metadata | What it reports | How to use it |
|---|---|---|
| Identity and provider | Model identifiers and vendor information. | Find a provider and copy an exact model ID. |
| Tasks and modalities | Model capabilities and supported input-to-output types. | Identify candidates for chat, embeddings, reranking, or multimodal workflows. |
| API compatibility | Inference API capabilities reported for the model. | Select an API that the model supports. |
| Regional availability | Realms, regions, and on-demand or dedicated serving modes. | Find candidates for your deployment location and serving mode. |
| Hosted or proxy access | The model's access classification. | Review the appropriate deployment and data-handling documentation. |
| Parameters | Reported names, types, ranges, defaults, and descriptions. | Build configuration forms and check settings against returned metadata. |
| Lifecycle | Deprecation and retirement dates by region and serving mode, plus replacements when provided. | Identify affected deployments and evaluate migration candidates. |
| Filters | Model ID, realm, region, capability, API capability, serving mode, access type, and lifecycle status. | Build a focused model picker or automate catalog searches. |
Individual models might not populate every field. Discovery helps you select and configure models. It doesn't invoke inference, grant access, or benchmark model quality. Validate a selected model and any suggested replacement with your application's workload.
In this tutorial, you authenticate with an OCI IAM session, query discovery with the Python SDK, send the same request over REST, and try ten practical examples. You also learn how to list models already imported into your compartment.
The operation is ListModelDiscovery. It is distinct from
list_models(), list_imported_models(), and the OpenAI-compatible /models endpoint. Sending a discovery request to Chicago doesn't restrict catalog results to Chicago. Use a region filter to select the catalog region.Before You Begin
To complete this tutorial, you need:
- An OCI account and a compartment where you can inspect models.
ListModelDiscoveryrequiresGENERATIVE_AI_MODEL_INSPECT. See Model Permissions. - For the imported-model examples, permission to inspect imported models in the selected compartment and an existing imported resource to find. See Imported Model Permissions.
- Python 3.11 or later,
uv, and an installed OCI CLI. The commands use a Bash-compatible shell on macOS, Linux, or Windows Subsystem for Linux. - A browser for OCI CLI session authentication and access to the service endpoint. These examples use US Midwest (Chicago) in the OC1 commercial realm.
The examples use OCI IAM request signing with a session token and its private key. An OCI Generative AI API key is a separate credential and doesn't replace the signer used here.
1. Prepare the Environment and Sign In
2. Query Discovery with the Python SDK
This example finds current on-demand chat models in the selected region. It follows pagination and prints model IDs, vendors, and capabilities. The helper functions are reused in later examples.
3. Call the Discovery REST API Directly
A direct request exposes the HTTP method, path, query parameters, and response headers. It calls the same discovery operation as the SDK. The request still requires OCI IAM authorization.
GET /20231130/modelDiscovery?compartmentId=<your-compartment-ocid>4. Prepare the Practical Examples
Choose Filters from the Returned Catalog
Before selecting filters, inspect the values reported for the models in your region:
catalog = fetch(region=[region])
for field in ("capabilities", "api_capability", "model_access", "vendor"):
counts = Counter()
for model in catalog:
values = model.get(field) or []
if isinstance(values, str):
values = [values]
counts.update(set(values))
print(field, dict(sorted(counts.items())))
for field in ("realm", "region", "serving_modes"):
counts = Counter()
for model in catalog:
values = set()
for availability in model.get("availability") or []:
value = availability.get(field)
if isinstance(value, list):
values.update(value)
elif value:
values.add(value)
counts.update(values)
print(field, dict(sorted(counts.items())))Each count is the number of returned model entries associated with a value. A model can contribute to several capability or availability values. Counts reflect the query filters.
| SDK argument | Example or purpose |
|---|---|
region, realm | Lists of region identifiers or realm values. Use values reported by the catalog. |
model_id | One exact model identifier. |
capability | A list such as ["CHAT"], ["TEXT_EMBEDDINGS"], or ["TEXT_RERANK"]. |
api_capability | A list of API identifiers reported by the catalog. |
serving_mode | ["ON_DEMAND"] or ["DEDICATED"]. |
model_access | ["HOSTED"] or ["PROXY"]. |
is_deprecated | False excludes deprecated models. |
is_on_demand_retired, is_dedicated_retired | Use False for the serving mode whose retired models you want to exclude. |
page, limit | Pagination token and requested page size. The example follows opc-next-page until all pages are retrieved. |
Use search_models() for local substring matching after fetching all pages. Search isn't a parameter of ListModelDiscovery. Review the operation reference for the full filter vocabulary.
Ten Practical Python Examples
1. Browse Models Across Both Serving Modes
Filter by your intended deployment region. Omitting serving_mode leaves both on-demand and dedicated models eligible.
catalog = fetch(region=[region])
show(catalog)2. Find Models by Partial Name or Vendor
Search the returned metadata locally. Every space-separated term must match a searchable field. Matching ignores case and punctuation. The service's model_id filter requires an exact identifier.
catalog = fetch(region=[region])
show(search_models(catalog, "grok"))Change the search term to a provider or model family in your results.
3. Find Current On-Demand Chat Models
Exclude deprecated models and models retired for on-demand serving.
show(fetch(
region=[region],
capability=["CHAT"],
serving_mode=["ON_DEMAND"],
is_deprecated=False,
is_on_demand_retired=False,
))4. Find Models for Dedicated Serving
Apply the retirement filter for dedicated serving. This query searches the discovery catalog. To list resources you have imported, use example 8.
show(fetch(
region=[region],
serving_mode=["DEDICATED"],
is_deprecated=False,
is_dedicated_retired=False,
))5. Find Embedding and Reranking Models
Query each capability separately. Discovery uses TEXT_EMBEDDINGS and TEXT_RERANK. Imported-model resources use a different capability vocabulary, including EMBEDDING and RERANK.
for capability in ("TEXT_EMBEDDINGS", "TEXT_RERANK"):
print("\nCapability:", capability)
show(fetch(region=[region], capability=[capability]))6. Find Proxy Models with a Reported API Capability
Read the API identifiers returned by the catalog, then copy a value to filter the proxy models. Review external-call notes and data handling for a selected model.
catalog = fetch(region=[region], model_access=["PROXY"])
api_values = sorted({
api for model in catalog for api in model.get("api_capability") or []
})
print(api_values)
if api_values:
api = input("Enter an API capability from the list: ").strip()
if api in api_values:
show(fetch(
region=[region],
model_access=["PROXY"],
api_capability=[api],
))
else:
print("Enter an exact value from the returned list.")
else:
print("No API capabilities were reported for these results.")7. Inspect Model Parameters and Lifecycle Details
Copy an exact model identifier from your results. Inspect the complete availability entries to keep each region associated with its serving modes, lifecycle dates, and reported replacements.
model_id = input("Enter an exact model ID from your results: ").strip()
for model in fetch(model_id=model_id):
print(model["model_id"])
for field in (
"api_capability", "modality_support", "parameters", "availability"
):
print(field)
print(json.dumps(model.get(field), indent=2, default=str))A field can be empty or unreported. Evaluate any suggested replacement with your application before migrating.
8. Find an Imported Qwen Model
Use source="imported" to query existing imports in your compartment and client region. This example searches for a Qwen 3.6 35B model. It returns a match only if you have imported a matching model and can inspect that resource. See Compatible Qwen 3.6 Models for import compatibility.
imports = fetch(source="imported")
selected = search_models(imports, "qwen 3.6 35B")
show(selected)
for model in selected:
print("Imported resource OCID:", model["id"])
print("Resource state:", model.get("lifecycle_state"))The returned OCID identifies the imported model resource. An ACTIVE resource state doesn't establish that an inference endpoint has been deployed. For deployment steps, see Managing Imported Models.
9. Compare Discovery with Imported Resources
Compare the two sources when a model appears in imported inventory but not in discovery. Discovery results and the resources imported into your compartment answer different questions.
print("Discovery catalog for the selected region:")
show(search_models(fetch(region=[region]), "qwen"))
print("\nImported resources in this compartment and client region:")
show(search_models(fetch(source="imported"), "qwen"))If imported results are empty, check the compartment, client region, and permissions. The imported-model query doesn't scan other compartments or regions.
10. Export Matching Imported Models
Write the full metadata for selected imported resources to a local JSON file.
selected = search_models(fetch(source="imported"), "qwen 3.6 35B")
Path("qwen-imports.json").write_text(
json.dumps({"items": selected}, indent=2, default=str),
encoding="utf-8",
)
print(f"Saved {len(selected)} matching resource(s) to qwen-imports.json")Verify the Result and Troubleshoot
A successful request returns model metadata, or an empty list when no entries match. Review identifiers, capabilities, parameters, and availability before building an inference request.
| Symptom | What to check |
|---|---|
The SDK has no list_model_discovery method. | Upgrade oci in the active virtual environment and repeat the method check. |
| A signed request returns HTTP 401. | Validate or recreate the CLI session, check the selected profile, and restart Python so it reads the new token. |
| The service reports an authorization error. | Check IAM permissions and the compartment OCID. Imported inventory requires permission to inspect imported-model resources. |
| An exact model-ID filter returns no results. | Browse or search locally first, then copy an identifier from the response. Check the region and lifecycle filters. |
| The response includes availability outside the endpoint region. | Set the discovery region filter explicitly and inspect each availability entry. The endpoint region alone doesn't constrain catalog results. |
| An imported model isn't returned. | Check the client's region, compartment, permissions, and resource display name. Use list_imported_models() for imported inventory. |
| Only part of the catalog is returned. | Follow opc-next-page. The Python examples on this page retrieve all pages. |
| The REST request fails while the SDK succeeds. | Use the same profile and compartment. Check the management endpoint, path, and camelCase query names, then review the status and request ID. |
For the generated CLI command, see list-model-discovery. For imported resources, see ListImportedModels. For the metadata fields returned by discovery, see ModelDiscovery.