语音识别模型文档生成SenseVoice-Small ONNX模型API自动注释实践1. 引言为什么需要自动生成API文档如果你开发过语音识别相关的应用一定遇到过这样的烦恼模型部署好了接口也调通了但每次都要手动写文档告诉别人这个接口怎么用、参数怎么传、返回什么结果。更头疼的是模型一更新文档又得重写费时费力还容易出错。今天要分享的就是一个能帮你自动搞定这件事的实践方案。我们用SenseVoice-Small这个高性能语音识别模型结合ONNX格式和Gradio前端搭建一个完整的语音识别服务然后自动为这个服务的API生成清晰、规范的文档。你可能会问SenseVoice-Small是什么简单说它是一个支持50多种语言、能识别情感和声音事件、推理速度超快的语音识别模型。10秒的音频它只要70毫秒就能识别完比大家熟悉的Whisper-Large快15倍。而且它提供了ONNX量化版本部署起来特别方便。这篇文章会手把手带你完成三件事快速部署SenseVoice-Small语音识别服务用Gradio搭建一个简单好用的前端界面最关键的一步自动为这个服务的API生成完整文档无论你是想给自己的项目加个语音识别功能还是想学习怎么自动化文档生成这篇文章都能给你实用的参考。2. 环境准备与模型部署2.1 系统要求与依赖安装开始之前确保你的环境满足以下要求Python 3.8或更高版本至少4GB可用内存处理长音频时需要更多支持ONNX Runtime的CPU或GPU环境安装必要的依赖包# 基础依赖 pip install modelscope onnxruntime gradio # 如果需要GPU加速 pip install onnxruntime-gpu # 文档生成相关工具 pip install pydoc-markdown mkdocs这里用到的几个核心工具ModelScope阿里的模型社区平台方便下载和管理预训练模型ONNX Runtime微软开源的推理引擎能高效运行ONNX格式的模型Gradio快速构建机器学习Web界面的工具几行代码就能做出交互式应用pydoc-markdown自动从Python代码生成Markdown文档的工具2.2 下载与加载SenseVoice-Small模型SenseVoice-Small提供了ONNX量化版本文件大小只有几百MB下载和加载都很方便。量化后的模型在精度损失很小的情况下大幅减少了内存占用和推理时间。import os from modelscope import snapshot_download # 模型在ModelScope上的ID model_id iic/SenseVoiceSmall # 下载模型到本地 model_dir snapshot_download(model_id, cache_dir./models) print(f模型已下载到: {model_dir}) print(f模型文件列表: {os.listdir(model_dir)})下载完成后你会看到模型目录下包含这些文件model.onnxONNX格式的模型文件config.json模型配置文件vocab.txt词汇表文件其他相关资源文件2.3 初始化ONNX推理会话ONNX Runtime提供了高效的推理环境下面看看怎么初始化import onnxruntime as ort import numpy as np def load_onnx_model(model_path): 加载ONNX模型并创建推理会话 参数: model_path: ONNX模型文件路径 返回: session: ONNX Runtime会话对象 input_names: 模型输入节点名称列表 output_names: 模型输出节点名称列表 # 设置推理提供者优先使用GPU providers [CUDAExecutionProvider, CPUExecutionProvider] # 创建会话选项 sess_options ort.SessionOptions() sess_options.graph_optimization_level ort.GraphOptimizationLevel.ORT_ENABLE_ALL # 加载模型 session ort.InferenceSession(model_path, sess_optionssess_options, providersproviders) # 获取输入输出信息 input_names [input.name for input in session.get_inputs()] output_names [output.name for output in session.get_outputs()] print(f模型加载成功!) print(f输入节点: {input_names}) print(f输出节点: {output_names}) return session, input_names, output_names # 使用示例 model_path ./models/iic/SenseVoiceSmall/model.onnx session, input_names, output_names load_onnx_model(model_path)这里有几个关键点需要注意提供者顺序[CUDAExecutionProvider, CPUExecutionProvider]表示优先使用GPU如果GPU不可用则自动回退到CPU优化级别ORT_ENABLE_ALL启用所有图优化能提升推理速度输入输出信息了解模型的输入输出格式很重要后面预处理和后处理都需要这些信息3. 构建语音识别服务3.1 音频预处理与特征提取语音识别模型通常需要特定的输入格式SenseVoice-Small也不例外。我们需要把原始音频转换成模型能理解的格式。import librosa import torch import torchaudio.compliance.kaldi as kaldi def preprocess_audio(audio_path, target_sample_rate16000): 预处理音频文件提取MFCC特征 参数: audio_path: 音频文件路径 target_sample_rate: 目标采样率Hz 返回: features: 预处理后的特征张量 audio_length: 音频长度秒 # 加载音频文件 audio, sr librosa.load(audio_path, srtarget_sample_rate, monoTrue) # 计算音频长度 audio_length len(audio) / sr # 转换为PyTorch张量 audio_tensor torch.FloatTensor(audio).unsqueeze(0) # 添加batch维度 # 提取MFCC特征SenseVoice使用的特征 # 这里使用torchaudio的kaldi兼容实现 features kaldi.mfcc( waveformaudio_tensor, sample_frequencytarget_sample_rate, num_ceps80, # MFCC系数数量 num_mel_bins80, # Mel滤波器数量 frame_length25, # 帧长毫秒 frame_shift10, # 帧移毫秒 ) # 添加batch维度并转换为numpy数组 features features.unsqueeze(0).numpy() print(f音频预处理完成: {audio_path}) print(f原始音频长度: {audio_length:.2f}秒) print(f特征形状: {features.shape}) return features, audio_length def prepare_model_input(features): 准备模型输入数据 参数: features: 音频特征 返回: model_input: 模型输入字典 # 根据SenseVoice的输入要求准备数据 # 实际格式需要参考模型文档 model_input { input: features, input_lengths: np.array([features.shape[1]], dtypenp.int64) } return model_input音频预处理的关键步骤统一采样率所有音频都重采样到16kHz这是语音识别的标准采样率特征提取使用MFCC梅尔频率倒谱系数提取音频特征格式转换将特征转换成模型需要的输入格式3.2 模型推理与结果后处理模型推理完成后我们需要把数字输出转换成人类可读的文字。def run_inference(session, model_input): 运行模型推理 参数: session: ONNX Runtime会话 model_input: 模型输入数据 返回: raw_output: 原始模型输出 # 运行推理 raw_output session.run(None, model_input) return raw_output def postprocess_output(raw_output, vocab_path./models/iic/SenseVoiceSmall/vocab.txt): 后处理模型输出将数字序列转换为文字 参数: raw_output: 模型原始输出 vocab_path: 词汇表文件路径 返回: transcript: 识别出的文字 confidence: 识别置信度如果有 emotions: 情感识别结果如果有 events: 声音事件检测结果如果有 # 加载词汇表 with open(vocab_path, r, encodingutf-8) as f: vocab [line.strip() for line in f] # 假设raw_output[0]是文字识别结果索引序列 # 实际格式需要根据模型输出调整 indices raw_output[0].flatten() # 将索引转换为文字 transcript for idx in indices: if idx len(vocab) and idx ! 0: # 0通常是空白或填充标记 transcript vocab[idx] # 简单的情感分析示例 # SenseVoice实际会输出更丰富的情感信息 emotions { positive: 0.7, neutral: 0.2, negative: 0.1 } # 声音事件检测示例 events [ {type: speech, start: 0.0, end: 5.0, confidence: 0.95}, {type: music, start: 5.0, end: 8.0, confidence: 0.8} ] return transcript, emotions, events # 完整的识别流程 def recognize_speech(audio_path): 完整的语音识别流程 参数: audio_path: 音频文件路径 返回: result: 识别结果字典 # 1. 预处理 features, audio_length preprocess_audio(audio_path) # 2. 准备输入 model_input prepare_model_input(features) # 3. 推理 raw_output run_inference(session, model_input) # 4. 后处理 transcript, emotions, events postprocess_output(raw_output) # 5. 组装结果 result { text: transcript, audio_length: audio_length, emotions: emotions, events: events, timestamp: { start: 0.0, end: audio_length } } return result后处理需要注意的几点词汇表映射模型输出的是词汇表中的索引需要转换成实际文字空白标记处理很多语音识别模型使用0作为空白或填充标记需要过滤掉多任务输出SenseVoice能同时输出文字、情感、事件需要分别处理3.3 使用Gradio构建Web界面Gradio能让我们快速创建一个Web界面不用写HTML/CSS/JavaScript。import gradio as gr import tempfile import soundfile as sf class SpeechRecognitionApp: def __init__(self, model_session): self.session model_session self.setup_ui() def setup_ui(self): 设置Gradio界面 with gr.Blocks(titleSenseVoice语音识别系统, themegr.themes.Soft()) as self.demo: gr.Markdown(# SenseVoice语音识别系统) gr.Markdown(上传音频文件或录制语音系统将自动识别文字、情感和声音事件) with gr.Row(): with gr.Column(scale1): # 输入部分 input_audio gr.Audio( label上传或录制音频, typefilepath, sources[upload, microphone] ) with gr.Row(): clear_btn gr.Button(清空, variantsecondary) submit_btn gr.Button(开始识别, variantprimary) with gr.Column(scale2): # 输出部分 with gr.Tab(识别结果): output_text gr.Textbox( label识别文字, lines5, placeholder识别结果将显示在这里... ) with gr.Tab(情感分析): emotion_chart gr.BarPlot( label情感分布, x情感类型, y置信度 ) with gr.Tab(声音事件): events_table gr.Dataframe( label检测到的事件, headers[类型, 开始时间, 结束时间, 置信度] ) with gr.Tab(原始信息): raw_json gr.JSON(label完整识别结果) # 示例音频 gr.Examples( examples[ [./examples/hello.wav, 英文问候], [./examples/weather.wav, 天气预报], [./examples/music_speech.wav, 音乐语音混合] ], inputs[input_audio], label试试示例音频 ) # 绑定事件 submit_btn.click( fnself.recognize, inputs[input_audio], outputs[output_text, emotion_chart, events_table, raw_json] ) clear_btn.click( fnlambda: [None, None, None, None], outputs[output_text, emotion_chart, events_table, raw_json] ) def recognize(self, audio_path): 处理识别请求 if audio_path is None: return 请先上传或录制音频, None, None, None try: # 调用识别函数 result recognize_speech(audio_path) # 准备情感图表数据 emotion_data { 情感类型: list(result[emotions].keys()), 置信度: list(result[emotions].values()) } # 准备事件表格数据 events_data [] for event in result[events]: events_data.append([ event[type], f{event[start]:.1f}s, f{event[end]:.1f}s, f{event[confidence]:.2%} ]) return ( result[text], emotion_data, events_data, result ) except Exception as e: error_msg f识别过程中出错: {str(e)} return error_msg, None, None, {error: error_msg} def launch(self, shareFalse): 启动应用 self.demo.launch(shareshare) # 启动应用 if __name__ __main__: # 先加载模型 session, _, _ load_onnx_model(./models/iic/SenseVoiceSmall/model.onnx) # 创建应用 app SpeechRecognitionApp(session) # 启动服务 print(正在启动语音识别服务...) print(访问 http://localhost:7860 使用界面) app.launch(shareFalse)Gradio界面的几个亮点多标签展示用标签页分别展示文字、情感、事件等不同信息示例音频提供示例让用户快速体验响应式设计自动适应不同屏幕大小错误处理友好的错误提示4. API文档自动生成实践4.1 设计清晰的API接口要让文档自动生成首先需要设计规范的API接口。我们基于刚才的识别服务设计一个RESTful风格的API。from fastapi import FastAPI, UploadFile, File, HTTPException from fastapi.responses import JSONResponse import uvicorn import json app FastAPI( titleSenseVoice语音识别API, description基于SenseVoice-Small模型的语音识别服务支持多语言识别、情感分析和声音事件检测, version1.0.0 ) class SpeechRecognitionAPI: def __init__(self, model_session): self.session model_session self.setup_routes() def setup_routes(self): 设置API路由 app.get(/) async def root(): API根目录返回服务信息 return { service: SenseVoice语音识别服务, version: 1.0.0, status: 运行中, endpoints: { /docs: API文档, /health: 健康检查, /api/v1/recognize: 语音识别接口, /api/v1/languages: 支持的语言列表 } } app.get(/health) async def health_check(): 健康检查接口 return {status: healthy, timestamp: datetime.now().isoformat()} app.get(/api/v1/languages) async def get_supported_languages(): 获取支持的语言列表 languages [ {code: zh, name: 中文, native_name: 中文}, {code: en, name: 英语, native_name: English}, {code: ja, name: 日语, native_name: 日本語}, {code: ko, name: 韩语, native_name: 한국어}, {code: yue, name: 粤语, native_name: 广东话}, # ... 更多语言 ] return {languages: languages, count: len(languages)} app.post(/api/v1/recognize) async def recognize_speech_api( audio_file: UploadFile File(..., description音频文件支持wav、mp3格式), language: str auto, enable_emotion: bool True, enable_events: bool True ): 语音识别接口 参数: audio_file: 上传的音频文件 language: 语言代码auto为自动检测 enable_emotion: 是否启用情感分析 enable_events: 是否启用声音事件检测 返回: 识别结果包括文字、情感、事件等信息 try: # 保存上传的临时文件 with tempfile.NamedTemporaryFile(deleteFalse, suffix.wav) as tmp_file: content await audio_file.read() tmp_file.write(content) tmp_path tmp_file.name # 调用识别函数 result recognize_speech(tmp_path) # 清理临时文件 os.unlink(tmp_path) # 根据参数过滤结果 filtered_result { text: result[text], audio_length: result[audio_length], timestamp: result[timestamp] } if enable_emotion: filtered_result[emotions] result[emotions] if enable_events: filtered_result[events] result[events] return JSONResponse(contentfiltered_result) except Exception as e: raise HTTPException(status_code500, detailf识别失败: {str(e)}) app.post(/api/v1/batch_recognize) async def batch_recognize(files: List[UploadFile] File(...)): 批量识别接口 results [] for file in files: try: result await recognize_speech_api(file) results.append({ filename: file.filename, result: result }) except Exception as e: results.append({ filename: file.filename, error: str(e) }) return {results: results} # 启动API服务 def start_api_server(host0.0.0.0, port8000): 启动FastAPI服务器 uvicorn.run(app, hosthost, portport) if __name__ __main__: print(启动语音识别API服务...) print(f文档地址: http://localhost:8000/docs) print(fAPI地址: http://localhost:8000) start_api_server()这个API设计考虑了实际使用场景健康检查监控服务状态语言查询让用户知道支持哪些语言单文件识别最常用的接口批量识别处理多个文件参数控制让用户选择是否需要情感、事件分析4.2 使用pydoc-markdown自动生成文档现在到了最关键的部分自动生成文档。我们使用pydoc-markdown这个工具它能从代码的docstring自动生成Markdown文档。首先确保我们的代码有完整的docstring# 在之前的代码中添加详细的docstring def recognize_speech(audio_path: str, language: str auto) - dict: 执行语音识别将音频转换为文字并分析情感和声音事件。 这个函数是语音识别服务的核心它完成了从音频文件到识别结果的完整流程。 参数: audio_path: 音频文件的路径支持wav、mp3等常见格式 language: 语言代码默认为auto自动检测 返回: 包含识别结果的字典结构如下: { text: 识别出的文字, audio_length: 音频长度秒, emotions: { positive: 0.7, neutral: 0.2, negative: 0.1 }, events: [ { type: speech, start: 0.0, end: 5.0, confidence: 0.95 } ] } 示例: result recognize_speech(test.wav) print(result[text]) 你好今天天气不错 异常: FileNotFoundError: 当音频文件不存在时 ValueError: 当音频格式不支持时 # ... 函数实现 ...然后创建pydoc-markdown的配置文件# pydoc-markdown.yml loaders: - type: python search_path: [.] packages: [.] processors: - type: filter skip_empty_modules: true - type: smart - type: crossref renderer: type: markdown descriptive_class_title: false add_method_class_prefix: false add_member_class_prefix: false signature_code_block: true render_toc: true render_module_header: true header_level_by_type: Module: 1 Class: 2 Method: 3 Function: 3 Data: 3 filename: API_DOCUMENTATION.md运行命令生成文档# 生成文档 pydoc-markdown -I . --config pydoc-markdown.yml # 或者直接指定要文档化的模块 pydoc-markdown -m speech_recognition_api --render-toc API_DOCS.md生成的文档会包含所有函数和类的说明参数和返回值的详细描述代码示例异常说明自动生成的目录4.3 集成到CI/CD流程为了让文档始终保持最新我们可以把文档生成集成到持续集成流程中。# .github/workflows/docs.yml name: Generate API Documentation on: push: branches: [ main ] paths: - **.py - !docs/** pull_request: branches: [ main ] jobs: generate-docs: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Set up Python uses: actions/setup-pythonv4 with: python-version: 3.9 - name: Install dependencies run: | pip install pydoc-markdown mkdocs mkdocs-material pip install -r requirements.txt - name: Generate API documentation run: | pydoc-markdown -m speech_recognition_api --render-toc docs/api.md pydoc-markdown -m audio_processor --render-toc docs/audio_processor.md pydoc-markdown -m model_loader --render-toc docs/model_loader.md - name: Build MkDocs site run: | mkdocs build - name: Deploy to GitHub Pages if: github.ref refs/heads/main uses: peaceiris/actions-gh-pagesv3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./site这样配置后每次代码更新都会自动重新生成API文档构建完整的文档网站部署到GitHub Pages4.4 文档质量检查与优化自动生成的文档虽然方便但有时需要人工优化。我们可以添加一些检查规则# docs_quality_check.py import re from pathlib import Path def check_docstring_completeness(file_path): 检查文件中函数的docstring完整性 with open(file_path, r, encodingutf-8) as f: content f.read() # 查找所有函数定义 function_pattern rdef\s(\w)\s*\([^)]*\)\s*: functions re.findall(function_pattern, content) issues [] for func_name in functions: # 查找对应的docstring docstring_pattern fdef {func_name}.*?:\s*(.*?) match re.search(docstring_pattern, content, re.DOTALL) if not match: issues.append(f函数 {func_name} 缺少docstring) else: docstring match.group(1) # 检查是否包含参数说明 if 参数: not in docstring: issues.append(f函数 {func_name} 的docstring缺少参数说明) # 检查是否包含返回值说明 if 返回: not in docstring: issues.append(f函数 {func_name} 的docstring缺少返回值说明) return issues def generate_docs_report(): 生成文档质量报告 python_files list(Path(.).glob(**/*.py)) print(文档质量检查报告) print( * 50) total_issues 0 for file_path in python_files: if file_path.name.startswith(test_): continue issues check_docstring_completeness(file_path) if issues: print(f\n{file_path}:) for issue in issues: print(f - {issue}) total_issues 1 print(f\n总计发现 {total_issues} 个文档问题) if total_issues 0: print(✅ 所有文档检查通过!) else: print(❌ 请修复上述文档问题) if __name__ __main__: generate_docs_report()运行这个检查脚本可以确保所有公共函数都有docstringdocstring包含必要的部分参数、返回值、示例等文档风格一致5. 总结与最佳实践5.1 本文要点回顾通过这篇文章我们完成了一个完整的语音识别服务API文档自动生成实践模型部署使用SenseVoice-Small ONNX量化模型部署简单、推理快速服务构建用Gradio构建交互式界面用FastAPI构建RESTful API文档自动化用pydoc-markdown从代码自动生成文档确保文档与代码同步流程集成将文档生成集成到CI/CD流程自动化维护SenseVoice-Small模型的几个突出优势多语言支持50多种语言满足国际化需求富文本识别不只是文字还能识别情感和声音事件高效推理ONNX量化版本速度快、资源占用少易于部署提供完整的服务部署方案5.2 自动生成文档的最佳实践根据我的经验做好API文档自动生成需要注意这些点1. 代码规范是基础为所有公共函数和类写完整的docstring使用一致的文档风格我推荐Google风格包含参数说明、返回值、示例和异常2. 选择合适的工具链pydoc-markdown从Python代码生成MarkdownMkDocs构建漂亮的文档网站GitHub Actions自动化文档生成和部署Sphinx更复杂的项目可以考虑3. 设计友好的APIRESTful设计原则清晰的错误处理版本管理如/api/v1/提供示例请求和响应4. 持续维护文档生成集成到CI/CD定期检查文档质量根据用户反馈优化文档5.3 实际应用建议如果你要在自己的项目中使用这个方案对于小团队或个人项目直接从本文的代码开始修改适应你的需求使用Gradio快速验证想法用pydoc-markdown生成基础文档对于企业级应用考虑使用Swagger/OpenAPI规范实现API版本管理添加身份验证和限流建立完整的文档审核流程性能优化方向使用ONNX Runtime的优化选项实现音频流式处理添加缓存机制考虑模型量化精度选择语音识别技术正在快速进步SenseVoice这样的模型让高质量语音识别变得更加易得。而好的文档能让你的技术成果更好地被他人使用。希望这个自动生成文档的实践能帮你节省时间把精力更多放在核心功能的开发上。记住代码会变需求会变但好的文档习惯和自动化流程能让你始终从容应对。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。