Skip to content

GLM-5.2 with LlamaIndex: Tested Setup, RAG and Tools

Independent research — not an official Z.ai publication.Identity and provider disclosure

Five abstract documents flow through LlamaIndex-style index nodes and an OpenAI-compatible gateway into a connected GLM-5.2 model core

Original editorial illustration of the tested data path. It is not a LlamaIndex or Z.ai product screen. The later terminal image is generated from the sanitized Docker results.

GLM-5.2 speaks an OpenAI-compatible chat protocol, but that does not make every class named OpenAI interchangeable. LlamaIndex’s regular wrapper expects a model in its own OpenAI metadata table. When our test asked it for metadata about glm-5.2, it raised ValueError: Unknown model 'glm-5.2' before making a network request.

OpenAILike is the deliberate escape hatch for a third-party compatible API. It also makes three decisions your application must not leave implicit. The tested package defaults to a 3,900-token context, treats the model as a completion model rather than a chat model, and disables function-calling metadata. GLM-5.2 supports a one-million-token context and chat tools, so each value needs to be stated.

This guide provides the exact object, four live acceptance checks, observed latency and usage, an embedding-free document query, and the commercial boundary between Z.ai’s metered API and Coding Plan. The goal is a runnable receipt, not a configuration that merely imports.

  1. Choose the adapter
  2. Separate the Z.ai products
  3. Install pinned packages
  4. Copy the tested object
  5. Verify chat
  6. Verify streaming
  7. Execute a tool
  8. Query one document
  9. Read the receipts
  10. Reconstruct cost
  11. Repair failures
  12. Promote safely
  13. Audit sources

The two wrappers share many constructor fields, but their metadata contracts are different:

LlamaIndex class Intended model family glm-5.2 result in our test
llama_index.llms.openai.OpenAI Known OpenAI model IDs Metadata lookup raised ValueError
llama_index.llms.openai_like.OpenAILike Third-party OpenAI-compatible APIs Accepted explicit GLM metadata and completed four checks

The current OpenAILike source describes it as a thin wrapper for compatible third-party APIs. The same source exposes these defaults:

Defaults observed in version 0.7.2
context_window = 3900
is_chat_model = false
is_function_calling_model = false

Those values are safe generic assumptions, not GLM-5.2 discovery. LlamaIndex does not fetch Z.ai’s model card and repair them for you.

The regular wrapper failure is useful. It prevents an unknown name from silently inheriting incorrect OpenAI metadata. Do not “fix” it by renaming the model to gpt-5.2; that is a different provider’s model. Change the adapter while preserving the real Z.ai model ID.

Separate the metered endpoint from Coding Plan

Section titled “Separate the metered endpoint from Coding Plan”

Z.ai publishes two OpenAI-compatible commercial routes with different usage rules:

Route Base URL LlamaIndex status on July 29
General pay-as-you-go API https://api.z.ai/api/paas/v4 Live tested and passed
GLM Coding Plan https://api.z.ai/api/coding/paas/v4 Not called; LlamaIndex was not listed as a supported tool

The Z.ai quick start says the Coding endpoint is for supported tools and recommends the general API for other use cases. The current Coding Plan tool list includes coding agents such as Claude Code, OpenCode, Cline, Kilo Code and others, but not LlamaIndex.

An endpoint accepting the same JSON shape does not erase that product rule. For a LlamaIndex application, use a general API key and general endpoint unless Z.ai adds the framework to its supported list. If you need a supported coding shell instead, the Coding Plan versus API guide separates subscription, metered and self-hosted decisions.

The successful container used Python 3.13.13 and this package set:

Reproducible package versions
llama-index-core 0.14.23
llama-index-llms-openai 0.7.10
llama-index-llms-openai-like 0.7.2
openai 2.50.0
pydantic 2.13.4

Create a clean environment and install only the integrations used here:

Install the tested LlamaIndex adapter
python -m venv .venv
. .venv/bin/activate
python -m pip install \
"llama-index-core==0.14.23" \
"llama-index-llms-openai==0.7.10" \
"llama-index-llms-openai-like==0.7.2"
python -m pip check

