Skip to content

feat: Support passing in tool calls with OpenAI chat format when doing SFT - #1181

Merged
terrykong merged 10 commits into
mainfrom
jiaqiz/tool-call-sft-params
Sep 26, 2025
Merged

feat: Support passing in tool calls with OpenAI chat format when doing SFT#1181
terrykong merged 10 commits into
mainfrom
jiaqiz/tool-call-sft-params

Conversation

@HeyyyyyyG

@HeyyyyyyG HeyyyyyyG commented Sep 22, 2025

Copy link
Copy Markdown
Contributor

What does this PR do ?

Support passing in tool calls with OpenAI chat format when doing SFT.
Support passing in a .jinja file as the chat template.

Issues

List issues that this PR closes (syntax):
close #1002

Usage

  • You can potentially add a usage example below
# Add a code snippet demonstrating how to use this

Before your PR is "Ready for review"

Pre checks:

  • Make sure you read and followed Contributor guidelines
  • Did you write any new necessary tests?
  • Did you run the unit tests and functional tests locally? Visit our Testing Guide for how to run tests
  • Did you add or update any necessary documentation? Visit our Document Development Guide for how to write, build and test the docs.

Additional Information

  • ...

Summary by CodeRabbit

  • New Features

    • Support loading chat templates from .jinja files.
    • Pass and preserve optional tool definitions across preprocessing and datasets.
    • OpenAI-format dataset now falls back to JSONL loading and preserves original sample keys.
    • Expanded logging options: enable/disable TensorBoard, MLflow, Weights & Biases, plus optional GPU monitoring controls.
  • Bug Fixes

    • More robust handling of messages with missing or None content while preserving multimodal elements.
  • Documentation

    • Clarified chat_template usage in config and added commented OpenAI data options.

Signed-off-by: Jiaqi Zeng <jiaqiz@nvidia.com>
@HeyyyyyyG
HeyyyyyyG requested review from a team as code owners September 22, 2025 17:40
@coderabbitai

coderabbitai Bot commented Sep 22, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds optional tool-calling support across SFT: propagates tools from datasets through preprocessing into chat template formatting; preserves heterogeneous sample keys via a new PreservingDataset and JSON fallback loader; supports chat template loading from .jinja files; extends config with OpenAI-format options and observability settings.

Changes

Cohort / File(s) Summary of Changes
Configuration additions
examples/configs/sft.yaml
Comment clarifying chat_template can be a Jinja string or .jinja file path. Adds optional OpenAI-format data keys (train/val paths, chat_key, system_key, system_prompt, tool_key). Expands logging: enables/disables tensorboard/mlflow/wandb, GPU monitoring settings, and nested backend configs.
SFT preprocessing tools passthrough
examples/run_sft.py
Forwards tools from each datum into get_formatted_message_log via tools=datum_dict.get("tools", None). No other logic changes.
Tokenizer chat template loader
nemo_rl/algorithms/utils.py
In get_tokenizer, if chat_template ends with ".jinja", loads template content from the file path before applying. Keeps existing None/"default"/string branches. Prints which file is loaded.
OpenAI-format dataset enhancements
nemo_rl/data/datasets/response_datasets/__init__.py, nemo_rl/data/datasets/response_datasets/oai_format_dataset.py
Adds tool_key parameter (default "tools") to OpenAIFormatDataset usage. Introduces PreservingDataset to keep original sample keys and structure. Attempts HF dataset load first; on failure, falls back to JSONL with preservation and prints chosen path. add_messages_key now optionally includes tools when present.
Message formatting with tools and robust content handling
nemo_rl/data/llm_message_utils.py
get_formatted_message_log adds tools parameter and forwards it to tokenizer.apply_chat_template via assembled template kwargs. Improves content handling for None/strings/lists while preserving non-text modalities. Adds limited debug prints for the first sample and final turn. Minor refactor to prepare template kwargs per message.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Loader as Dataset Loader
  participant Preproc as sft_preprocessor
  participant Formatter as get_formatted_message_log
  participant Tok as Tokenizer.apply_chat_template

  rect rgb(245,248,255)
    note over Loader: Load samples (HF path → fallback JSONL)
    User->>Loader: Configure OpenAI-format dataset (tool_key optional)
    Loader-->>User: Samples (may include tools)
  end

  rect rgb(245,255,245)
    User->>Preproc: Sample datum
    Preproc->>Formatter: messages, roles, tools=datum.tools?
    note right of Formatter: Builds template kwargs incl. tools (if provided)
    Formatter->>Tok: apply_chat_template(messages, kwargs...)
    Tok-->>Formatter: formatted text
    Formatter-->>Preproc: formatted conversation
  end
