Files
hsa/.venv/lib/python3.10/site-packages/dashscope/cli.py
2025-09-11 13:29:12 +00:00

594 lines
23 KiB
Python

#!/usr/bin/env python
import argparse
import sys
import time
from http import HTTPStatus
import dashscope
from dashscope.aigc import Generation
from dashscope.common.constants import (DeploymentStatus, FilePurpose,
TaskStatus)
def print_failed_message(rsp):
print('Failed, request_id: %s, status_code: %s, code: %s, message: %s' %
(rsp.request_id, rsp.status_code, rsp.code, rsp.message))
def text_generation(args):
response = Generation.call(args.model, args.prompt, stream=args.stream)
if args.stream:
for rsp in response:
if rsp.status_code == HTTPStatus.OK:
print(rsp.output)
print(rsp.usage)
else:
print_failed_message(rsp)
else:
if response.status_code == HTTPStatus.OK:
print(response.output)
print(response.usage)
else:
print_failed_message(response)
class FineTunes:
@classmethod
def call(cls, args):
params = {}
if args.n_epochs is not None:
params['n_epochs'] = args.n_epochs
if args.batch_size is not None:
params['batch_size'] = args.batch_size
if args.learning_rate is not None:
params['learning_rate'] = args.learning_rate
if args.prompt_loss is not None:
params['prompt_loss'] = args.prompt_loss
if args.params:
params.update(args.params)
rsp = dashscope.FineTune.call(
model=args.model,
training_file_ids=args.training_file_ids,
validation_file_ids=args.validation_file_ids,
mode=args.mode,
hyper_parameters=params)
if rsp.status_code == HTTPStatus.OK:
print('Create fine-tune job success, job_id: %s' %
rsp.output['job_id'])
cls.wait(rsp.output['job_id'])
else:
print_failed_message(rsp)
@classmethod
def wait(cls, job_id):
try:
while True:
rsp = dashscope.FineTune.get(job_id)
if rsp.status_code == HTTPStatus.OK:
if rsp.output['status'] == TaskStatus.FAILED:
print('Fine-tune FAILED!')
break
elif rsp.output['status'] == TaskStatus.CANCELED:
print('Fine-tune task CANCELED')
break
elif rsp.output['status'] == TaskStatus.RUNNING:
print(
'Fine-tuning is RUNNING, start get output stream.')
cls.stream_events(job_id)
elif rsp.output['status'] == TaskStatus.SUCCEEDED:
print('Fine-tune task success, fine-tuned model:%s' %
rsp.output['finetuned_output'])
break
else:
print('The fine-tune task is: %s' %
rsp.output['status'])
time.sleep(30)
else:
print_failed_message(rsp)
except Exception:
print(
'You can stream output via: dashscope fine_tunes.stream -j %s'
% job_id)
@classmethod
def get(cls, args):
rsp = dashscope.FineTune.get(args.job)
if rsp.status_code == HTTPStatus.OK:
if rsp.output['status'] == TaskStatus.FAILED:
print('Fine-tune failed!')
elif rsp.output['status'] == TaskStatus.CANCELED:
print('Fine-tune task canceled')
elif rsp.output['status'] == TaskStatus.SUCCEEDED:
print('Fine-tune task success, fine-tuned model : %s' %
rsp.output['finetuned_output'])
else:
print('The fine-tune task is: %s' % rsp.output['status'])
else:
print_failed_message(rsp)
@classmethod
def list(cls, args):
rsp = dashscope.FineTune.list(page=args.start_page,
page_size=args.page_size)
if rsp.status_code == HTTPStatus.OK:
if rsp.output is not None:
for job in rsp.output['jobs']:
if job['status'] == TaskStatus.SUCCEEDED:
print(
'job: %s, status: %s, base model: %s, fine-tuned model: %s' # noqa E501
% # noqa
(job['job_id'], job['status'], job['model'],
job['finetuned_output']))
else:
print('job: %s, status: %s, base model: %s' %
(job['job_id'], job['status'], job['model']))
else:
print('There is no fine-tuned model.')
else:
print_failed_message(rsp)
@classmethod
def stream_events(cls, job_id):
# check job status if job is completed, get log.
rsp = dashscope.FineTune.get(job_id)
if rsp.status_code == HTTPStatus.OK:
if rsp.output['status'] in [
TaskStatus.FAILED, TaskStatus.CANCELED,
TaskStatus.SUCCEEDED
]:
print('Fine-tune job: %s is %s' %
(job_id, rsp.output['status']))
cls.log(job_id)
return
else:
print_failed_message(rsp)
return
# start streaming events.
try:
stream_events = dashscope.FineTune.stream_events(job_id)
for rsp in stream_events:
if rsp.status_code == HTTPStatus.OK:
print(rsp.output)
else:
print_failed_message(rsp)
except Exception:
print(
'You can stream output via: dashscope fine-tunes.stream -j %s'
% job_id)
@classmethod
def events(cls, args):
cls.stream_events(args.job)
@classmethod
def log(cls, job_id):
start = 1
n_line = 1000 # 1000 line per request
while True:
rsp = dashscope.FineTune.logs(job_id, start, n_line)
if rsp.status_code == HTTPStatus.OK:
for line in rsp.output['logs']:
print(line)
if rsp.output['total'] < n_line:
break
else:
start += n_line
else:
print_failed_message(rsp)
@classmethod
def cancel(cls, args):
rsp = dashscope.FineTune.cancel(args.job)
if rsp.status_code == HTTPStatus.OK:
print('Cancel fine-tune job: %s success!')
else:
print_failed_message(rsp)
@classmethod
def delete(cls, args):
rsp = dashscope.FineTune.delete(args.job)
if rsp.status_code == HTTPStatus.OK:
print('fine_tune job: %s delete success' % args.job)
else:
print_failed_message(rsp)
class Files:
@classmethod
def upload(cls, args):
rsp = dashscope.File.upload(file_path=args.file,
purpose=args.purpose,
description=args.description)
print(rsp)
if rsp.status_code == HTTPStatus.OK:
print('Upload success, file id: %s' %
rsp.output['uploaded_files'][0]['file_id'])
else:
print_failed_message(rsp)
@classmethod
def get(cls, args):
rsp = dashscope.File.get(file_id=args.id)
if rsp.status_code == HTTPStatus.OK:
print('file_id: %s, name: %s, description: %s' %
(rsp.output['file_id'], rsp.output['name'],
rsp.output['description']))
else:
print_failed_message(rsp)
@classmethod
def list(cls, args):
rsp = dashscope.File.list(page=args.start_page,
page_size=args.page_size)
if rsp.status_code == HTTPStatus.OK:
if rsp.output is not None:
for f in rsp.output['files']:
print('file_id: %s, name: %s, description: %s, time: %s' %
(f['file_id'], f['name'], f['description'],
f['gmt_create']))
else:
print('There is no uploaded file.')
else:
print_failed_message(rsp)
@classmethod
def delete(cls, args):
rsp = dashscope.File.delete(args.id)
if rsp.status_code == HTTPStatus.OK:
print('Delete success')
else:
print_failed_message(rsp)
class Deployments:
@classmethod
def call(cls, args):
rsp = dashscope.Deployment.call(model=args.model,
capacity=args.capacity,
suffix=args.suffix)
if rsp.status_code == HTTPStatus.OK:
deployed_model = rsp.output['deployed_model']
print('Create model: %s deployment' % deployed_model)
try:
while True: # wait for deployment ok.
status = dashscope.Deployment.get(deployed_model)
if status.status_code == HTTPStatus.OK:
if status.output['status'] in [
DeploymentStatus.PENDING,
DeploymentStatus.DEPLOYING
]:
time.sleep(30)
print('Deployment %s is %s' %
(deployed_model, status.output['status']))
else:
print('Deployment: %s status: %s' %
(deployed_model, status.output['status']))
break
else:
print_failed_message(rsp)
except Exception:
print('You can get deployment status via: \
dashscope deployments.get -d %s' % deployed_model)
else:
print_failed_message(rsp)
@classmethod
def get(cls, args):
rsp = dashscope.Deployment.get(args.deploy)
if rsp.status_code == HTTPStatus.OK:
print('Deployed model: %s capacity: %s status: %s' %
(rsp.output['deployed_model'], rsp.output['capacity'],
rsp.output['status']))
else:
print_failed_message(rsp)
@classmethod
def list(cls, args):
rsp = dashscope.Deployment.list(page_no=args.start_page,
page_size=args.page_size)
if rsp.status_code == HTTPStatus.OK:
if rsp.output is not None:
if 'deployments' not in rsp.output:
print('There is no deployed model!')
return
for deployment in rsp.output['deployments']:
print('Deployed_model: %s, model: %s, status: %s' %
(deployment['deployed_model'],
deployment['model_name'], deployment['status']))
else:
print('There is no deployed model.')
else:
print_failed_message(rsp)
@classmethod
def update(cls, args):
rsp = dashscope.Deployment.update(args.deployed_model, args.version)
if rsp.status_code == HTTPStatus.OK:
if rsp.output is not None:
if 'deployments' not in rsp.output:
print('There is no deployed model!')
return
for deployment in rsp.output['deployments']:
print('Deployed_model: %s, model: %s, status: %s' %
(deployment['deployed_model'],
deployment['model_name'], deployment['status']))
else:
print('There is no deployed model.')
else:
print_failed_message(rsp)
@classmethod
def scale(cls, args):
rsp = dashscope.Deployment.scale(args.deployed_model, args.capacity)
if rsp.status_code == HTTPStatus.OK:
if rsp.output is not None:
print('Deployed_model: %s, model: %s, status: %s' %
(rsp.output['deployed_model'], rsp.output['model_name'],
rsp.output['status']))
else:
print('There is no deployed model.')
else:
print_failed_message(rsp)
@classmethod
def delete(cls, args):
rsp = dashscope.Deployment.delete(args.deploy)
if rsp.status_code == HTTPStatus.OK:
print('Deployed model: %s delete success' % args.deploy)
else:
print_failed_message(rsp)
# from: https://gist.github.com/vadimkantorov/37518ff88808af840884355c845049ea
class ParseKVAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, dict())
for each in values:
try:
key, value = each.split('=')
getattr(namespace, self.dest)[key] = value
except ValueError as ex:
message = '\nTraceback: {}'.format(ex)
message += "\nError on '{}' || It should be 'key=value'".format(
each)
raise argparse.ArgumentError(self, str(message))
def main():
parser = argparse.ArgumentParser(
prog='dashscope', description='dashscope command line tools.')
parser.add_argument('-k', '--api-key', help='Dashscope API key.')
sub_parsers = parser.add_subparsers(help='Api subcommands')
text_generation_parser = sub_parsers.add_parser('generation.call')
text_generation_parser.add_argument('-p',
'--prompt',
type=str,
required=True,
help='Input prompt')
text_generation_parser.add_argument('-m',
'--model',
type=str,
required=True,
help='The model to call.')
text_generation_parser.add_argument('--history',
type=str,
required=False,
help='The history of the request.')
text_generation_parser.add_argument('-s',
'--stream',
default=False,
action='store_true',
help='Use stream mode default false.')
text_generation_parser.set_defaults(func=text_generation)
fine_tune_call = sub_parsers.add_parser('fine_tunes.call')
fine_tune_call.add_argument(
'-t',
'--training_file_ids',
required=True,
nargs='+',
help='Training file ids which upload by File command.')
fine_tune_call.add_argument(
'-v',
'--validation_file_ids',
required=False,
nargs='+',
default=[],
help='Validation file ids which upload by File command.')
fine_tune_call.add_argument('-m',
'--model',
type=str,
required=True,
help='The based model to start fine-tune.')
fine_tune_call.add_argument(
'--mode',
type=str,
required=False,
choices=['sft', 'efficient_sft'],
help='Select fine-tune mode sft or efficient_sft')
fine_tune_call.add_argument('-e',
'--n_epochs',
type=int,
required=False,
help='How many epochs to fine-tune.')
fine_tune_call.add_argument('-b',
'--batch_size',
type=int,
required=False,
help='How big is batch_size.')
fine_tune_call.add_argument('-l',
'--learning_rate',
type=float,
required=False,
help='The fine-tune learning rate.')
fine_tune_call.add_argument('-p',
'--prompt_loss',
type=float,
required=False,
help='The fine-tune prompt loss.')
fine_tune_call.add_argument(
'--hyper_parameters',
nargs='+',
dest='params',
action=ParseKVAction,
help='Extra hyper parameters accepts by key1=value1 key2=value2',
metavar='KEY1=VALUE1')
fine_tune_call.set_defaults(func=FineTunes.call)
fine_tune_get = sub_parsers.add_parser('fine_tunes.get')
fine_tune_get.add_argument('-j',
'--job',
type=str,
required=True,
help='The fine-tune job id.')
fine_tune_get.set_defaults(func=FineTunes.get)
fine_tune_delete = sub_parsers.add_parser('fine_tunes.delete')
fine_tune_delete.add_argument('-j',
'--job',
type=str,
required=True,
help='The fine-tune job id.')
fine_tune_delete.set_defaults(func=FineTunes.delete)
fine_tune_stream = sub_parsers.add_parser('fine_tunes.stream')
fine_tune_stream.add_argument('-j',
'--job',
type=str,
required=True,
help='The fine-tune job id.')
fine_tune_stream.set_defaults(func=FineTunes.events)
fine_tune_list = sub_parsers.add_parser('fine_tunes.list')
fine_tune_list.add_argument('-s',
'--start_page',
type=int,
default=1,
help='Start of page, default 1')
fine_tune_list.add_argument('-p',
'--page_size',
type=int,
default=10,
help='The page size, default 10')
fine_tune_list.set_defaults(func=FineTunes.list)
fine_tune_cancel = sub_parsers.add_parser('fine_tunes.cancel')
fine_tune_cancel.add_argument('-j',
'--job',
type=str,
required=True,
help='The fine-tune job id.')
fine_tune_cancel.set_defaults(func=FineTunes.cancel)
file_upload = sub_parsers.add_parser('files.upload')
file_upload.add_argument(
'-f',
'--file',
type=str,
required=True,
help='The file path to upload',
)
file_upload.add_argument(
'-p',
'--purpose',
default=FilePurpose.fine_tune,
const=FilePurpose.fine_tune,
nargs='?',
help='Purpose to upload file[fine-tune]',
required=True,
)
file_upload.add_argument(
'-d',
'--description',
type=str,
help='The file description.',
required=False,
)
file_upload.set_defaults(func=Files.upload)
file_get = sub_parsers.add_parser('files.get')
file_get.add_argument('-i',
'--id',
type=str,
required=True,
help='The file ID')
file_get.set_defaults(func=Files.get)
file_delete = sub_parsers.add_parser('files.delete')
file_delete.add_argument('-i',
'--id',
type=str,
required=True,
help='The files ID')
file_delete.set_defaults(func=Files.delete)
file_list = sub_parsers.add_parser('files.list')
file_list.add_argument('-s',
'--start_page',
type=int,
default=1,
help='Start of page, default 1')
file_list.add_argument('-p',
'--page_size',
type=int,
default=10,
help='The page size, default 10')
file_list.set_defaults(func=Files.list)
deployments_call = sub_parsers.add_parser('deployments.call')
deployments_call.add_argument('-m',
'--model',
required=True,
help='The model ID')
deployments_call.add_argument('-s',
'--suffix',
required=False,
help=('The suffix of the deployment, \
lower cased characters 8 chars max.'))
deployments_call.add_argument('-c',
'--capacity',
type=int,
required=False,
default=1,
help='The target capacity')
deployments_call.set_defaults(func=Deployments.call)
deployments_get = sub_parsers.add_parser('deployments.get')
deployments_get.add_argument('-d',
'--deploy',
required=True,
help='The deployed model.')
deployments_get.set_defaults(func=Deployments.get)
deployments_delete = sub_parsers.add_parser('deployments.delete')
deployments_delete.add_argument('-d',
'--deploy',
required=True,
help='The deployed model.')
deployments_delete.set_defaults(func=Deployments.delete)
deployments_list = sub_parsers.add_parser('deployments.list')
deployments_list.add_argument('-s',
'--start_page',
type=int,
default=1,
help='Start of page, default 1')
deployments_list.add_argument('-p',
'--page_size',
type=int,
default=10,
help='The page size, default 10')
deployments_list.set_defaults(func=Deployments.list)
deployments_scale = sub_parsers.add_parser('deployments.scale')
deployments_scale.add_argument('-d',
'--deployed_model',
type=str,
required=True,
help='The deployed model to scale')
deployments_scale.add_argument('-c',
'--capacity',
type=int,
required=True,
help='The target capacity')
deployments_scale.set_defaults(func=Deployments.scale)
args = parser.parse_args()
if args.api_key is not None:
dashscope.api_key = args.api_key
args.func(args)
if __name__ == '__main__':
sys.exit(main())