PyPI lists llama-index-llms-openai-like 0.7.2 for Python 3.10 and newer. It was uploaded April 23, 2026. Pinning the integration separately from core matters because LlamaIndex ships provider adapters as independent packages.

Our digest-pinned container mounted the repository read-only and opened no listener or published port. Its default Docker bridge reproduced this host’s known DNS failure, so the trusted outbound-only test used the documented host network exception. That accommodation is part of our reproducibility record, not a recommendation to grant host networking to arbitrary containers.

Keep the key out of the Python file:

Load the metered Z.ai key
export ZAI_API_KEY="your-general-api-key"
test -n "$ZAI_API_KEY" && echo "ZAI_API_KEY is set"

Then set every model-specific metadata field:

glm_llamaindex.py
import os
from llama_index.llms.openai_like import OpenAILike
llm = OpenAILike(
model="glm-5.2",
api_base="https://api.z.ai/api/paas/v4",
api_key=os.environ["ZAI_API_KEY"],
context_window=1_048_576,
is_chat_model=True,
is_function_calling_model=True,
reasoning_effort="none",
temperature=0,
max_tokens=128,
max_retries=0,
timeout=90,
)

The official GLM-5.2 guide supplies the model ID, the OpenAI-compatible base URL, text modality, one-million-token context and 128K maximum output. The max_tokens=128 line above is a small test budget, not the model maximum.

max_retries=0 makes a one-shot acceptance test easier to interpret. A production application can add bounded retries for selected transient errors, but it should record the attempt count. Otherwise one apparent five-second call may hide several upstream requests and charges.

Do not stop after printing llm.metadata. Send a request and assert the application-visible value:

check_chat.py
from llama_index.core.llms import ChatMessage
from glm_llamaindex import llm
response = llm.chat([
ChatMessage(
role="user",
content="Return exactly LLAMAINDEX_CHAT_OK and no other text.",
)
])
text = (response.message.content or "").strip()
assert text == "LLAMAINDEX_CHAT_OK", text
print(text)

The July 29 request returned the exact marker in 3,432 ms. Its usage object reported 25 prompt tokens, 65 completion tokens and 90 total tokens. This is one observed request, not a latency percentile.

The completion count is more important than it first appears. The visible marker is short, yet the provider accounted for 65 completion tokens. Hidden reasoning or provider-side accounting can make visible characters a poor cost proxy. Save sanitized usage fields even when the final text is tiny.

Streaming success requires more than receiving HTTP 200. Accumulate deltas and check the final string:

check_stream.py
from llama_index.core.llms import ChatMessage
from glm_llamaindex import llm
pieces = []
event_count = 0
for event in llm.stream_chat([
ChatMessage(
role="user",
content="Return exactly LLAMAINDEX_STREAM_OK and no other text.",
)
]):
event_count += 1
if event.delta:
pieces.append(event.delta)
text = "".join(pieces).strip()
assert text == "LLAMAINDEX_STREAM_OK", text
print(event_count, text)

Our stream delivered 117 LlamaIndex events and the exact marker in 2,691 ms. The final usage object reported 25 prompt and 120 completion tokens. Event count is adapter behavior, not token count: one token can be surrounded by metadata-only events, and a delta can contain more than one text unit.

For an SSE-level parser and disconnect tests, use the separate GLM-5.2 streaming API guide. LlamaIndex abstracts that wire format; it does not remove the need to handle empty deltas, cancellation, timeouts and partial output.

Marking is_function_calling_model=True advertises a capability to LlamaIndex. A real tool test must still prove the model selected the right function, supplied valid arguments and allowed the application to execute it:

check_tool.py
from llama_index.core.tools import FunctionTool
from glm_llamaindex import llm
calls = []
def lookup_service_port(service: str) -> str:
"""Return the configured TCP port for one fixture service."""
calls.append(service)
return "7442" if service == "Orchid Relay" else "unknown"
tool = FunctionTool.from_defaults(fn=lookup_service_port)
answer = llm.predict_and_call(
[tool],
user_msg=(
"Call lookup_service_port for Orchid Relay. "
"Return only the tool result."
),
error_on_no_tool_call=True,
error_on_tool_error=True,
)
assert calls == ["Orchid Relay"], calls
assert str(answer.response).strip() == "7442", answer.response
print(answer.response)