Loading
sequenceDiagram
  autonumber
  participant Config as Config (sft.yaml)
  participant Utils as get_tokenizer
  participant FS as Filesystem

  Config->>Utils: chat_template value
  alt chat_template endswith ".jinja"
    Utils->>FS: Read template file
    FS-->>Utils: Template string
    Utils-->>Config: Tokenizer with file-based template
  else default/inline/None
    Utils-->>Config: Tokenizer with existing handling
  end
Loading

Estimated code review effort

ðŸŽŊ 3 (Moderate) | ⏱ïļ ~25 minutes

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠ïļ Warning Several edits in this changeset appear outside the linked issue scope: examples/configs/sft.yaml introduces expanded logging/backends and GPU monitoring configuration, and nemo_rl/algorithms/utils.py plus nemo_rl/data/llm_message_utils.py add ad-hoc print/debug output that is unrelated to enabling tool-calling SFT. The additions of PreservingDataset and a JSONL fallback are defensible as in-scope because they support preserving heterogeneous samples (including tools). The configuration and noisy print changes should be isolated or removed to keep the feature PR focused and reviewable. Please move the logging/GPU-monitoring config changes to a separate PR or clearly document why they belong here, and remove or replace ad-hoc prints with proper logger.debug calls (or gate them behind a debug/verbose flag); after isolating these unrelated edits, re-run CI and include a short usage example and tests to validate the end-to-end tool-calling SFT behavior.
Docstring Coverage ⚠ïļ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Test Results For Major Changes ⚠ïļ Warning This PR introduces new feature support for tool-calling SFT and .jinja chat templates, with non-trivial changes across dataset loading/shape (new PreservingDataset, altered OpenAIFormatDataset return structure), tokenizer/template handling, and message formatting APIs. These qualify as major changes that can impact preprocessing behavior and potentially training outcomes. The PR description (as of September 22, 2025) contains no test results, benchmarks, or convergence/performance validations, and the contributor checklist items for tests/docs are unchecked. Therefore, the requirement to include testing information for major changes is not met. Please update the PR description with a concise test plan and results: include unit/integration tests for tool preservation and .jinja templates, sample runs showing formatted outputs match expectations, and a small SFT smoke run comparing loss/metrics before vs. after (or with/without tools) to show no regression; if performance could be affected, add throughput/latency numbers with config details. Mark the checklist items as completed and link to logs or artifacts so reviewers can verify.
✅ 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 "feat: Support passing in tool calls with OpenAI chat format when doing SFT" concisely and accurately summarizes the primary change implemented in this PR — adding support for passing tool calls in OpenAI chat format during supervised fine-tuning. It is specific to the feature and avoids unrelated details or noisy lists, so a teammate scanning history would understand the main purpose. The phrasing is clear and appropriate for a single-line PR title.
Linked Issues Check ✅ Passed This PR implements the core coding requirements from linked issue #1002: OpenAIFormatDataset was extended to preserve a configurable "tool_key", the SFT preprocessing path forwards tools from examples to get_formatted_message_log, and get_formatted_message_log accepts a tools parameter and passes it into tokenizer.apply_chat_template so tools/messages are formatted for SFT; get_tokenizer also gained .jinja template-file support as stated in the objectives. These modifications are present across dataset loading, preprocessing, and template handling code summarized in the diff. The changes therefore satisfy the primary implementation goals to load tools in OpenAI chat format and use apply_chat_template for formatting. The PR does not include unit tests or a filled usage example, which would help validate the end-to-end workflow.
âœĻ Finishing touches
  • 📝 Generate Docstrings
