Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,17 @@ out/
/tmp-*/
/AGENTS.override.md
/logs/
/debug/
*.log
*.tmp
/core
/core.*

# Windows serve harness runtime assets (large / third-party; supply locally).
# scripts/windows/win_paths.ps1 resolves these via NINFER_FFMPEG_BIN /
# NINFER_CURL_BIN or a sibling third_party/ dir - they are NOT vendored here.
/third_party/

# Measurement raw corpora & intermediates (large; produced by offline tooling).
# The small final frequency stats under fixtures/ranking/ ARE tracked; the rest is ignored.
tools/freq_corpus/fixtures/*
Expand Down
15 changes: 15 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,21 @@ routing map, not a mandatory reading list:
Do not survey unrelated references for completeness. Read additional documents only when they
govern a live decision in the current task.

## Build (Windows)

The agent terminal is **not** a VS Developer prompt, so `INCLUDE`/`LIB` are unset and a bare
`cmake --build` fails with `fatal error C1083: Cannot open include file: 'chrono'`. Initialize the
MSVC x64 environment in the same command as the build:

```powershell
cmd /c '"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat" && cmake --build ninfer\build --target ninfer-serve'
```

Run from the workspace root (the parent of `ninfer/`). `ninfer/build` is already configured
(Ninja, Release, CUDA 13.3); only re-run `cmake -S ninfer -B ninfer/build -G Ninja
-DCMAKE_BUILD_TYPE=Release` if the CMake configuration itself changes. The server binary lands at
`ninfer/build/apps/ninfer-serve.exe`.

## Product and ownership boundaries

These boundaries govern ordinary implementation work. An explicit architecture task may revise
Expand Down
71 changes: 66 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,28 @@ if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 13.1)
"${CMAKE_CUDA_COMPILER_VERSION}")
endif()

# CUDA 13's CCCL headers require MSVC's standard-conforming preprocessor.
if(MSVC)
add_compile_options($<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/Zc:preprocessor>)
# windows.h defines max/min as macros that break std::max/std::min.
add_compile_definitions(NOMINMAX)
endif()

# Media (vision) decode and acquisition need FFMPEG and libcurl. Those are not
# part of the default Windows toolchain, so the text-only build
# (NINFER_BUILD_MEDIA=OFF) compiles API-compatible stubs instead and rejects
# vision requests at runtime.
if(WIN32)
set(NINFER_MEDIA_DEFAULT OFF)
else()
set(NINFER_MEDIA_DEFAULT ON)
endif()
option(NINFER_BUILD_MEDIA "Build FFMPEG/libcurl media decode and acquisition"
${NINFER_MEDIA_DEFAULT})

# ninfer_serve and prompt_input link ninfer_media_acquire unconditionally, so
# the target must exist whenever apps/tests build; NINFER_BUILD_MEDIA only
# selects the real (libcurl) vs stub implementation.
set(NINFER_BUILD_MEDIA_ACQUIRE OFF)
if(NINFER_BUILD_APPS OR BUILD_TESTING)
set(NINFER_BUILD_MEDIA_ACQUIRE ON)
Expand All @@ -55,11 +77,50 @@ if(NINFER_BUILD_APPS OR BUILD_TESTING)
endif()

find_package(CUDAToolkit REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
libavformat>=60 libavcodec>=60 libavutil>=58 libswscale>=7)
if(NINFER_BUILD_MEDIA_ACQUIRE)
pkg_check_modules(LIBCURL REQUIRED IMPORTED_TARGET libcurl>=7.85)
if(NINFER_BUILD_MEDIA)
if(WIN32)
# Windows: use find_path/find_library for FFMPEG + libcurl (no pkg-config)
set(FFMPEG_ROOT "${PROJECT_SOURCE_DIR}/../third_party/ffmpeg/ffmpeg-master-latest-win64-gpl-shared")
set(CURL_ROOT "${PROJECT_SOURCE_DIR}/../third_party/curl-inst")

find_path(FFMPEG_INCLUDE_DIR NAMES libavformat/avformat.h PATHS "${FFMPEG_ROOT}/include" NO_DEFAULT_PATH)
find_library(AVFORMAT_LIBRARY NAMES avformat.lib PATHS "${FFMPEG_ROOT}/lib" NO_DEFAULT_PATH)
find_library(AVCODEC_LIBRARY NAMES avcodec.lib PATHS "${FFMPEG_ROOT}/lib" NO_DEFAULT_PATH)
find_library(AVUTIL_LIBRARY NAMES avutil.lib PATHS "${FFMPEG_ROOT}/lib" NO_DEFAULT_PATH)
find_library(SWSCALE_LIBRARY NAMES swscale.lib PATHS "${FFMPEG_ROOT}/lib" NO_DEFAULT_PATH)

if(NOT FFMPEG_INCLUDE_DIR OR NOT AVFORMAT_LIBRARY OR NOT AVCODEC_LIBRARY OR NOT AVUTIL_LIBRARY OR NOT SWSCALE_LIBRARY)
message(FATAL_ERROR "FFMPEG libraries not found. Install BtbN ffmpeg-win64-gpl-shared into third_party/ffmpeg/")
endif()

add_library(PkgConfig::FFMPEG INTERFACE IMPORTED)
set_target_properties(PkgConfig::FFMPEG PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES "${AVFORMAT_LIBRARY};${AVCODEC_LIBRARY};${AVUTIL_LIBRARY};${SWSCALE_LIBRARY}"
)

if(NINFER_BUILD_MEDIA_ACQUIRE)
find_path(CURL_INCLUDE_DIR NAMES curl/curl.h PATHS "${CURL_ROOT}/include" NO_DEFAULT_PATH)
find_library(CURL_LIBRARY NAMES libcurl_imp.lib PATHS "${CURL_ROOT}/lib" NO_DEFAULT_PATH)

if(NOT CURL_INCLUDE_DIR OR NOT CURL_LIBRARY)
message(FATAL_ERROR "libcurl not found. Build curl with MSVC into third_party/curl-inst/")
endif()

add_library(PkgConfig::LIBCURL INTERFACE IMPORTED)
set_target_properties(PkgConfig::LIBCURL PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES "${CURL_LIBRARY}"
)
endif()
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
libavformat>=60 libavcodec>=60 libavutil>=58 libswscale>=7)
if(NINFER_BUILD_MEDIA_ACQUIRE)
pkg_check_modules(LIBCURL REQUIRED IMPORTED_TARGET libcurl>=7.85)
endif()
endif()
endif()
find_package(Threads REQUIRED)

Expand Down
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,49 @@

> Selected checkpoints. Maximum single-GPU inference performance.

> **Windows port fork.** This is a fork of [Neroued/ninfer](https://github.com/Neroued/ninfer),
> ported to build and run **natively on Windows** (MSVC + CUDA, no WSL) for a **single NVIDIA GeForce
> RTX 5090** (`sm_120a`). The upstream sections below describe the Linux build; Windows users should
> follow **[Windows build & run](#windows-build--run)** first. The port adds a native `ReadFile`
> artifact path, a TMA tensormap-proxy fix for the NVFP4 kernels, and a PowerShell serve harness under
> [`scripts/windows/`](scripts/windows/).

## Windows build & run

The engine builds with the MSVC x64 developer environment plus CUDA Toolkit 13.3, CMake 3.28+, and
Ninja. The agent/CI shell is **not** a Visual Studio developer prompt, so `INCLUDE`/`LIB` are unset
and a bare `cmake --build` fails with `C1083: cannot open include file: 'chrono'`. Initialize MSVC in
the *same* command as the build (adjust the `vcvars64.bat` path to your Visual Studio install):

```powershell
cmd /c '"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat" `
&& cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release `
&& cmake --build build --target ninfer-serve -j'
```

The server binary lands at `build/apps/ninfer-serve.exe`.

### Serve harness (`scripts/windows/`)

PowerShell launchers that resolve the build tree, model artifacts, and third-party DLLs portably
(env override → repo layout → workspace-root fallback; see `scripts/windows/win_paths.ps1`):

| Script | Purpose |
|---|---|
| `serve.ps1 <1..4>` | Launch the server. Model 1 = NVFP4 text-only, 2 = groupwise-int + vision, 3 = heretic + vision, 4 = NVFP4 + vision. |
| `watch-serve.ps1` | Heartbeat supervisor: relaunches on crash/health-fail with bounded backoff. |
| `swap-serve.ps1` | A/B swap between the current build and a candidate build, with auto-rollback. |
| `win_repro_test.ps1` / `win_parity_capture.ps1` | One-shot smoke / cross-platform parity capture. |

```powershell
.\scripts\windows\serve.ps1 1 # NVFP4, text-only, 256K context + MTP3
```

Two Windows gotchas: (1) the server appends its request JSONL to `debug/ninfer-serve-<date>.jsonl`
and **fails to start if `debug/` does not exist** — create it first; (2) vision builds import FFmpeg
and libcurl DLLs at load — supply them and point `NINFER_FFMPEG_BIN` / `NINFER_CURL_BIN` at their
`bin` dirs (they are not vendored; see `.gitignore`).

NInfer is a from-scratch C++/CUDA inference engine for explicitly registered Qwen checkpoints on a
single NVIDIA GeForce RTX 5090. It runs text, image, and video prompts through a local CLI or
OpenAI-/Anthropic-compatible HTTP APIs. The runtime is deliberately specialized: one GPU, one
Expand All @@ -22,7 +65,8 @@ tokenizer, chat template, and media frontend resources required by its registere

## Quick start

NInfer requires 64-bit Linux, an NVIDIA GeForce RTX 5090, CUDA Toolkit 13.1 or newer, CMake 3.28 or
NInfer requires 64-bit Linux (or, in this fork, native Windows via MSVC + CUDA — see
[Windows build & run](#windows-build--run)), an NVIDIA GeForce RTX 5090, CUDA Toolkit 13.1 or newer, CMake 3.28 or
newer, a C++20 host compiler, Ninja, `pkg-config`, FFmpeg development libraries
(`libavformat >= 60`, `libavcodec >= 60`, `libavutil >= 58`, and `libswscale >= 7`), and
`libcurl >= 7.85`. The build rejects CUDA architectures other than `sm_120a`.
Expand Down
1 change: 1 addition & 0 deletions scripts/windows/payloads/parity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"temperature":0,"messages":[{"content":"Read the following document carefully, then answer the question at the end. Paragraph 0. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 1. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 2. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 3. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 4. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 5. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 6. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 7. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 8. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 9. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 10. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 11. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. Paragraph 12. This is a filler paragraph about the history of computing. Early computers were room-sized machines built from vacuum tubes and punch cards. Over the decades, transistors replaced tubes, integrated circuits packed thousands of transistors onto a single chip, and microprocessors brought computing to the desktop. Each generation of hardware enabled new software, from simple calculators to the complex distributed systems we rely on today. \n\nWhat is the last paragraph number mentioned in the document above? Reply with only the number.","role":"user"}],"model":"256k","seed":42,"max_tokens":64}
Loading