Skip to content

Conversation

ajcasagrande
Copy link
Contributor

@ajcasagrande ajcasagrande commented Sep 26, 2025

Format is slightly different from GenAI-Perf. Looking for feedback on this:

  • payload was renamed to payloads
  • Each item in payloads represents a turn in a conversation/session
  • session_id field was added, so it can be used for correlation purposes later. this will allow us to link requests to payloads for use in the future

2 Turns Data:
image

CLI Command:

aiperf profile -m "openai/gpt-oss-20b" --isl 200 --url "localhost:9000" --streaming --num-requests 100 --osl 100 --random-seed 0 --extra-inputs "temperature:0" --session-turns-mean 2 --num-dataset-entries 10


Multi-Modal Data:
image

CLI Command:

aiperf profile -m "openai/gpt-oss-20b" --isl 200 --url "localhost:9000" --streaming --num-requests 1 --osl 100 --random-seed 0 --extra-inputs "temperature:0" --image-width-mean 100 --image-height-mean 100 --session-turns-mean 2

Summary by CodeRabbit

  • New Features
    • Generates inputs.json with structured session payloads during profile configuration.
    • Exposes new data models for inputs and session payloads for external use.
  • Refactor
    • Standardized default file names and locations for logs and export artifacts.
  • Chores
    • Added a default graceful shutdown timeout.
    • Added license headers to test modules.
  • Tests
    • Added comprehensive tests/fixtures for inputs.json generation and error cases; updated exporter tests to use standardized defaults.

Copy link

coderabbitai bot commented Sep 26, 2025

Walkthrough

Adds output-related defaults and a graceful shutdown constant; updates logging and exporters to use the new defaults; introduces InputsFile and SessionPayloads models and re-exports them; extends DatasetManager to generate inputs.json during profile configuration; and adds/updates tests and fixtures.

Changes

Cohort / File(s) Summary
Config defaults
aiperf/common/config/config_defaults.py
Added OutputDefaults attributes: LOG_FOLDER, LOG_FILE, INPUTS_JSON_FILE, PROFILE_EXPORT_AIPERF_CSV_FILE, PROFILE_EXPORT_AIPERF_JSON_FILE.
Core constants
aiperf/common/constants.py
Added GRACEFUL_SHUTDOWN_TIMEOUT = 5.0 with docstring.
Logging & controller paths
aiperf/common/logging.py, aiperf/controller/system_controller.py
Replaced hard-coded "logs"/"aiperf.log" with OutputDefaults.LOG_FOLDER / OutputDefaults.LOG_FILE; added imports.
Models and exports
aiperf/common/models/dataset_models.py, aiperf/common/models/__init__.py
Added SessionPayloads and InputsFile models; re-exported via __all__.
Dataset manager: inputs.json generation
aiperf/dataset/dataset_manager.py
Added _generate_input_payloads and _generate_inputs_json_file; _profile_configure_command now calls _generate_inputs_json_file; added imports and typings.
Exporters use defaults
aiperf/exporters/csv_exporter.py, aiperf/exporters/json_exporter.py
Replaced hard-coded export filenames with OutputDefaults.PROFILE_EXPORT_AIPERF_CSV_FILE / OutputDefaults.PROFILE_EXPORT_AIPERF_JSON_FILE.
Exporter tests updated
tests/data_exporters/test_csv_exporter.py, tests/data_exporters/test_json_exporter.py
Tests updated to reference OutputDefaults constants instead of literal filenames.
Dataset test scaffolding
tests/dataset/conftest.py, tests/dataset/__init__.py
Added fixtures for user_config, sample conversations, DatasetManager instances, and file-write capture; added SPDX header to __init__.py.
Dataset manager inputs.json tests
tests/dataset/test_dataset_manager_inputs_json.py
Added comprehensive tests covering inputs.json generation, payload structure, ordering, error cases, logging, and Pydantic model compatibility.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant DatasetManager
  participant RequestConverterFactory
  participant RequestConverter
  participant Conversations
  participant FS

  User->>DatasetManager: _profile_configure_command()
  activate DatasetManager
  DatasetManager->>DatasetManager: _configure_dataset(...)
  DatasetManager->>DatasetManager: _generate_inputs_json_file()
  DatasetManager->>RequestConverterFactory: get(model_endpoint)
  RequestConverterFactory-->>DatasetManager: RequestConverter
  DatasetManager->>Conversations: iterate sessions & turns
  loop per session
    DatasetManager->>RequestConverter: format_payload(turn)
    RequestConverter-->>DatasetManager: payload dict
    DatasetManager->>DatasetManager: accumulate SessionPayloads
  end
  DatasetManager->>FS: write OutputDefaults.INPUTS_JSON_FILE (InputsFile JSON)
  FS-->>DatasetManager: success / error
  DatasetManager-->>User: done
  deactivate DatasetManager
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Poem

