mirror of
https://github.com/lmstudio-ai/lms.git
synced 2025-08-02 02:42:12 +08:00
* feat(cli): add --verbose flag to chat command * Address review comments: add types, rename --verbose to --stats, remove emoji and GPU layers stat - Add proper types for displayVerboseStats function parameters - Rename --verbose flag to --stats to avoid conflict with global verbose flag - Add short flag -t for --stats - Remove emoji from stats output for cleaner appearance - Hide numGpuLayers stat as it's not currently populated * Update src/subcommands/chat.ts Co-authored-by: Yagil Burowski <yagil@elementlabs.ai> * Remove short stats flag * Update Prediction Stats title * Add second new line ln26 * Remove short stats flag again --------- Co-authored-by: Yagil Burowski <yagil@elementlabs.ai>
This commit is contained in:
@ -1,9 +1,11 @@
|
||||
import { Chat, type LLM } from "@lmstudio/sdk";
|
||||
import { command, option, optional, string } from "cmd-ts";
|
||||
import { command, flag, option, optional, string } from "cmd-ts";
|
||||
import * as readline from "readline";
|
||||
import { createClient, createClientArgs } from "../createClient.js";
|
||||
import { createLogger, logLevelArgs } from "../logLevel.js";
|
||||
import { optionalPositional } from "../optionalPositional.js";
|
||||
import type { LLMPredictionStats } from "@lmstudio/lms-shared-types";
|
||||
import type { SimpleLogger } from "@lmstudio/lms-common";
|
||||
|
||||
async function readStdin(): Promise<string> {
|
||||
return new Promise(resolve => {
|
||||
@ -20,6 +22,26 @@ async function readStdin(): Promise<string> {
|
||||
});
|
||||
}
|
||||
|
||||
function displayVerboseStats(stats: LLMPredictionStats, logger: SimpleLogger) {
|
||||
logger.info("\n\nPrediction Stats:");
|
||||
logger.info(` Stop Reason: ${stats.stopReason}`);
|
||||
if (stats.tokensPerSecond !== undefined) {
|
||||
logger.info(` Tokens/Second: ${stats.tokensPerSecond.toFixed(2)}`);
|
||||
}
|
||||
if (stats.timeToFirstTokenSec !== undefined) {
|
||||
logger.info(` Time to First Token: ${stats.timeToFirstTokenSec.toFixed(3)}s`);
|
||||
}
|
||||
if (stats.promptTokensCount !== undefined) {
|
||||
logger.info(` Prompt Tokens: ${stats.promptTokensCount}`);
|
||||
}
|
||||
if (stats.predictedTokensCount !== undefined) {
|
||||
logger.info(` Predicted Tokens: ${stats.predictedTokensCount}`);
|
||||
}
|
||||
if (stats.totalTokensCount !== undefined) {
|
||||
logger.info(` Total Tokens: ${stats.totalTokensCount}`);
|
||||
}
|
||||
}
|
||||
|
||||
export const chat = command({
|
||||
name: "chat",
|
||||
description: "Open an interactive chat with the currently loaded model.",
|
||||
@ -44,6 +66,10 @@ export const chat = command({
|
||||
short: "s",
|
||||
description: "Custom system prompt to use for the chat",
|
||||
}),
|
||||
stats: flag({
|
||||
long: "stats",
|
||||
description: "Display detailed prediction statistics after each response",
|
||||
}),
|
||||
},
|
||||
async handler(args) {
|
||||
const logger = createLogger(args);
|
||||
@ -101,6 +127,10 @@ export const chat = command({
|
||||
const result = await prediction.result();
|
||||
chat.append("assistant", result.content);
|
||||
|
||||
if (args.stats) {
|
||||
displayVerboseStats(result.stats, logger);
|
||||
}
|
||||
|
||||
if (!lastFragment.endsWith("\n")) {
|
||||
// Newline before new shell prompt if not already there
|
||||
process.stdout.write("\n");
|
||||
@ -149,6 +179,10 @@ export const chat = command({
|
||||
const result = await prediction.result();
|
||||
chat.append("assistant", result.content);
|
||||
|
||||
if (args.stats) {
|
||||
displayVerboseStats(result.stats, logger);
|
||||
}
|
||||
|
||||
// Resume readline and write a new prompt
|
||||
process.stdout.write("\n\n");
|
||||
rl.resume();
|
||||
|
Reference in New Issue
Block a user