|
| 1 | +# Copilot Instructions for OpenVINO Model Server (OVMS) |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +OpenVINO Model Server (OVMS) is a high-performance inference serving platform built on top of **OpenVINO** and **OpenVINO GenAI**. The codebase is primarily **C++** with **Bazel** as the build system. Supporting infrastructure uses **Makefiles**, **Dockerfiles** (Ubuntu & Red Hat), and **batch files** (Windows). |
| 6 | + |
| 7 | +**Performance is a top priority** — both **throughput** and **latency** are critical. Code changes should be evaluated for their performance impact. Avoid unnecessary copies, allocations, and blocking operations on the hot path. |
| 8 | + |
| 9 | +## Repository Structure |
| 10 | + |
| 11 | +- `src/` — Main C++ source code (server, gRPC/REST handlers, model management, pipelines, mediapipe, LLM, C API) |
| 12 | +- `src/test/` — C++ unit tests (gtest-based); this is where most developer tests live |
| 13 | +- `src/python/` — Python bindings and related code |
| 14 | +- `demos/` — End-user demo applications |
| 15 | +- `client/` — Client libraries (C++, Python, Go, Java) |
| 16 | +- `docs/` — Documentation |
| 17 | +- `third_party/` — Third-party dependency definitions for Bazel |
| 18 | +- `Dockerfile.ubuntu` / `Dockerfile.redhat` — Multi-stage Dockerfiles for Linux builds |
| 19 | +- `Makefile` — Orchestrates Docker-based builds and test runs |
| 20 | +- `*.bat` files — Windows build and setup scripts |
| 21 | + |
| 22 | +## Build System |
| 23 | + |
| 24 | +### Bazel (primary build tool) |
| 25 | + |
| 26 | +Building and testing is done **inside a Docker `-build` container** with the repository mounted. Developers do not run Bazel on the host directly. |
| 27 | + |
| 28 | +**Important:** Building the `-build` image from scratch is time-expensive, but may be required if dependencies or the build environment change. Before building a new one, check if one already exists: |
| 29 | +```bash |
| 30 | +docker images | grep -build |
| 31 | +``` |
| 32 | +If a `-build` image exists, start a container from it with the repository mounted: |
| 33 | +```bash |
| 34 | +docker run -it -v $(pwd):/ovms \ |
| 35 | + -e http_proxy=$http_proxy -e https_proxy=$https_proxy -e no_proxy=$no_proxy \ |
| 36 | + <image_name> bash |
| 37 | +``` |
| 38 | +If a container from a previous session is still available (`docker ps -a`), reuse it with `docker start -i <container>` or `docker exec -it <container> bash`. |
| 39 | + |
| 40 | +**Key Bazel targets:** |
| 41 | + |
| 42 | +| Target | Description | |
| 43 | +|--------|-------------| |
| 44 | +| `//src:ovms` | Main OVMS server binary | |
| 45 | +| `//src:ovms_test` | C++ unit tests (gtest) | |
| 46 | +| `//src:ovms_shared` | C API shared library (`libovms_shared.so`) | |
| 47 | +| `//src:capi_benchmark` | C API benchmark application | |
| 48 | +| `//src:capi_cpp_example` | C API C++ example | |
| 49 | +| `//src:release_custom_nodes` | Custom node plugins | |
| 50 | +| `//src/python/binding:test_python_binding` | Python binding tests | |
| 51 | + |
| 52 | +**Build the server:** |
| 53 | +```bash |
| 54 | +bazel build //src:ovms |
| 55 | +``` |
| 56 | + |
| 57 | +**Build and run unit tests:** |
| 58 | +```bash |
| 59 | +bazel build //src:ovms_test |
| 60 | +bazel test --test_summary=detailed --test_output=streamed //src:ovms_test |
| 61 | +``` |
| 62 | + |
| 63 | +### Red Hat builds — distro flag |
| 64 | + |
| 65 | +For Red Hat (UBI9) builds, the `--//:distro=redhat` flag must be passed to all Bazel commands: |
| 66 | +```bash |
| 67 | +bazel build --//:distro=redhat //src:ovms |
| 68 | +bazel test --//:distro=redhat //src:ovms_test |
| 69 | +``` |
| 70 | + |
| 71 | +The default distro is `ubuntu`. Inside the `-build` container, the distro is auto-detected from `/etc/redhat-release`. |
| 72 | + |
| 73 | +### Makefile (Docker-based workflow) |
| 74 | + |
| 75 | +The Makefile orchestrates full Docker-based builds. Key targets: |
| 76 | + |
| 77 | +| Target | Description | |
| 78 | +|--------|-------------| |
| 79 | +| `make docker_build` | Full build: builder image → package → release images (default target) | |
| 80 | +| `make ovms_builder_image` | Build the `-build` Docker image (compilation container) | |
| 81 | +| `make targz_package` | Extract `.tar.gz` release package | |
| 82 | +| `make ovms_release_images` | Build CPU and GPU release Docker images | |
| 83 | +| `make run_unit_tests` | Run C++ unit tests in the `-build` container | |
| 84 | +| `make test_functional` | Run Python functional tests | |
| 85 | +| `make style` / `make cpplint` | Code style checks | |
| 86 | + |
| 87 | +**Red Hat build via Make:** |
| 88 | +```bash |
| 89 | +make docker_build BASE_OS=redhat |
| 90 | +``` |
| 91 | + |
| 92 | +**Supported `BASE_OS` values:** `ubuntu24`, `ubuntu22`, `redhat` |
| 93 | + |
| 94 | +### Dockerfile stages |
| 95 | + |
| 96 | +Both `Dockerfile.ubuntu` and `Dockerfile.redhat` use multi-stage builds: |
| 97 | + |
| 98 | +| Stage | Purpose | |
| 99 | +|-------|---------| |
| 100 | +| `base_build` | System dependencies, Boost, Azure SDK, OpenCV | |
| 101 | +| `build` | Bazel + OpenVINO setup, compiles OVMS (the `-build` container) | |
| 102 | +| `capi-build` | Builds C API shared library and examples | |
| 103 | +| `pkg` | Packages everything into a `.tar.gz` | |
| 104 | +| `release` | Minimal runtime image with entrypoint | |
| 105 | + |
| 106 | +### Windows builds |
| 107 | + |
| 108 | +Windows builds use batch files in the repository root: |
| 109 | +- `windows_install_build_dependencies.bat` — Install build dependencies (MSVC 2022 Build Tools, etc.) |
| 110 | +- `windows_build.bat` — Main build script |
| 111 | +- `windows_test.bat` — Run tests |
| 112 | + |
| 113 | +Windows-specific Bazel config: `--config=win_mp_on_py_off` (or `--config=win_mp_on_py_on` for Python support). |
| 114 | + |
| 115 | +## Testing |
| 116 | + |
| 117 | +### Test setup |
| 118 | + |
| 119 | +Before running tests, test models must be prepared: |
| 120 | +```bash |
| 121 | +make prepare_models |
| 122 | +``` |
| 123 | + |
| 124 | +Models are exported using the `demos/common/export_models/export_model.py` script (used internally by the test setup). |
| 125 | + |
| 126 | +If LLM test models change (e.g., new model version, openvino version change or config update), you may need to remove and regenerate the LLM test data: |
| 127 | +```bash |
| 128 | +rm -rf src/test/llm_testing |
| 129 | +make prepare_models |
| 130 | +``` |
| 131 | + |
| 132 | +### Running tests |
| 133 | + |
| 134 | +Running the full `//src:ovms_test` suite is **time-consuming**. During development, always run only the test fixtures relevant to your changes first using `--test_filter`: |
| 135 | +```bash |
| 136 | +bazel test --test_summary=detailed --test_output=streamed --test_filter="SuiteName.TestName" //src:ovms_test |
| 137 | +``` |
| 138 | +Run the full test suite only after the targeted tests pass. |
| 139 | + |
| 140 | +### Test structure |
| 141 | + |
| 142 | +- **Unit tests** are in `src/test/` — gtest-based C++ tests covering all server components |
| 143 | +- Test files follow the `*_test.cpp` naming convention |
| 144 | +- Test utilities: `test_utils.hpp`, `light_test_utils.hpp`, `c_api_test_utils.hpp` |
| 145 | +- Test models are stored in `src/test/` subdirectories (e.g., `dummy/`, `passthrough/`, `summator/`) |
| 146 | +- Specialized test areas: `src/test/llm/`, `src/test/mediapipe/`, `src/test/python/`, `src/test/embeddings/` |
| 147 | + |
| 148 | +## Code Style |
| 149 | + |
| 150 | +- C++ style is enforced via `cpplint` and `clang-format` |
| 151 | +- Run `make style` to check formatting |
| 152 | +- Apache 2.0 license headers are required on all source files |
| 153 | + |
| 154 | +## Expertise Areas |
| 155 | + |
| 156 | +1. **OpenVINO Expertise:** |
| 157 | + - Proficient with OpenVINO core libraries and `ov::genai` components |
| 158 | + - Familiar with OpenVINO performance optimization techniques |
| 159 | +2. **C++ Proficiency:** |
| 160 | + - Strong C++17 skills |
| 161 | + - Familiar with best practices in memory management, concurrency, and template programming |
| 162 | +3. **Serving Infrastructure:** |
| 163 | + - gRPC and REST API handler design |
| 164 | + - Model management, pipeline orchestration, and MediaPipe integration |
| 165 | + - C API (`libovms_shared.so`) surface and bindings |
| 166 | +4. **Build System Awareness:** |
| 167 | + - Bazel build configuration and dependency management |
| 168 | + - Minimizing C++ build times: forward declarations, include-what-you-use, avoiding transitive header leakage |
| 169 | + - Understanding of Bazel targets, build flags (`--//:distro`), and multi-stage Docker builds |
| 170 | + |
| 171 | +## Code Review Instructions for PRs |
| 172 | + |
| 173 | +When analyzing a Pull Request, follow this protocol: |
| 174 | + |
| 175 | +1. Follow **C++ Core Guidelines** strictly. Include references in review comments. |
| 176 | +2. Check for **hidden performance costs**: avoid `dynamic_cast` on the hot path; suggest `static_cast` or redesign if the type is known. |
| 177 | +3. **Avoid copies**: ensure large data structures (tensors, buffers) are passed by reference or moved, not copied. |
| 178 | +4. **Python bindings**: if C++ APIs change, check whether the corresponding pybind11 wrappers in `src/python/` need updates. |
| 179 | +5. **Assertions**: use project assertion macros for checks instead of `if` + `throw` where applicable. |
| 180 | +6. **Documentation**: ensure new public APIs have docstrings in C++ headers and Python bindings; update `docs/` as needed. |
| 181 | +7. **Test coverage**: ensure that new features or changes have corresponding tests in `src/test/`. |
| 182 | +8. **Formatting & safety:** |
| 183 | + - No `using namespace std; using namespace ov;`. Prefer explicit using with specific symbols if needed, for readability. |
| 184 | + - No `auto` for primitive types where it obscures readability. |
| 185 | + - Use `const` and `constexpr` wherever possible. |
| 186 | +9. Pass non-fundamental values by `const` reference wherever possible. |
| 187 | +10. Prefer member initializer lists over direct assignments in constructor bodies. |
| 188 | +11. Verify that the result of every newly introduced function is used in at least one call site (except `void` functions). |
| 189 | +12. Use descriptive function and variable names. Avoid duplicate code — extract common functionality into reusable utilities. |
| 190 | +13. When initial container values are known upfront, prefer initializer-list / brace-initialization over constructing an empty container and inserting. |
| 191 | +14. Unused functions and includes are not allowed. Build times are already long — do not add unnecessary `#include` directives. Prefer forward declarations where possible and follow the include-what-you-use principle. |
| 192 | + - **Forward-declare in headers, include in `.cpp`**: if a header only uses pointers or references to a type, use a forward declaration (`class Foo;`) instead of `#include "foo.hpp"`. Move the full `#include` to the `.cpp` file where the type is actually used. |
| 193 | + - **Keep headers self-contained but minimal**: each header must compile on its own, but should not pull in transitive dependencies that callers don't need. |
| 194 | + - **Prefer opaque types / Pimpl**: for complex implementation details, consider the Pimpl idiom to keep implementation-only types out of the public header entirely. |
| 195 | + - **Never include a header solely for a typedef or enum**: forward-declare the enum (`enum class Foo;` in C++17) or relocate the typedef to a lightweight `fwd.hpp`-style header. |
| 196 | +15. Be mindful when accepting `const T&` in constructors or functions that store the reference: verify that the referenced object's lifetime outlaps the usage to avoid dangling references. |
0 commit comments