I thump where defaults gently land,
Logs and JSON tidy at hand.
Sessions bundled, payloads neat,
Files hop home — a rabbit feat.
Small changes, snug within the code. 🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the primary feature added—the generation of an inputs.json file to enhance dataset traceability. It directly reflects the key change in the pull request using clear and concise language without extraneous detail. This makes it easy for reviewers to understand the main intent when scanning the repository history.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ajc/inputs.json

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 454462f and e9d5571.

📒 Files selected for processing (1)
  • aiperf/dataset/dataset_manager.py (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
aiperf/dataset/dataset_manager.py (5)
aiperf/clients/model_endpoint_info.py (4)
  • ModelEndpointInfo (117-155)
  • from_user_config (47-54)
  • from_user_config (103-114)
  • from_user_config (130-135)
aiperf/common/config/config_defaults.py (1)
  • OutputDefaults (114-121)
aiperf/common/factories.py (16)
  • RequestConverterFactory (475-480)
  • create_instance (183-209)
  • create_instance (284-315)
  • create_instance (354-364)
  • create_instance (375-381)
  • create_instance (390-395)
  • create_instance (406-414)
  • create_instance (425-430)
  • create_instance (439-447)
  • create_instance (456-464)
  • create_instance (491-499)
  • create_instance (536-550)
  • create_instance (561-573)
  • create_instance (584-596)
  • create_instance (607-611)
  • create_instance (620-628)
aiperf/common/models/dataset_models.py (3)
  • Conversation (73-83)
  • InputsFile (98-105)
  • SessionPayloads (86-95)
aiperf/common/protocols.py (3)
  • RequestConverterProtocol (416-423)
  • format_payload (419-423)
  • info (69-69)
🪛 Ruff (0.13.1)
aiperf/dataset/dataset_manager.py

162-162: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (2)
aiperf/dataset/dataset_manager.py (2)

99-101: inputs.json generation wired into profile configure ✅

Hooking _generate_inputs_json_file() directly into the configure flow ensures the artifact is produced immediately after the dataset is ready. Nice integration.


143-158: Artifact directory creation prevents FileNotFoundError

Great follow-up on the earlier feedback—creating the parent directory before opening the file guarantees aiofiles.open won’t trip over a missing path and keeps traceability intact.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the feat label Sep 26, 2025
Copy link

codecov bot commented Sep 26, 2025

Codecov Report

❌ Patch coverage is 92.00000% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
aiperf/common/logging.py 25.00% 3 Missing ⚠️
aiperf/controller/system_controller.py 50.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
aiperf/common/models/dataset_models.py (1)

92-105: Avoid mutable defaults on the new Pydantic models.

Using Field(default=[]) relies on Pydantic copying the list every time. Switch to default_factory=list so we never risk shared state or unnecessary deep copies.

-    payloads: list[dict[str, Any]] = Field(
-        default=[],
+    payloads: list[dict[str, Any]] = Field(
+        default_factory=list,
         description="List of formatted payloads in the session (one per turn). These have been formatted for the model and endpoint.",
     )
…
-    data: list[SessionPayloads] = Field(
-        default=[], description="List of all dataset sessions."
+    data: list[SessionPayloads] = Field(
+        default_factory=list, description="List of all dataset sessions."
     )
tests/dataset/test_dataset_manager_inputs_json.py (1)

124-133: Make payload conversion failures easier to diagnose.

By default asyncio.gather masks individual coroutine contexts when an exception is raised, making the source turn harder to track. Passing return_exceptions=True would hide errors entirely. A better middle ground is to call asyncio.gather with return_exceptions=False (the default) but wrap each format_payload call with additional context, or iterate sequentially. For clarity during failures, consider refactoring to iterate over turns or add context to raised errors so the failing turn/session is obvious.

tests/dataset/conftest.py (1)

123-124: Silence Ruff ARG001 by accepting *args, **kwargs.

Ruff flags the unused file_path/mode parameters in mock_open. Broaden the signature to *args, **kwargs and drop the unused names to keep lint green.

Apply this diff:

-    def mock_open(file_path, mode="r"):
+    def mock_open(*args, **kwargs):
         return AsyncContextManager(capture)
aiperf/dataset/dataset_manager.py (2)

124-134: Guard against unbounded concurrency on large datasets.

asyncio.gather will spawn one coroutine per turn in the conversation. For big datasets (thousands of turns) this can blow past file descriptors/memory and back-pressure the loop. Consider batching, streaming per turn, or using asyncio.Semaphore to cap outstanding conversions.


160-164: Log full stack traces for easier debugging.

Catching bare Exception and logging only the message hides stack context. Use self.exception/logger.exception (if available) or include exc_info=True so operators can trace the failure source.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b14d24 and 7d59ca9.

📒 Files selected for processing (14)
  • aiperf/common/config/config_defaults.py (1 hunks)
  • aiperf/common/constants.py (1 hunks)
  • aiperf/common/logging.py (4 hunks)
  • aiperf/common/models/__init__.py (3 hunks)
  • aiperf/common/models/dataset_models.py (2 hunks)
  • aiperf/controller/system_controller.py (2 hunks)
  • aiperf/dataset/dataset_manager.py (5 hunks)
  • aiperf/exporters/csv_exporter.py (2 hunks)
  • aiperf/exporters/json_exporter.py (2 hunks)
  • tests/data_exporters/test_csv_exporter.py (5 hunks)
  • tests/data_exporters/test_json_exporter.py (2 hunks)
  • tests/dataset/__init__.py (1 hunks)
  • tests/dataset/conftest.py (1 hunks)
  • tests/dataset/test_dataset_manager_inputs_json.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (11)
aiperf/common/models/__init__.py (1)
aiperf/common/models/dataset_models.py (2)
  • InputsFile (98-105)
  • SessionPayloads (86-95)
tests/data_exporters/test_json_exporter.py (1)
aiperf/common/config/config_defaults.py (1)
  • OutputDefaults (114-121)
aiperf/exporters/csv_exporter.py (1)
aiperf/common/config/config_defaults.py (1)
  • OutputDefaults (114-121)
aiperf/common/models/dataset_models.py (1)
aiperf/common/models/base_models.py (1)
  • AIPerfBaseModel (25-53)
aiperf/controller/system_controller.py (1)
aiperf/common/config/config_defaults.py (1)
  • OutputDefaults (114-121)
aiperf/dataset/dataset_manager.py (5)
aiperf/clients/model_endpoint_info.py (4)
  • ModelEndpointInfo (117-155)
  • from_user_config (47-54)
  • from_user_config (103-114)
  • from_user_config (130-135)
aiperf/common/config/config_defaults.py (1)
  • OutputDefaults (114-121)
aiperf/common/factories.py (16)
  • RequestConverterFactory (475-480)
  • create_instance (183-209)
  • create_instance (284-315)
  • create_instance (354-364)
  • create_instance (375-381)
  • create_instance (390-395)
  • create_instance (406-414)
  • create_instance (425-430)
  • create_instance (439-447)
  • create_instance (456-464)
  • create_instance (491-499)
  • create_instance (536-550)
  • create_instance (561-573)
  • create_instance (584-596)
  • create_instance (607-611)
  • create_instance (620-628)
aiperf/common/models/dataset_models.py (3)
  • Conversation (73-83)
  • InputsFile (98-105)
  • SessionPayloads (86-95)
aiperf/common/protocols.py (3)
  • RequestConverterProtocol (416-423)
  • format_payload (419-423)
  • info (69-69)
tests/dataset/test_dataset_manager_inputs_json.py (5)
aiperf/common/config/config_defaults.py (1)
  • OutputDefaults (114-121)
aiperf/common/factories.py (1)
  • RequestConverterFactory (475-480)
aiperf/common/models/dataset_models.py (2)
  • InputsFile (98-105)
  • SessionPayloads (86-95)
tests/dataset/conftest.py (4)
  • populated_dataset_manager (80-91)
  • capture_file_writes (95-127)
  • empty_dataset_manager (66-76)
  • user_config (19-28)
aiperf/dataset/dataset_manager.py (1)
  • _generate_inputs_json_file (136-164)
aiperf/exporters/json_exporter.py (1)
aiperf/common/config/config_defaults.py (1)
  • OutputDefaults (114-121)
tests/data_exporters/test_csv_exporter.py (1)
aiperf/common/config/config_defaults.py (1)
  • OutputDefaults (114-121)
aiperf/common/logging.py (2)
aiperf/common/config/config_defaults.py (1)
  • OutputDefaults (114-121)
tests/dataset/conftest.py (1)
  • user_config (19-28)
tests/dataset/conftest.py (3)
aiperf/common/config/output_config.py (1)
  • OutputConfig (15-34)
aiperf/common/models/dataset_models.py (3)
  • Conversation (73-83)
  • Text (24-27)
  • Turn (43-70)
aiperf/dataset/dataset_manager.py (1)
  • DatasetManager (52-355)
🪛 Ruff (0.13.1)
aiperf/dataset/dataset_manager.py

160-160: Do not catch blind exception: Exception

(BLE001)

tests/dataset/test_dataset_manager_inputs_json.py

185-185: Unused function argument: args

(ARG001)


185-185: Unused function argument: kwargs

(ARG001)


186-186: Avoid specifying long messages outside the exception class

(TRY003)

tests/dataset/conftest.py

123-123: Unused function argument: file_path

(ARG001)


123-123: Unused function argument: mode

(ARG001)

🔇 Additional comments (12)
tests/dataset/__init__.py (1)

1-2: License header alignment looks good

SPDX metadata matches project conventions and keeps test package compliant.

aiperf/common/constants.py (1)

12-13: Addition of GRACEFUL_SHUTDOWN_TIMEOUT matches new shutdown flow.

New constant is well documented and consistent with existing timeout defaults.

aiperf/common/config/config_defaults.py (1)

115-121: No hard-coded references to inputs.json or aiperf.log
I ran a repo-wide search and found no occurrences outside config_defaults.py; confirm any documentation or CLI defaults reference these new constants.

aiperf/common/models/__init__.py (2)

24-27: Consistent public surface for new dataset models

Re-exporting InputsFile and SessionPayloads here keeps the public API aligned with their introduction in dataset_models; no gaps spotted.


91-109: all kept in sync

The additions to __all__ match the new imports, so downstream consumers get the expected symbols.

tests/data_exporters/test_json_exporter.py (2)

11-11: Test now tracks shared constant

Switching to OutputDefaults keeps the expectation coupled to the runtime constant—solid guard against future drift.


95-97: Expectation mirrors exporter path

The assertion now mirrors the exporter’s default path logic, so the test will flag any future divergence.

aiperf/exporters/json_exporter.py (1)

10-51: Exporter path follows config defaults

Using OutputDefaults.PROFILE_EXPORT_AIPERF_JSON_FILE keeps this exporter aligned with the centralized defaults; everything else remains untouched.

aiperf/exporters/csv_exporter.py (1)

12-46: CSV exporter path centralized

Great to see the CSV exporter adopting the same OutputDefaults constant—consistent artifact naming across exporters.

aiperf/controller/system_controller.py (1)

13-520: Log file path honors artifact root

The controller now reports the log location under the configured artifact directory, matching the logging setup—looks good.

aiperf/common/logging.py (1)

14-163: Logging defaults sourced from OutputDefaults

All file-handling paths now flow through OutputDefaults, ensuring every logging entry point honors the same folder/file defaults. Nice consolidation.

tests/data_exporters/test_csv_exporter.py (1)

11-293: Tests aligned with exporter defaults

Updating the expectations to use OutputDefaults.PROFILE_EXPORT_AIPERF_CSV_FILE guarantees the tests mirror the runtime behavior. Everything checks out.

Copy link
Contributor

@the-david-oy the-david-oy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very clean PR! Thanks for adding this feature.

@ajcasagrande ajcasagrande merged commit a58de00 into main Sep 26, 2025
6 checks passed
@ajcasagrande ajcasagrande deleted the ajc/inputs.json branch September 26, 2025 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants