Skip to content

feat(qairt): opt-in sliding window CLI flag and env var#1160

Open
David Qian (Davidqian123) wants to merge 3 commits into
mainfrom
feat/qairt-sliding-window
Open

feat(qairt): opt-in sliding window CLI flag and env var#1160
David Qian (Davidqian123) wants to merge 3 commits into
mainfrom
feat/qairt-sliding-window

Conversation

@Davidqian123

@Davidqian123 David Qian (Davidqian123) commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Wires the opt-in sliding-window context eviction (geniex-qairt-plugin PR #13) into the public SDK API, the CLI, and every language binding, per qcom-ai-hub/geniex#1197.

  • Bumps the third-party/geniex-qairt submodule pointer.
  • Adds sliding_window / sliding_window_n_keep fields to geniex_GenerationConfig (sdk/include/geniex.h), read directly by QairtLlm::generate(). llama_cpp ignores these fields (it always context-shifts).
  • Adds a --sliding-window flag to geniex infer, passed through the typed config on every Generate() call.
  • Updates every binding's FFI surface in this change (per CONTRIBUTING.md): Go (bindings/go), Python (bindings/python), Android (bindings/android).
  • Documents the flag in cli/README.md and docs/{en,cn}/run/cli/reference.mdx.

Why a typed config field instead of an env var

An earlier version of this PR read an env var (GENIEX_SLIDING_WINDOW=1, set via os.Setenv() from the Go CLI) directly in the plugin. This had a real bug on Windows: os.Setenv() called at runtime from Go is not guaranteed to be visible to a separately-CRT-linked plugin DLL (each DLL's CRT can hold its own environment-block snapshot) -- --sliding-window was silently non-functional unless the env var was also exported in the parent shell before launching the process.

Moving the flag onto geniex_GenerationConfig fixes this (same in-process struct pointer already used for max_tokens/sampler_config) and, per review feedback, makes the feature available to the Python and Android bindings as well, not just the Go CLI.

Acceptance criteria (qcom-ai-hub/geniex#1197)

  • Default behavior is preserved: exceeding the context length without opt-in returns the existing out-of-context error.
  • Passing --sliding-window to the CLI enables ring-buffer eviction.
  • With sliding window enabled, conversations continue past the context limit by evicting the oldest context -- verified end-to-end on real QAIRT hardware (see geniex-qairt-plugin#13), including the case where eviction fires mid-turn and the conversation continues coherently into the next turn.
  • Available to all bindings (Go, Python, Android), not just the CLI.
  • Document the flag in CLI help / docs.

Testing

  • Rebuilt the SDK bridge + qairt plugin (cmake --build) and the Go CLI (bazelisk build //cli --config=windows_arm64) -- clean builds.
  • clang-format, ruff check/ruff format --check on all touched files -- clean.
  • Ran geniex infer qualcomm/Qwen3-4B-Instruct-2507 --sliding-window on real hardware with GENIEX_SLIDING_WINDOW unset from the environment (confirming the old env-var dependency is gone): eviction fires (sliding window: discarding N tokens...), generation continues with no context length exceeded error.

Related

Adds --sliding-window to 'geniex infer' and wires GENIEX_SLIDING_WINDOW
into the qairt plugin's generate(), enabling the ring-buffer context
eviction added in the geniex-qairt-plugin submodule (bumped in this
commit). llama_cpp already has its own always-on context-shift and
ignores the env var.

No FFI/geniex.h struct change: the flag sets GENIEX_SLIDING_WINDOW=1
via os.Setenv() before model creation, read by the plugin on every
generate() call. This keeps the change scoped to sdk/plugins/qairt and
cli/, avoiding a ripple through every binding's FFI surface for what
is currently a QAIRT-only, opt-in feature.

Documents the flag/env var in cli/README.md and
docs/{en,cn}/run/cli/reference.mdx per the issue's acceptance criteria.

Ref: qcom-ai-hub/geniex#1197
Signed-off-by: Davidqian123 <yq2325@nyu.edu>
@mintlify

mintlify Bot commented Jul 7, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
qualcomm-0801e48b 🟢 Ready View Preview Jul 7, 2026, 7:01 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@mengshengwu

Copy link
Copy Markdown
Contributor

It looks good, but I have a few questions:

  1. Why pass this parameter via environment variables? Since it is within gen_cfg, wouldn't adding a new struct field be a better approach?
  2. Only the Go CLI is supported at present. We have two other client sides, Python and Android. Should we implement this feature for them as well? Taking this into consideration, I believe the solution mentioned in the first point is more appropriate.

@Davidqian123

Copy link
Copy Markdown
Contributor Author

Mengsheng Wu (@mengshengwu) Good catch, already Implemented.

GENIEX_SLIDING_WINDOW=1 set via os.Setenv() from the Go CLI at runtime is not guaranteed to be visible to a separately-CRT-linked qairt plugin DLL on Windows (each DLL's CRT can hold its own environment-block snapshot) -- the flag was silently non-functional. Moves sliding_window / sliding_window_n_keep onto geniex_GenerationConfig instead, read directly by QairtLlm::generate() on every call.

Per CONTRIBUTING.md, updates every binding's FFI surface in this change: Go (bindings/go, cli/cmd/geniex/infer.go), Python (bindings/python), and Android (bindings/android). Drops the GENIEX_SLIDING_WINDOW env var and its documentation entirely.

BREAKING CHANGE: geniex_GenerationConfig gains two new trailing fields (sliding_window, sliding_window_n_keep); any code constructing the struct positionally (rather than by field name) needs updating.

Signed-off-by: Davidqian123 <yq2325@nyu.edu>
Signed-off-by: Davidqian123 <yq2325@nyu.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants