diff --git a/docs/cli.md b/docs/cli.md index 785a0b1..d2cd0c0 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -254,6 +254,63 @@ aha delete --model qwen3vl-2b - Shows "Model not found" message if the model directory doesn't exist - Shows "Model deleted successfully" message after completion +### list - List all supported models + +List all supported models with their ModelScope IDs. + +**Syntax:** +```bash +aha list [OPTIONS] +``` + +**Options:** + +| Option | Description | Default | +|--------|-------------|---------| +| `-j, --json` | Output in JSON format (includes name, model_id, and type fields) | false | + +**Examples:** + +```bash +# List models in table format (default) +aha list + +# List models in JSON format +aha list --json + +# Short form +aha list -j +``` + +**JSON Output Format:** + +When using `--json`, the output includes: +- `name`: Model identifier used with `-m` flag +- `model_id`: Full ModelScope model ID +- `type`: Model category (`llm`, `ocr`, `asr`, or `image`) + +Example: +```json +[ + { + "name": "qwen3vl-2b", + "model_id": "Qwen/Qwen3-VL-2B-Instruct", + "type": "llm" + }, + { + "name": "deepseek-ocr", + "model_id": "deepseek-ai/DeepSeek-OCR", + "type": "ocr" + } +] +``` + +**Model Types:** +- `llm`: Language models (text generation, chat, etc.) +- `ocr`: Optical Character Recognition models +- `asr`: Automatic Speech Recognition models +- `image`: Image processing models + ## Supported Models | Model ID | Model Name | Description | diff --git a/docs/cli.zh-CN.md b/docs/cli.zh-CN.md index 7ec8f31..db83be4 100644 --- a/docs/cli.zh-CN.md +++ b/docs/cli.zh-CN.md @@ -254,6 +254,63 @@ aha delete --model qwen3vl-2b - 如果模型目录不存在,显示"模型未找到"消息 - 删除完成后显示"删除成功"消息 +### list - 列出所有支持的模型 + +列出所有支持的模型及其 ModelScope ID。 + +**语法:** +```bash +aha list [OPTIONS] +``` + +**选项:** + +| 选项 | 说明 | 默认值 | +|------|------|--------| +| `-j, --json` | 以 JSON 格式输出(包含 name、model_id 和 type 字段) | false | + +**示例:** + +```bash +# 以表格格式列出模型(默认) +aha list + +# 以 JSON 格式列出模型 +aha list --json + +# 简写形式 +aha list -j +``` + +**JSON 输出格式:** + +使用 `--json` 时,输出包含: +- `name`:与 `-m` 参数一起使用的模型标识符 +- `model_id`:完整的 ModelScope 模型 ID +- `type`:模型类别(`llm`、`ocr`、`asr` 或 `image`) + +示例: +```json +[ + { + "name": "qwen3vl-2b", + "model_id": "Qwen/Qwen3-VL-2B-Instruct", + "type": "llm" + }, + { + "name": "deepseek-ocr", + "model_id": "deepseek-ai/DeepSeek-OCR", + "type": "ocr" + } +] +``` + +**模型类型:** +- `llm`:语言模型(文本生成、对话等) +- `ocr`:光学字符识别模型 +- `asr`:自动语音识别模型 +- `image`:图像处理模型 + ## 支持的模型 | 模型标识 | 模型名称 | 说明 | diff --git a/src/main.rs b/src/main.rs index 46bbffd..4adf92c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,8 @@ use aha::{ utils::{download_model, get_default_save_dir}, }; use clap::{Args, Parser, Subcommand, ValueEnum}; +use serde::Serialize; +use serde_json; use rocket::{ Config, data::{ByteUnit, Limits}, @@ -63,7 +65,7 @@ enum Commands { /// Run model inference directly Run(RunArgs), /// List all supported models - List, + List(ListArgs), } /// Common/shared arguments for server operations @@ -168,6 +170,14 @@ struct DeleteArgs { model: WhichModel, } +/// Arguments for the 'list' subcommand (list all supported models) +#[derive(Args, Debug)] +struct ListArgs { + /// Output models in JSON format (includes name, model_id, and type fields) + #[arg(short, long)] + json: bool, +} + /// Get the default weight path for a given model /// Returns ~/.aha/{model_id} e.g., ~/.aha/OpenBMB/VoxCPM1.5 fn get_default_weight_path(model: WhichModel) -> String { @@ -176,8 +186,17 @@ fn get_default_weight_path(model: WhichModel) -> String { format!("{}/{}", save_dir, model_id) } +/// Model information for JSON output +#[derive(Serialize)] +struct ModelInfo { + name: String, + model_id: String, + #[serde(rename = "type")] + model_type: String, +} + /// List all supported models -fn run_list() -> anyhow::Result<()> { +fn run_list(args: ListArgs) -> anyhow::Result<()> { let models = [ WhichModel::MiniCPM4_0_5B, WhichModel::Qwen2_5vl3B, @@ -199,15 +218,29 @@ fn run_list() -> anyhow::Result<()> { WhichModel::FunASRNano2512, ]; - println!("Available models:"); - println!(); - println!("{:<30} ModelScope ID", "Model Name"); - println!("{}", "-".repeat(80)); - for model in models { - let possible_value = model.to_possible_value().unwrap(); - let name = possible_value.get_name(); - let id = model.model_id(); - println!("{:<30} {}", name, id); + if args.json { + // JSON output + let model_infos: Vec = models.iter().map(|model| { + let possible_value = model.to_possible_value().unwrap(); + ModelInfo { + name: possible_value.get_name().to_string(), + model_id: model.model_id().to_string(), + model_type: model.model_type().to_string(), + } + }).collect(); + println!("{}", serde_json::to_string_pretty(&model_infos)?); + } else { + // Table output (default) + println!("Available models:"); + println!(); + println!("{:<30} ModelScope ID", "Model Name"); + println!("{}", "-".repeat(80)); + for model in models { + let possible_value = model.to_possible_value().unwrap(); + let name = possible_value.get_name(); + let id = model.model_id(); + println!("{:<30} {}", name, id); + } } Ok(()) @@ -517,7 +550,7 @@ async fn main() -> anyhow::Result<()> { Some(Commands::Delete(args)) => run_delete(args), Some(Commands::Download(args)) => run_download(args).await, Some(Commands::Run(args)) => run_run(args), - Some(Commands::List) => run_list(), + Some(Commands::List(args)) => run_list(args), None => { // Backward compatibility: when no subcommand is provided, use 'cli' behavior let model = cli.model.expect("Model is required (use -m or --model)");