Skip to content
Merged
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
35 changes: 35 additions & 0 deletions tests/test_gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,41 @@ def test_chat_response_format_sent_as_top_level_kwarg(
assert call["response_format"] == {"type": "json_object"}
assert "response_format" not in call.get("extra_body", {})

def test_chat_json_mode_sent_as_top_level_kwarg(
self, runner, patched_cli, tmp_path
):
f = tmp_path / "img.png"
f.write_bytes(b"fakepng")
result = runner.invoke(
app,
["gw", "chat", str(f), "-m", "pp-ocrv6", "--json-mode", "--no-stream"],
)
assert result.exit_code == 0, result.stdout
call = patched_cli["client"].gateway.completions.calls[-1]
assert call["response_format"] == {"type": "json_object"}
assert "response_format" not in call.get("extra_body", {})

def test_chat_json_mode_and_response_format_mutually_exclusive(
self, runner, patched_cli, tmp_path
):
f = tmp_path / "img.png"
f.write_bytes(b"fakepng")
result = runner.invoke(
app,
[
"gw",
"chat",
str(f),
"-m",
"pp-ocrv6",
"--json-mode",
"--response-format",
"json_object",
],
)
assert result.exit_code == 1
assert "mutually exclusive" in result.stdout.lower()

def test_chat_response_format_invalid(self, runner, patched_cli, tmp_path):
f = tmp_path / "img.png"
f.write_bytes(b"fakepng")
Expand Down
23 changes: 21 additions & 2 deletions vlmrun/cli/_cli/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
vlmrun gw chat img.jpg -m paddleocr/pp-ocrv6 --method detect
vlmrun gw chat img.jpg -m paddleocr/pp-ocrv6 --method ocr \\
--method-params '{"lang": "en", "score_threshold": 0.5}'
vlmrun gw chat img.jpg -m paddleocr/pp-ocrv6 --json-mode

\b
NOTES:
Expand Down Expand Up @@ -621,14 +622,23 @@ def chat(
"--method-params",
help='JSON object of method arguments, e.g. \'{"lang": "en"}\'.',
),
json_mode: bool = typer.Option(
False,
"--json-mode",
help=(
"Enable JSON mode (response_format json_object). Mutually exclusive "
"with --response-format."
),
),
response_format: Optional[str] = typer.Option(
None,
"--response-format",
help=(
"Ask the MODEL to constrain its output: 'text', 'json_object' (JSON "
'mode), or a JSON object like \'{"type":"json_schema",...}\'. '
"Sent to the gateway as `response_format`; not yet honored server-side. "
"(Distinct from --json, which formats the CLI's own output.)"
"(Distinct from --json, which formats the CLI's own output. Use "
"--json-mode as a shorthand for json_object.)"
),
),
extra: Optional[List[str]] = typer.Option(
Expand Down Expand Up @@ -676,7 +686,16 @@ def chat(
raise typer.Exit(1)
extra_body["method_params"] = parsed_params

if response_format:
if json_mode and response_format:
console.print(
"[red]Error:[/] --json-mode and --response-format are mutually "
"exclusive. Use one or the other."
)
raise typer.Exit(1)

if json_mode:
create_kwargs["response_format"] = {"type": "json_object"}
elif response_format:
# A standard OpenAI create() field, so it rides as a top-level kwarg.
create_kwargs["response_format"] = _parse_response_format(response_format)

Expand Down
2 changes: 1 addition & 1 deletion vlmrun/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.7.2"
__version__ = "0.7.3"
Loading