第3章 三类客户端Python Client、JavaScript Client与Curl Client1——使用Gradio Python Client第3章 三类客户端Python Client、JavaScript Client与Curl Client3.1 使用Gradio Python Client3.1.1 连接Gradio应用1. 通过URL或SpaceID连接2. duplicate()和HF_TOKEN3.1.2 查看可用API1. view_api()与页脚链接2. API记录器与OpenAPI规范3.1.3 使用API直接调用predict()1. 单个或多个参数2. 通过文件路径或URL上传数据3.1.4 使用API异步调用job与生成器端点第3章 三类客户端Python Client、JavaScript Client与Curl ClientGradio应用部署完成后如何将它作为API使用呢这就用到Gradio Client它向应用提交各类请求后应用返回相应结果。本章讲解三类客户端Python Client、JavaScript Client与Curl Client。这三类客户端都包含以下内容安装方式通过URL或Space ID连接Gradio应用查看Gradio应用可用API方法view_api()和页面查看以及使用API方法直接调用.predict()和异步调用job。另外Curl客户端还有获取嵌入式URL、POST请求预测和GET获取结果的使用。除此之外本章还演示了在线JavaScript/TypeScript开发环境PLAYCODE的使用。通过本章读者可掌握如何安装各类客户端、连接Gradio应用、安全认证、查看并使用API的方法。3.1 使用Gradio Python Client通过Gradio Python ClientPython形式的代码程序会非常容易将Gradio应用作为API使用。如果已安装Gradio的最新版本那么gradio_client将作为依赖项包含在内。但如果不确定请使用以下命令升级$ pipinstall--upgradegradio_client3.1.1 连接Gradio应用Gradio Client可通过URL或Space ID连接任何托管的Gradio应用。1. 通过URL或SpaceID连接Gradio Client主要用于连接Hugging Face Spaces上托管的应用程序因此可用Hugging Face Spaces的Space ID创建Client对象但也可通过URL连接本地或外网部署的Gradio应用。为增加读者对Gradio程序的了解引入Space ID为gradio/text_analysis的示例其基于spaCy库的英文文本分析功能对输入进行语法分析并输出highlight、json和html三种格式的分析结果如代码3-1所示代码3-1importgradioasgrimportos# 以下括号中的代码也可在对应环境的命令行下运行os.system(pip install spacy)os.system(python -m spacy download en_core_web_sm)importspacyfromspacyimportdisplacy nlpspacy.load(en_core_web_sm)deftext_analysis(text):docnlp(text)htmldisplacy.render(doc,styledep,pageTrue)html(div stylemax-width:100%; max-height:360px; overflow:autohtml/div)pos_count{char_count:len(text),token_count:len(doc)}pos_tokens[]fortokenindoc:pos_tokens.extend([(token.text,token.pos_),( ,None)])returnpos_tokens,pos_count,html demogr.Interface(text_analysis,gr.Textbox(placeholderEnter sentence here...),[highlight,json,html],examples[[What a beautiful morning for a walk!],[It was the best of times, it was the worst of times.]])demo.launch()首先使用os.system执行命令行操作以自动安装spaCy库及下载英文语言模型然后加载预训练的英文处理管道(en_core_web_sm)接着导入可视化工具displacy用于依存关系展示最后在‌文本分析函数中接收文本输入采用工业级NLP库进行专业文本处理生成交互式依存关系图并封装为可滚动HTML容器统计字符数和词汇数量提取每个词汇及其对应的词性标注返回词性标注、统计数据和可视化HTML结果。程序运行界面如图3-1图3-1创建对应Client并执行预测函数.predict()如代码3-2所示代码3-2fromgradio_clientimportClient# or client Client(https://huggingface.co/spaces/gradio/text_analysis)clientClient(gradio/text_analysis)resultclient.predict(textFind the API endpoint below corresponding to your desired function in the app.,api_name/predict)print(result)LoadedasAPI:https://gradio-text-analysis.hf.space ✔([{token:Find,class_or_confidence:VERB},...)代码中首先从gradio_client中导入对象Client然后利用应用的URL或SpaceID创建客户端对象client最后使用client的内置函数predict执行预测结果。Client的成员函数predict中参数text为API输入变量api_name指定接受输入变量的API尤其存在多个API时需要特别指定。2. duplicate()和HF_TOKEN虽然可以通过Hugging Face的公共Space作为Gradio Client的API但当请求太多时会被Hugging Face限速。如果想无限次使用某个Space的Gradio程序只需通过duplicate()将Space复制到本地并创建一个私人的Gradio应用即可。当访问Hugging Face上私有Space或复制Space时需传入HF_TOKEN或使用登录后的Hugging Face CLI。以Spaces的abidlabs/en2fr为例它将英语翻译为法语如代码3-3所示代码3-3importgradioasgrfromtransformersimportpipeline titleEnglish to French Translationpipepipeline(translation,modelHelsinki-NLP/opus-mt-en-fr)defpredict(text):returnpipe(text)[0][translation_text]ifacegr.Interface(fnpredict,inputs[gr.Textbox(labeltext,lines3)],outputstext,titletitle)iface.launch()使用在线编辑运行环境Colab并通过HF_TOKEN方式连接如代码3-4所示代码3-4importosfromgradio_clientimportClient,filefromgoogle.colabimportuserdata# 设置系统变量的hf_tokenhf_token需在Hugging Face官网申请HF_TOKENuserdata.get(HF_TOKEN)clientClient.duplicate(abidlabs/en2fr,hf_tokenHF_TOKEN,hardwarecpu-basic)client.predict(Hello,api_name/predict)# 输出如下Using your existing Space:https://hf.space/shao918516/en2fr LoadedasAPI:https://shao918516-en2fr.hf.space ✔Bonjour.关于duplicate()需注意以下几点(1)之前复制过Space重新运行duplicate()将不会创建新的Space相反客户端将连接到先前创建的空间。因此多次重新运行Client.duplicate()方法是安全的。(2)如果在Colab NoteBook运行获取HF_TOKEN方法如下fromgoogle.colabimportuserdata HF_TOKENuserdata.get(HF_TOKEN)(3)关于计费GPU。如果原始空间使用GPU那么复制后的私人空间也会使用这时Hugging Face账户将根据GPU的价格进行计费。为了最大限度地减少花费共享空间会在1小时不活动后自动进入睡眠状态。如果不想扩大开销也可以设置免费硬件hardware “cpu-basic”其他可选收费硬件包括cpu-upgrade, t4-small, l4x1, a10g-small, h100, v5e-1x1等。3.1.2 查看可用API如何获取已部署Gradio应用的API以便在其他程序中使用呢有两种方法可以实现函数调用view_api()和页面查看API。1. view_api()与页脚链接当使用客户端连接到Gradio应用后可以通过客户端成员函数view_api()查看可用的API以gradio/text_analysis为例在本地启动后创建客户端并使用view_api()查看可用的API如代码3-5所示代码3-5fromgradio_clientimportClient clientClient(http://127.0.0.1:7860/)client.view_api()# 输出如下Client.predict()Usage Info---------------------------Named API endpoints:1-predict(text,api_name/predict)-(output_0,output_1,output_2)Parameters:-[Textbox]text:str(required)Returns:-[Highlightedtext]output_0:list[dict(token:str,class_or_confidence:str|float|None)]-[Json]output_1:str|float|bool|list|dict(anyvalid json)-[Html]output_2:str可以看到Client.predict()的用途信息它有1个命名的API端点predict并展示了如何使用该API端点进行预测提供入参text必需及api_name‘/predict’返回Highlightedtext、Json及Html类型的结果。注意view_api()会自动忽略gr.State()类型的输入输出参数这是因为Python客户端会自动处理状态——当客户端发出一系列请求时一个请求返回的状态会存储在内部并自动提供给后续请求。如果想重置状态可以通过调用Client.reset_session()来完成。除了调用客户端对象的成员函数view_api()还可以在demo.launch()中的设置参数footer_links[“api”]来查看可用API在应用界面中如图3-2右侧黑框所示图3-2单击“通过API使用”出现可用API页面如图3-3所示图3-32. API记录器与OpenAPI规范注意图3-3的API页面还包括一个“API Recorder”单击后可在页面底部图3-2左侧黑框看到API的调用记录。API Recorder可以记录用户与Gradio界面的交互信息并将交互转换为相应的代码以便与Python Client配合一起运行。以openai/gpt-oss-safeguard-20b为例当调用清除方法时其输出如图3-4所示图3-4通过访问端点your-gradio-app-url/gradio_api/openapi.json例如本地应用可访问http://127.0.0.1:7860/predict/openapi.json可获取该Gradio应用的完整OpenAPI原Swagger规范。该OpenAPI规范是REST API标准化且与编程语言无关的接口描述使开发者和计算机系统都能发现并理解程序服务的功能特性。3.1.3 使用API直接调用predict()获取到可用的API端点后有两种使用方法直接调用predict()和异步调用job。本小节讲解predict()中如何设置单个或多个参数以及通过文件路径或URL上传数据。1. 单个或多个参数使用API进行预测的最简单方法就是调用Client对象的predict()函数将参数api_name指定相应API即可参考代码3-2。当传递多个参数时应将其作为单独的参数传递给predict()以Spaces的计算器gradio/calculator为例如代码3-6所示代码3-6importgradioasgrdefcalculator(num1,operation,num2):ifoperationadd:returnnum1num2elifoperationsubtract:returnnum1-num2elifoperationmultiply:returnnum1*num2elifoperationdivide:ifnum20:raisegr.Error(Cannot divide by zero!)returnnum1/num2 demogr.Interface(calculator,[number,gr.Radio([add,subtract,multiply,divide]),number],number,examples[[45,add,3],[3.14,divide,2],[144,multiply,2.5],[0,subtract,1.2]],titleToy Calculator,descriptionHeres a sample toy calculator.)if__name____main__:demo.launch()启动gr.Interface输入数据并选择加减乘除运行界面如图3-5图3-5在Client对象的predict()函数中多个参数的调用方法如代码3-7所示建议提供关键字参数而不是位置参数此处可省略api_name代码3-7fromgradio_clientimportClient clientClient(gradio/calculator)# 关键字参数client.predict(num14, operationadd, num25)client.predict(4,add,5)9.02. 通过文件路径或URL上传数据上传数据时将文件路径或URL以字符串形式传递给gradio_client.handle_file()函数负责将文件上传到Gradio服务器并确保文件得到正确的预处理。以处理音频转录功能的Spaces项目abidlabs/whisper为例其源代码如代码3-8所示代码3-8importgradioasgr whispergr.load(models/openai/whisper-small)deftranscribe(audio):returnwhisper(audio).replace(AutomaticSpeechRecognitionOutput(text ,).replace(, chunksNone),)gr.Interface(transcribe,gr.Audio(typefilepath),gr.Textbox()).launch()代码中gr.load()可加载大模型并将其当作普通的Python函数使用。通过Client.predict()函数调用API并上传文件如代码3-9所示代码3-9fromgradio_clientimportClient,handle_file clientClient(abidlabs/whisper)client.predict(audiohandle_file(https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3))# 输出如下LoadedasAPI:https://abidlabs-whisper.hf.space ✔ My thought I have nobody by a beautyandwillasyou poured...3.1.4 使用API异步调用job与生成器端点Client.predict()是一个阻塞操作因为它在返回预测之前等待操作完成。因此最好让作业在后台运行这可以通过对象Job实现。Job常规用法。通过对象Client及其submit()操作来创建对象Job这时作业在后台运行 稍后调用其result()来获取结果。此外Job还有以下操作获取状态Job对象的status()方法来获取正在运行作业的状态。函数返回StatusUpdate对象主要属性有code状态代码、rank队列排序、queue_size队列大小、eta预估时间、success是否完成及time生成时间等。添加回调可以通过参数result_callbacks添加一个或多个回调作业执行结果将传送至回调函数以便执行指定操作。取消作业Job类还有一个实例方法cancel()用于取消已排队但尚未启动的作业。是否完成Job的类方法done()可判断作业是否完成。操作的总合示例如代码3-10所示代码3-10fromgradio_clientimportClientdefprint_result(x):print(The translated result is: {x})clientClient(srcabidlabs/en2fr)jobclient.submit(Hello,api_name/predict,result_callbacks[print_result])# Do something elsejob.status()StatusUpdate(codeStatus.STARTING:STARTING,rankNone,queue_sizeNone,etaNone,successNone,timedatetime.datetime(2024,7,10,10,3,21,689817),progress_dataNone,logNone)job.result()# This is blockingThe translated resultis:Bonjour job.cancel()# will return False, assuming the job has startedjob.done()# will return True生成器端点。某些Gradio API端点不返回单个值而是一系列值这时通过Job的outputs()来获取此类生成器端点返回的所有系列值。以gradio/count_generator计数程序为例它每0.5秒返回一个递增的数字如代码3-11所示代码3-11importgradioasgrimporttimedefcount(n):foriinrange(int(n)):time.sleep(0.5)yieldidefshow(n):returnstr(list(range(int(n))))withgr.Blocks()asdemo:withgr.Column():numgr.Number(value10)withgr.Row():count_btngr.Button(Count)list_btngr.Button(List)withgr.Column():outgr.Textbox()count_btn.click(count,num,out)list_btn.click(show,num,out)demo.queue()if__name____main__:demo.launch()单击“Count”会每隔0.5秒返回0到9的数字单击“List”列出所有生成数字的列表运行界面如图3-6图3-6创建客户端并提交参数后Job可以作为生成器端点从端点迭代返回结果最终返回数组可由Job.outputs()获取如代码3-12所示代码3-12fromgradio_clientimportClient clientClient(srcgradio/count_generator)jobclient.submit(3,api_name/count)foroinjob:print(o)012job.outputs()[0,1,2]注意在生成器端点上运行job.result()时只会返回端点生成的第一个值。