The function ran once with Orchid Relay and returned 7442 in 5,518 ms. This receipt covers one string parameter and one local function. It does not prove parallel tools, nested schemas, MCP resources, retries after a tool error, or a multi-turn tool loop.

Use the GLM-5.2 tool-calling acceptance loop when an application needs the full request → tool execution → tool result → final answer cycle.

Query one document without an embedding dependency

Section titled “Query one document without an embedding dependency”

A beginner RAG example often fails for an unrelated reason: VectorStoreIndex needs an embedding model, and LlamaIndex may fall back to an OpenAI embedding default if none is configured. GLM-5.2 is the generator in this guide; it is not being presented as an embedding model.

SummaryIndex provides a smaller acceptance path. It stores the document nodes and sends the relevant list through the configured LLM without requiring an embedding service:

check_summary_index.py
from llama_index.core import Document, SummaryIndex
from glm_llamaindex import llm
document = Document(text=(
"Orchid Relay is the internal event bridge. "
"Its production TCP port is 7442. "
"Cedar mode is disabled during maintenance."
))
index = SummaryIndex.from_documents([document])
query_engine = index.as_query_engine(
llm=llm,
response_mode="compact",
)
answer = query_engine.query(
"What production TCP port does Orchid Relay use? "
"Return only the number."
)
assert str(answer).strip() == "7442", answer
assert len(answer.source_nodes) == 1
print(answer)

The query returned 7442 from one document and one source node in 1,224 ms. That proves LlamaIndex orchestration beyond a direct chat call. It is not a vector-retrieval benchmark: SummaryIndex can become expensive as the document set grows because it is designed to synthesize across its nodes.

For production vector RAG, choose and test an explicit embedding model, chunking rule, vector store, metadata filters, top-k value and citation policy. The ColBERT retrieval guide provides a pinned multi-vector example with MaxSim, a tail-truncation negative control, raw index arithmetic and source-preserving context packing. Keep the generator and embedder credentials separate.

Sanitized Docker terminal capture showing the regular OpenAI wrapper failure and passing GLM-5.2 LlamaIndex chat, stream, function tool and SummaryIndex checks

Actual test capture generated from the sanitized result JSON. It contains no API key, Authorization header, cookie, response ID, account detail or model reasoning. It is not a Z.ai billing or LlamaIndex product screen.

Acceptance check Measured time Result Evidence boundary
Exact chat 3.432 s LLAMAINDEX_CHAT_OK One request; 25 in / 65 completion tokens
Stream 2.691 s 117 events; LLAMAINDEX_STREAM_OK One stream; 25 in / 120 completion tokens
Function tool 5.518 s One call; 7442 One typed string argument and local function
SummaryIndex 1.224 s 7442; one source node One tiny document; no embedding model

These timings are not a speed ranking. The prompts and response paths differ, the account and region are one sample, and no warm-up or percentile run was performed. The value is compatibility evidence: four different LlamaIndex surfaces produced the expected application result.

The full sanitized machine-readable record is available as GLM-5.2 LlamaIndex test data. Use it to compare package versions and usage fields before repeating the test.

Budget from provider usage, not visible characters

Section titled “Budget from provider usage, not visible characters”

Z.ai’s pricing page listed GLM-5.2 at $1.40 per million fresh input tokens, $0.26 per million cached input tokens and $4.40 per million output tokens on the test date.

Using fresh-input rates, the two requests with captured usage reconstruct to:

Observed request cost, excluding other two checks
chat = 25 × $1.40 / 1M + 65 × $4.40 / 1M
= $0.000321
stream = 25 × $1.40 / 1M + 120 × $4.40 / 1M
= $0.000563

Those values are arithmetic estimates, not an invoice. The tool and SummaryIndex wrappers did not expose equivalent usage in our sanitized receipt, so we do not invent their cost. Caching eligibility, rounding, account discounts and future prices can also change the bill.

For reusable documents, prompt caching can matter more than the framework choice. The GLM-5.2 prompt-caching guide shows how to distinguish cache eligibility from a confirmed cache hit.

Unknown model appears before the first request

Section titled “Unknown model appears before the first request”

Symptom: ValueError: Unknown model 'glm-5.2'.

Cause: the regular OpenAI wrapper tries to resolve the name against its built-in OpenAI model metadata.

Fix: import OpenAILike from llama_index.llms.openai_like. Keep the real glm-5.2 model ID and set its metadata explicitly.

Symptom: a request targets a legacy completion path, returns a route error, or formats chat messages into one prompt.

Cause: OpenAILike defaults is_chat_model to false.

Fix: set is_chat_model=True and run an exact ChatMessage acceptance call. Do not infer the wire route from the successful constructor.

Symptom: LlamaIndex truncates, repacks or rejects a context far below the model’s documented limit.

Cause: the integration default is 3,900, while GLM-5.2’s official context is 1,048,576.

Fix: set context_window=1_048_576. Then choose a smaller application limit based on latency, cost and retrieval quality; a model maximum is not a target for every query.

Symptom: predict_and_call raises for no tool call or the model answers in plain text.

Cause: function-calling metadata remained false, the tool description was ambiguous, or the requested schema exceeded the tested capability.

Fix: set is_function_calling_model=True, use a typed function with a specific docstring, require a tool in the acceptance prompt, and validate the arguments before execution. Test complex schemas separately.

Symptom: a key that works in one Z.ai product returns unauthorized on the other URL.

Cause: general API and Coding Plan credentials, quota and eligibility are separate. A correct protocol shape does not make the products interchangeable.

Fix: pair the general key with https://api.z.ai/api/paas/v4. Do not route LlamaIndex through Coding Plan unless Z.ai’s current supported-tool policy allows it.

VectorStoreIndex asks for another provider key

Section titled “VectorStoreIndex asks for another provider key”

Symptom: a document example unexpectedly requests OPENAI_API_KEY or fails while constructing embeddings.

Cause: the vector index needs an embedder, and no explicit embedding model was configured.

Fix: configure a deliberate embedding integration or start with the embedding-free SummaryIndex acceptance check above. Do not claim GLM-5.2 performed vector embedding when a different service did.

Streaming finishes with no accepted answer

Section titled “Streaming finishes with no accepted answer”

Symptom: the generator produced events but the joined text is empty, partial or stopped at the output cap.

Cause: metadata-only deltas, a disconnect, a too-small output budget, or reasoning usage consumed the allowance.

Fix: accumulate only non-empty deltas, retain the final usage and finish metadata, enforce a non-empty acceptance condition, and budget output from observed usage. An event count alone is not success.

Promote the adapter with a versioned acceptance test

Section titled “Promote the adapter with a versioned acceptance test”

Before production, turn the four examples into a small CI or release gate:

  1. pin Python and all three LlamaIndex packages;
  2. record the exact API base and model ID without the key;
  3. assert explicit metadata before the first network call;
  4. require an exact chat marker and non-empty streamed marker;
  5. execute one real application tool and validate its arguments;
  6. query a fixture document and require the expected source node;
  7. archive sanitized latency, usage and package versions;
  8. fail closed on a changed endpoint, model error, empty stream or missing tool;
  9. rerun after any LlamaIndex, OpenAI SDK or provider upgrade.

Keep the adapter object local to the component or pass it explicitly to the query engine. A global Settings.llm can be convenient, but it also makes tests depend on import order and can hide which model answered a query.

If multi-provider routing is the real requirement, compare this direct path with the tested GLM-5.2 LangChain route guide or the GLM-5.2 API provider map. Framework choice and commercial route are separate architecture decisions.

Primary sources checked July 29, 2026:

Our reproducible probe is archived under docs/evidence/glm-5-2-llamaindex-2026-07-29/. The test proves one general Z.ai account, one package set and four bounded operations on the stated date. It does not prove every index, embedding model, agent, tool schema, provider account, region or future release.