🧊 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jiaqiz/tool-call-sft-params

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠ïļ Outside diff range comments (3)
nemo_rl/data/datasets/response_datasets/__init__.py (1)

58-65: Do not set config defaults in code; pass through tool_key without a fallback.

Per nemo_rl guidelines, avoid non-None defaults in code. Using data_config.get("tool_key", "tools") sets a hidden default. Let YAML (examples/configs) carry the default, or pass None and let the dataset handle it explicitly.

Apply this diff:

-        base_dataset = OpenAIFormatDataset(
+        base_dataset = OpenAIFormatDataset(
             data_config["train_data_path"],
             data_config["val_data_path"],
             data_config["chat_key"],
             data_config["system_key"],
             data_config["system_prompt"],
-            data_config.get("tool_key", "tools"),
+            data_config.get("tool_key"),  # no in-code default
         )
nemo_rl/data/datasets/response_datasets/oai_format_dataset.py (2)

104-118: Do not encode a default for tool_key in library code.

In nemo_rl, defaults belong in YAML, not code. tool_key should default to None here and be set in config.

-        tool_key: str | None = "tools",
+        tool_key: str | None = None,

Also remove any code that assumes "tools" when None; treat None as “no tools column”.


172-190: Use explicit validation instead of assert for data checks.

assert can be stripped with -O. Raise a clear error instead.

-        assert messages[-1]["role"] == "assistant"
+        if not messages or messages[-1].get("role") != "assistant":
+            raise ValueError("OpenAIFormatDataset expects the last message to be from 'assistant'.")
ðŸ§đ Nitpick comments (4)
nemo_rl/algorithms/utils.py (1)

242-254: Support .jinja file path more robustly (existence, encoding) and update docs.

  • Guard path handling, read with UTF‑8, and raise on missing file.
  • Also document file-path support in the function docstring.

Apply this diff:

         elif tokenizer_config["chat_template"].lower() == "default":
             print("Using tokenizer's default chat template")
-        elif tokenizer_config["chat_template"].endswith(".jinja"):
-            # Load template from file
-            template_path = tokenizer_config["chat_template"]
-            print(f"Loading chat template from file: {template_path}")
-            with open(template_path, "r") as f:
-                tokenizer.chat_template = f.read()
+        elif isinstance(tokenizer_config["chat_template"], str) and tokenizer_config["chat_template"].endswith(".jinja"):
+            # Load template from file
+            from pathlib import Path
+            template_path = Path(tokenizer_config["chat_template"]).expanduser()
+            if not template_path.is_file():
+                raise FileNotFoundError(f"Chat template file not found: {template_path}")
+            print(f"Loading chat template from file: {template_path}")
+            tokenizer.chat_template = template_path.read_text(encoding="utf-8")

And amend the docstring section describing chat_template (Lines 166-171) to include “or a path to a .jinja file”.

examples/configs/sft.yaml (1)

159-167: Surface the recommended default for tool_key in YAML instead of code.

To avoid hidden defaults in code, show the default in exemplar configs. Consider uncommenting tool_key with "tools".

-  ## OpenAI format specific configs
+  ## OpenAI format specific configs
   # train_data_path: "/path/to/train.jsonl"  # Path to training data
   # val_data_path: "/path/to/val.jsonl"      # Path to validation data
   # chat_key: "messages"                     # Key for messages in the data
   # system_key: null                         # Key for system message (optional)
   # system_prompt: null                      # Default system prompt (optional)
-  # tool_key: null                           # Key for tools in the data (optional, defaults to "tools" if not specified)
+  tool_key: "tools"                          # Key for tools in the data (optional; recommended default)
nemo_rl/data/datasets/response_datasets/oai_format_dataset.py (2)

23-84: PreservingDataset polish: remove unused args; minor Ruff nits.

  • map(..., *args) unused; drop it or name as _ to silence ARG002.
  • Docstrings are good; keep them concise.
-    def map(self, function: Callable, *args, **kwargs) -> "PreservingDataset":
+    def map(self, function: Callable, **kwargs) -> "PreservingDataset":
         """Apply a function to each sample in the dataset.

118-132: Narrow exception handling; add UTF‑8 when reading JSONL; reduce noisy prints.

  • Avoid catching bare Exception (BLE001). Catch specific errors from datasets and JSON.
  • Use encoding="utf-8".
  • Consider logging at debug level instead of unconditional prints.
-        except (TypeError, ValueError, Exception) as e:
+        except (TypeError, ValueError) as e:
+            # Fall back when schema heterogeneity breaks HF dataset assumptions
             # Fallback to custom loading for heterogeneous schemas
@@
-            with open(train_ds_path, "r") as f:
+            with open(train_ds_path, "r", encoding="utf-8") as f:
                 train_data = [json.loads(line) for line in f]
@@
-            with open(val_ds_path, "r") as f:
+            with open(val_ds_path, "r", encoding="utf-8") as f:
                 val_data = [json.loads(line) for line in f]

Optionally, import datasets as ds and also catch (OSError, json.JSONDecodeError). Replace print(...) with logging.debug(...) if a logger is available.

Also applies to: 132-143, 144-161

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

ðŸ“Ĩ Commits

Reviewing files that changed from the base of the PR and between 42aa41b and e3aa08a.

📒 Files selected for processing (6)
  • examples/configs/sft.yaml (2 hunks)
  • examples/run_sft.py (1 hunks)
  • nemo_rl/algorithms/utils.py (1 hunks)
  • nemo_rl/data/datasets/response_datasets/__init__.py (1 hunks)
  • nemo_rl/data/datasets/response_datasets/oai_format_dataset.py (3 hunks)
  • nemo_rl/data/llm_message_utils.py (6 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (CODING_GUIDELINES.md)

**/*.py: Follow the Google Python Style Guide for all Python code
Target Python 3.12+ for all Python code in NeMo-RL
Indent Python code with 4 spaces; do not use tabs
Python filenames should be snake_case (e.g., some_file.py)
Class names should be PascalCase
Function and method names should be snake_case
Local variable names should be snake_case; if starting with a number, prefix with k (e.g., k_99th_percentile)
Global variables should be UPPER_SNAKE_CASE and prefixed with G_ (e.g., G_MY_GLOBAL)
Constants should be UPPER_SNAKE_CASE
Avoid shadowing variables declared in an outer scope
Initialize all externally visible members of a class in the constructor
For public interfaces used outside a file, prefer docstrings over comments
Use comments mainly for code within a function or interfaces local to a file
Commented-out code must include a nearby comment explaining usage and why it is commented out; otherwise remove before merging
Use Google-style docstrings for classes and functions (Sphinx-parseable)
Avoid using reflection when functionality can be easily achieved without it
Limit except clauses to the smallest specific set of exceptions possible
For duck-typing via try/except, keep the try body minimal and use else for main logic
Add the NVIDIA copyright header (with current year) at the top of all Python files, excluding tests/ and test-only scripts

Files:

  • nemo_rl/algorithms/utils.py
  • nemo_rl/data/llm_message_utils.py
  • nemo_rl/data/datasets/response_datasets/oai_format_dataset.py
  • nemo_rl/data/datasets/response_datasets/__init__.py
  • examples/run_sft.py
nemo_rl/**/*.py

📄 CodeRabbit inference engine (CODING_GUIDELINES.md)

nemo_rl/**/*.py: Do not set non-None configuration defaults in code; YAML is the single source of truth for defaults
Access required config attributes directly (e.g., policy_cfg["precision"]) and assume presence; do not introduce hidden defaults
Express configuration optionality via TypedDict using typing.NotRequired
When adding a new config key to a TypedDict subclass, document the key’s purpose, valid values/types, and recommended default in code
For any class or function decorated with @ray.remote, add '# pragma: no cover' on the class/def line (and on remote functions)

Files:

  • nemo_rl/algorithms/utils.py
  • nemo_rl/data/llm_message_utils.py
  • nemo_rl/data/datasets/response_datasets/oai_format_dataset.py
  • nemo_rl/data/datasets/response_datasets/__init__.py
examples/configs/*.yaml

📄 CodeRabbit inference engine (CODING_GUIDELINES.md)

examples/configs/*.yaml: Exemplar configs under examples/configs/.yaml must include documented defaults
When adding a new config key, reflect its recommended default in exemplar YAMLs under examples/configs/
.yaml

Files:

  • examples/configs/sft.yaml
🧎 Code graph analysis (2)
nemo_rl/algorithms/utils.py (2)
tests/unit/models/generation/test_vllm_generation.py (1)
  • tokenizer (236-239)
tests/unit/utils/test_native_checkpoint.py (1)
  • tokenizer (113-116)
nemo_rl/data/datasets/response_datasets/oai_format_dataset.py (2)
nemo_rl/data/interfaces.py (1)
  • TaskDataSpec (53-86)
nemo_rl/data/datasets/response_datasets/response_dataset.py (1)
  • add_messages_key (72-80)
🊛 Ruff (0.13.1)
nemo_rl/data/datasets/response_datasets/oai_format_dataset.py

55-57: Avoid specifying long messages outside the exception class

(TRY003)


62-64: Avoid specifying long messages outside the exception class

(TRY003)


69-69: Unused method argument: args

(ARG002)


132-132: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Lint check
  • GitHub Check: Post automodel integration comment / Comment on PR
  • GitHub Check: Post submodule check comment / Comment on PR
🔇 Additional comments (5)
examples/configs/sft.yaml (1)

28-29: Good: inline note about .jinja path support.

Comment clarifies new behavior and aligns with utils.get_tokenizer. No action needed.

examples/run_sft.py (1)

69-77: LGTM: tools are forwarded to formatting safely.

Passing tools via datum_dict.get("tools") keeps behavior unchanged when absent.

Please confirm your chat templates (default or custom) actually reference the “tools” variable. If not, passing it is harmless, but older Transformers may reject unknown kwargs. See follow-up suggestion in llm_message_utils to add a safe fallback.

nemo_rl/data/llm_message_utils.py (3)

427-433: LGTM: safe handling for None content in multimodal/tool-call turns.

Returning [] for None content avoids errors when extracting images.


533-537: Double-check add_generation_prompt for 'tool' role.

Typically add_generation_prompt is only for user turns. Including tool turns might change formatting for some templates.

Would you like to keep add_generation_prompt on 'tool' messages? If unintentional, restrict to user only:

-            "add_generation_prompt": add_generation_prompt
-            and message["role"] in ["user", "tool"],
+            "add_generation_prompt": add_generation_prompt and message["role"] == "user",

531-543: Verify transformers version; add fallback only if supporting <4.45

transformers.PreTrainedTokenizerBase.apply_chat_template accepts a "tools" kwarg starting in transformers v4.45 (used in Llama/Qwen/Gemma docs). If this repo pins transformers >= 4.45 you can leave the code as-is; if you must support older transformers or third‑party tokenizers that may lack the kwarg, apply the TypeError retry below.

Location: nemo_rl/data/llm_message_utils.py (lines 531–543)

-        formatted_message: str = tokenizer.apply_chat_template(  # type: ignore
-            message_log_strs[: i + 1], **template_kwargs
-        )
+        try:
+            formatted_message: str = tokenizer.apply_chat_template(  # type: ignore
+                message_log_strs[: i + 1], **template_kwargs
+            )
+        except TypeError as e:
+            # Retry without tools for older tokenizers that don't accept this kwarg
+            if "tools" in template_kwargs:
+                template_kwargs.pop("tools", None)
+                formatted_message = tokenizer.apply_chat_template(  # type: ignore
+                    message_log_strs[: i + 1], **template_kwargs
+                )
+            else:
+                raise

Comment thread nemo_rl/data/llm_message_utils.py
@terrykong

Copy link
Copy Markdown
Collaborator

@yuki-97 could you help review

@yuki-97 yuki-97 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks @HeyyyyyyG for adding this! overall LGTM, left some comments.

Comment thread nemo_rl/data/datasets/response_datasets/oai_format_dataset.py Outdated
Comment thread nemo_rl/data/datasets/response_datasets/oai_format_dataset.py
Signed-off-by: Jiaqi Zeng <jiaqiz@nvidia.com>
@HeyyyyyyG
HeyyyyyyG requested a review from a team as a code owner September 24, 2025 23:08
Signed-off-by: Jiaqi Zeng <jiaqiz@nvidia.com>
Signed-off-by: Jiaqi Zeng <jiaqiz@nvidia.com>
@HeyyyyyyG
HeyyyyyyG requested review from a team as code owners September 24, 2025 23:38
@github-actions github-actions Bot added the Documentation Improvements or additions to documentation label Sep 24, 2025
@HeyyyyyyG

Copy link
Copy Markdown
Contributor Author

Made changes according to comments, and updated docs. @yuki-97 @terrykong could you take a look again?

yuki-97
yuki-97 previously approved these changes Sep 25, 2025

@yuki-97 yuki-97 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks @HeyyyyyyG , LGTM! @terrykong can you also take a review?

@terrykong terrykong left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm @HeyyyyyyG . just one minor comment

Comment thread nemo_rl/data/datasets/response_datasets/__init__.py Outdated
Co-authored-by: Terry Kong <terrycurtiskong@gmail.com>
Signed-off-by: Jiaqi Zeng <49757268+HeyyyyyyG@users.noreply.github.com>
Comment thread examples/configs/sft.yaml Outdated
@terrykong

Copy link
Copy Markdown
Collaborator

@HeyyyyyyG to resolve the lint issue, you need to update your branch

HeyyyyyyG and others added 3 commits September 25, 2025 12:19
Co-authored-by: Terry Kong <terrycurtiskong@gmail.com>
Signed-off-by: Jiaqi Zeng <49757268+HeyyyyyyG@users.noreply.github.com>
Signed-off-by: Jiaqi Zeng <jiaqiz@nvidia.com>
@HeyyyyyyG

Copy link
Copy Markdown
Contributor Author

@terrykong fixed

@terrykong terrykong added the CI:L1 Run doctests, unit tests, and functional tests label Sep 25, 2025
@terrykong

Copy link
Copy Markdown
Collaborator

great, thanks @jiemingz . enqueued

@terrykong
terrykong merged commit 6fe56b0 into main Sep 26, 2025
41 of 42 checks passed
@terrykong
terrykong deleted the jiaqiz/tool-call-sft-params branch September 26, 2025 00:22
PrinsYin pushed a commit to PrinsYin/RL that referenced this pull request Nov 30, 2025
â€Ķg SFT (NVIDIA-NeMo#1181)

Signed-off-by: Jiaqi Zeng <jiaqiz@nvidia.com>
Signed-off-by: Jiaqi Zeng <49757268+HeyyyyyyG@users.noreply.github.com>
Co-authored-by: Terry Kong <terrycurtiskong@gmail.com>
yuanhangsu1986 pushed a commit to yuanhangsu1986/RL-Nemontron-Edge-Omni that referenced this pull request Feb 21, 2026
â€Ķg SFT (NVIDIA-NeMo#1181)

Signed-off-by: Jiaqi Zeng <jiaqiz@nvidia.com>
Signed-off-by: Jiaqi Zeng <49757268+HeyyyyyyG@users.noreply.github.com>
Co-authored-by: Terry Kong <terrycurtiskong@gmail.com>
Signed-off-by: yuanhangs <yuanhangs@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI:L1 Run doctests, unit tests, and functional tests Documentation Improvements or additions to documentation r0.4.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tool calling SFT support

4 participants