├── readme.md ├── 智能语音助手 ├── _snowboydetect.so ├── app.py ├── chatyuan.py ├── readme.md ├── requirements.txt ├── resources │ ├── common.res │ ├── ding.wav │ ├── music_list.csv │ └── xiaozhixiaozhi.pmdl ├── snowboy-detect-swig.cc ├── snowboy-detect-swig.i ├── snowboy-detect-swig.o ├── snowboydecoder.py ├── snowboydetect.py ├── tts.py └── whisper.py ├── 第1集 软件安装.md ├── 第2集 python.md ├── 第3集 文本分类.md └── 第4集 命名实体识别.md /readme.md: -------------------------------------------------------------------------------- 1 | 2 |

重生之我是 AI 打工人

3 | 4 | 5 |

6 | 7 | bilibili 8 |     9 | 10 | github 11 |     12 | 13 | huggingface 14 | 15 |

16 | 17 |
18 | 19 | [第1集 软件安装](%E7%AC%AC1%E9%9B%86%20%E8%BD%AF%E4%BB%B6%E5%AE%89%E8%A3%85.md) 20 | 21 | [第2集 python](%E7%AC%AC2%E9%9B%86%20python.md) 22 | 23 | [第3集 文本分类](%E7%AC%AC3%E9%9B%86%20%E6%96%87%E6%9C%AC%E5%88%86%E7%B1%BB.md) 24 | 25 | [第4集 命名实体识别](%E7%AC%AC4%E9%9B%86%20%E5%91%BD%E5%90%8D%E5%AE%9E%E4%BD%93%E8%AF%86%E5%88%AB.md) 26 | 27 | -------------------------------------------------------------------------------- /智能语音助手/_snowboydetect.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiansztiansz/voice-assistant/abfe44b365204f74dd1e779ea26166f9475febb4/智能语音助手/_snowboydetect.so -------------------------------------------------------------------------------- /智能语音助手/app.py: -------------------------------------------------------------------------------- 1 | import snowboydecoder 2 | import wave 3 | import sys 4 | import time 5 | import os 6 | from pyaudio import PyAudio, paInt16 7 | import time 8 | from pydub import AudioSegment 9 | from pydub.playback import play as play_music 10 | import urllib.request 11 | # import wget 12 | import pandas as pd 13 | from random import choice 14 | from chatyuan import ChatYuan 15 | from whisper import ASR 16 | from tts import TTS 17 | 18 | 19 | interrupted = False # snowboy监听唤醒结束标志 20 | endSnow = False # 程序结束标志 21 | framerate = 16000 # 采样率 22 | num_samples = 2000 # 采样点 23 | channels = 1 # 声道 24 | sampwidth = 2 # 采样宽度2bytes 25 | FILEPATH = "./resources/sst.wav" # 录制完成存放音频路径 26 | music_open = "./resources/ding.wav" # 唤醒系统打开语音 27 | os.close(sys.stderr.fileno()) # 去掉错误警告 28 | 29 | 30 | def interrupt_callback(): 31 | """ 32 | 监听唤醒 33 | """ 34 | global interrupted 35 | return interrupted 36 | 37 | 38 | def detected(): 39 | """ 40 | 唤醒成功 41 | """ 42 | play(music_open) 43 | global interrupted 44 | interrupted = True 45 | detector.terminate() 46 | 47 | 48 | def play(filename): 49 | """ 50 | 播放音频 51 | """ 52 | wf = wave.open(filename, "rb") # 打开audio.wav 53 | p = PyAudio() # 实例化 pyaudio 54 | # 打开流 55 | stream = p.open( 56 | format=p.get_format_from_width(wf.getsampwidth()), 57 | channels=wf.getnchannels(), 58 | rate=wf.getframerate(), 59 | output=True, 60 | ) 61 | data = wf.readframes(1024) 62 | while data != b"": 63 | data = wf.readframes(1024) 64 | stream.write(data) 65 | # 释放IO 66 | stream.stop_stream() 67 | stream.close() 68 | p.terminate() 69 | 70 | 71 | def save_wave_file(filepath, data): 72 | """ 73 | 存储文件 74 | """ 75 | wf = wave.open(filepath, "wb") 76 | wf.setnchannels(channels) 77 | wf.setsampwidth(sampwidth) 78 | wf.setframerate(framerate) 79 | wf.writeframes(b"".join(data)) 80 | wf.close() 81 | 82 | 83 | def my_record(): 84 | """ 85 | 录音 86 | """ 87 | pa = PyAudio() 88 | stream = pa.open( 89 | format=paInt16, 90 | channels=channels, 91 | rate=framerate, 92 | input=True, 93 | frames_per_buffer=num_samples, 94 | ) 95 | my_buf = [] 96 | t = time.time() 97 | print("正在录音...\n") 98 | while time.time() < t + 3: # 秒 99 | string_audio_data = stream.read(num_samples) 100 | my_buf.append(string_audio_data) 101 | save_wave_file(FILEPATH, my_buf) 102 | stream.close() 103 | 104 | 105 | def speech2text(): 106 | """ 107 | 音频转文字 108 | """ 109 | text = ASR.speech2text(FILEPATH) 110 | print("【语音识别结果】 %s\n" % (text)) 111 | return text 112 | 113 | 114 | def text2speech(text): 115 | """ 116 | 文字转音频,并实时播放 117 | """ 118 | TTS.text2speech(text) 119 | print("正在保存音频...\n") 120 | birdsound = AudioSegment.from_mp3("resources/tts.mp3") 121 | print("正在回答问题...\n") 122 | play_music(birdsound) 123 | 124 | 125 | def music(text): 126 | if text == "播放音乐" or text == "播放音樂": 127 | music_list = pd.read_csv("./resources/music_list.csv", usecols=["URL"]) 128 | LIST = [i for i in music_list.URL] 129 | url = choice(LIST) 130 | filename = "./resources/music.mp3" 131 | print("正在下载音乐....\n") 132 | urllib.request.urlretrieve(url, filename) 133 | # wget.download(url, filename) 134 | birdsound = AudioSegment.from_mp3(filename) 135 | print("正在播放音乐...\n") 136 | play_music(birdsound) 137 | else: 138 | result_text = ChatYuan.text2text(text) 139 | print("【机器人回复】 {}\n".format(result_text)) 140 | text2speech(result_text) 141 | 142 | 143 | if __name__ == "__main__": 144 | while endSnow == False: 145 | interrupted = False 146 | # 实例化snowboy,第一个参数就是唤醒识别模型位置 147 | detector = snowboydecoder.HotwordDetector( 148 | "./resources/xiaozhixiaozhi.pmdl", sensitivity=0.5 149 | ) 150 | print("等待唤醒...\n") 151 | # snowboy监听循环 152 | detector.start( 153 | detected_callback=detected, 154 | interrupt_check=interrupt_callback, 155 | sleep_time=0.03, 156 | ) 157 | my_record() # 唤醒成功开始录音 158 | text = speech2text() 159 | music(text) 160 | -------------------------------------------------------------------------------- /智能语音助手/chatyuan.py: -------------------------------------------------------------------------------- 1 | from transformers import T5Tokenizer, T5ForConditionalGeneration 2 | import torch 3 | 4 | device = torch.device("cuda") 5 | tokenizer = T5Tokenizer.from_pretrained("ClueAI/ChatYuan-large-v2") 6 | model = ( 7 | T5ForConditionalGeneration.from_pretrained("ClueAI/ChatYuan-large-v2") 8 | .half() 9 | .to(device) 10 | ) 11 | 12 | 13 | def preprocess(text): 14 | text = text.replace("\n", "\\n").replace("\t", "\\t") 15 | return text 16 | 17 | 18 | def postprocess(text): 19 | return text.replace("\\n", "\n").replace("\\t", "\t").replace("%20", " ") 20 | 21 | 22 | def answer(text, sample=True, top_p=0.9, temperature=0.7, context=""): 23 | """sample:是否抽样。生成任务,可以设置为True; 24 | top_p:0-1之间,生成的内容越多样""" 25 | text = f"{context}\n用户:{text}\n小元:" 26 | text = text.strip() 27 | text = preprocess(text) 28 | encoding = tokenizer( 29 | text=[text], truncation=True, padding=True, max_length=512, return_tensors="pt" 30 | ).to(device) 31 | if not sample: 32 | out = model.generate( 33 | **encoding, 34 | return_dict_in_generate=True, 35 | output_scores=False, 36 | max_new_tokens=512, 37 | num_beams=1, 38 | length_penalty=0.6, 39 | ) 40 | else: 41 | out = model.generate( 42 | **encoding, 43 | return_dict_in_generate=True, 44 | output_scores=False, 45 | max_new_tokens=512, 46 | do_sample=True, 47 | top_p=top_p, 48 | temperature=temperature, 49 | no_repeat_ngram_size=12, 50 | ) 51 | out_text = tokenizer.batch_decode(out["sequences"], skip_special_tokens=True) 52 | return postprocess(out_text[0]) 53 | 54 | 55 | class ChatYuan: 56 | def __init__(self) -> None: 57 | pass 58 | 59 | def text2text(input_text): 60 | output_text = answer(input_text) 61 | return output_text 62 | 63 | 64 | if __name__ == "__main__": 65 | text2text = ChatYuan.text2text("时间是否存在") 66 | print(text2text) 67 | -------------------------------------------------------------------------------- /智能语音助手/readme.md: -------------------------------------------------------------------------------- 1 | 2 |

智能语音助手

3 | 4 | 5 |

6 | 7 | bilibili 8 |     9 | 10 | github 11 |     12 | 13 | huggingface 14 | 15 |

16 | 17 | 18 |

基于 Snowboy、Whisper、ChatYuan 和 Azure TTS 的智能语音助手

19 | 20 | 21 | 22 |
23 | 24 | 25 | ## 如何使用 26 | 首先确保系统环境为 Ubuntu 20.04 及以上! 27 | 28 | 打开终端并克隆本仓库: 29 | ```bash 30 | git clone https://github.com/tiansztiansz/voice-assistant.git 31 | ``` 32 | 进入当前项目目录,然后安装依赖包: 33 | ```bash 34 | pip install -r requirements.txt 35 | ``` 36 | 接着运行主程序: 37 | ```bash 38 | python3 app.py 39 | ``` 40 | 41 | 当你看到程序显示“等待唤醒”字样时,则表明你已成功运行了程序! 42 | 43 | 接着尝试唤醒它吧,请说“小智小智”。当听到 ding 的语音提示时,请尝试说“广州在哪里”来向它提问。 44 | 45 | 或者当你想听歌的时候,请尝试说“播放音乐” 46 | 47 |
48 | 49 | 50 | ## 智能音箱实现 51 | 可在淘宝购买【带麦克风】的蓝牙音箱,连接电脑后即可实现智能音箱的效果。 52 | 53 | 54 | 55 |
56 | 57 | 58 | ## 待办事项 59 | - [ ] 修改唤醒时的语音 60 | - [ ] 语音转文字的提示 61 | - [ ] 文字转文字的提示 62 | - [ ] 文字转语音的提示 63 | 64 | 65 |
66 | 67 | 68 | 69 | ## 参考资料 70 | [训练唤醒模型](https://snowboy.hahack.com/) 71 | 72 | [唤醒后录制音频](https://www.passerma.com/article/54/#2.%E6%A0%91%E8%8E%93%E6%B4%BE%E5%BD%95%E5%88%B6%E5%A3%B0%E9%9F%B3%E4%B8%8A%E4%BC%A0%E7%99%BE%E5%BA%A6) 73 | 74 | [如何使用snowboy](https://www.bilibili.com/video/BV1pr4y1U7cE/?spm_id_from=333.1007.top_right_bar_window_default_collection.content.click&vd_source=06eafedcfca50f6eabb7b3d6b61ecfe3) 75 | 76 | [音乐如何下载](https://link.hhtjim.com/) 77 | 78 | 79 | [chatyuan](https://github.com/clue-ai/ChatYuan) 80 | 81 | [killed错误](https://www.cnblogs.com/tiansz/p/17134831.html) 82 | 83 | [kaggle-AI](https://github.com/tiansztiansz/kaggle-AI) 84 | 85 | 86 | -------------------------------------------------------------------------------- /智能语音助手/requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp==3.8.4 2 | aiosignal==1.3.1 3 | antlr4-python3-runtime==4.9.3 4 | anyio==3.6.2 5 | appdirs==1.4.4 6 | astor==0.8.1 7 | asttokens==2.2.1 8 | async-timeout==4.0.2 9 | attrs==22.2.0 10 | audioread==3.0.0 11 | av==10.0.0 12 | Babel==2.11.0 13 | backcall==0.2.0 14 | bce-python-sdk==0.8.79 15 | black==23.1.0 16 | blinker==1.4 17 | certifi==2022.12.7 18 | cffi==1.15.1 19 | charset-normalizer==3.0.1 20 | ci-sdr==0.0.2 21 | click==8.1.3 22 | colorama==0.4.6 23 | coloredlogs==15.0.1 24 | colorlog==6.7.0 25 | comm==0.1.2 26 | command-not-found==0.3 27 | ConfigArgParse==1.5.3 28 | contourpy==1.0.7 29 | cryptography==3.4.8 30 | ctc-segmentation==1.7.4 31 | ctranslate2==3.11.0 32 | cycler==0.11.0 33 | Cython==0.29.33 34 | datasets==2.9.0 35 | dbus-python==1.2.18 36 | debugpy==1.6.6 37 | decorator==5.1.1 38 | dill==0.3.4 39 | Distance==0.1.3 40 | distro==1.7.0 41 | distro-info===1.1build1 42 | editdistance==0.6.2 43 | einops==0.6.0 44 | espnet==202301 45 | espnet-model-zoo==0.1.7 46 | espnet-tts-frontend==0.0.3 47 | executing==1.2.0 48 | fast-bss-eval==0.1.3 49 | fastapi==0.92.0 50 | faster-whisper==0.4.1 51 | ffmpeg==1.4 52 | filelock==3.9.0 53 | Flask==2.2.3 54 | Flask-Babel==2.0.0 55 | flatbuffers==23.3.3 56 | fonttools==4.38.0 57 | frozenlist==1.3.3 58 | fsspec==2023.1.0 59 | future==0.18.3 60 | g2p-en==2.1.0 61 | gevent==22.10.2 62 | greenlet==2.0.2 63 | gyp==0.1 64 | h11==0.14.0 65 | h5py==3.8.0 66 | httplib2==0.20.2 67 | huggingface-hub==0.13.4 68 | humanfriendly==10.0 69 | hydra-core==1.3.1 70 | idna==3.4 71 | importlib-metadata==4.6.4 72 | inflect==6.0.2 73 | ipykernel==6.21.2 74 | ipython==8.11.0 75 | itsdangerous==2.1.2 76 | jaconv==0.3.4 77 | jamo==0.4.1 78 | jedi==0.18.2 79 | jeepney==0.7.1 80 | jieba==0.42.1 81 | Jinja2==3.1.2 82 | joblib==1.2.0 83 | jupyter_client==8.0.3 84 | jupyter_core==5.2.0 85 | kaldiio==2.17.2 86 | keyring==23.5.0 87 | kiwisolver==1.4.4 88 | launchpadlib==1.10.16 89 | lazr.restfulclient==0.14.4 90 | lazr.uri==1.0.6 91 | librosa==0.9.2 92 | llvmlite==0.39.1 93 | markdown-it-py==2.1.0 94 | MarkupSafe==2.1.2 95 | matplotlib==3.7.0 96 | matplotlib-inline==0.1.6 97 | mdurl==0.1.2 98 | more-itertools==8.10.0 99 | mpmath==1.3.0 100 | multidict==6.0.4 101 | multiprocess==0.70.12.2 102 | mypy-extensions==1.0.0 103 | nest-asyncio==1.5.6 104 | netifaces==0.11.0 105 | nltk==3.8.1 106 | numba==0.56.4 107 | numpy==1.23.5 108 | nvidia-cublas-cu11==11.10.3.66 109 | nvidia-cuda-nvrtc-cu11==11.7.99 110 | nvidia-cuda-runtime-cu11==11.7.99 111 | nvidia-cudnn-cu11==8.5.0.96 112 | oauthlib==3.2.0 113 | omegaconf==2.3.0 114 | onnxruntime==1.14.1 115 | opt-einsum==3.3.0 116 | packaging==23.0 117 | paddle-bfloat==0.1.7 118 | paddle2onnx==1.0.5 119 | paddlefsl==1.1.0 120 | paddlenlp==2.5.1 121 | paddlepaddle==2.4.2 122 | pandas==1.5.3 123 | parso==0.8.3 124 | pathspec==0.11.0 125 | pexpect==4.8.0 126 | pickleshare==0.7.5 127 | Pillow==9.4.0 128 | platformdirs==3.0.0 129 | pooch==1.6.0 130 | prompt-toolkit==3.0.38 131 | protobuf==3.20.0 132 | psutil==5.9.4 133 | ptyprocess==0.7.0 134 | pure-eval==0.2.2 135 | pyarrow==11.0.0 136 | PyAudio==0.2.13 137 | pycparser==2.21 138 | pycryptodome==3.17 139 | pydantic==1.10.5 140 | pydub==0.25.1 141 | Pygments==2.14.0 142 | PyGObject==3.42.1 143 | PyJWT==2.3.0 144 | pyparsing==2.4.7 145 | pypinyin==0.44.0 146 | python-apt==2.3.0+ubuntu2.1 147 | python-dateutil==2.8.2 148 | pytorch-wpe==0.0.1 149 | pytz==2022.7.1 150 | pyworld==0.3.2 151 | PyYAML==5.4.1 152 | pyzmq==25.0.0 153 | regex==2022.10.31 154 | requests==2.28.2 155 | resampy==0.4.2 156 | responses==0.18.0 157 | rich==13.3.1 158 | scikit-learn==1.2.1 159 | scipy==1.10.0 160 | SecretStorage==3.3.1 161 | sentencepiece==0.1.97 162 | seqeval==1.2.2 163 | six==1.16.0 164 | sniffio==1.3.0 165 | soundfile==0.12.1 166 | stack-data==0.6.2 167 | starlette==0.25.0 168 | sympy==1.11.1 169 | systemd-python==234 170 | threadpoolctl==3.1.0 171 | tokenizers==0.13.2 172 | tomli==2.0.1 173 | torch==1.13.1 174 | torch-complex==0.4.3 175 | torchaudio==0.13.1 176 | tornado==6.2 177 | tqdm==4.64.1 178 | traitlets==5.9.0 179 | transformers==4.26.1 180 | typeguard==2.13.3 181 | typer==0.7.0 182 | typing_extensions==4.5.0 183 | ubuntu-advantage-tools==27.12 184 | ubuntu-drivers-common==0.0.0 185 | ufw==0.36.1 186 | unattended-upgrades==0.1 187 | Unidecode==1.3.6 188 | urllib3==1.26.14 189 | uvicorn==0.20.0 190 | visualdl==2.4.2 191 | wadllib==1.3.6 192 | wcwidth==0.2.6 193 | websockets==10.2 194 | Werkzeug==2.2.3 195 | xkit==0.0.0 196 | xxhash==3.2.0 197 | yarl==1.8.2 198 | zipp==1.0.0 199 | zope.event==4.6 200 | zope.interface==5.5.2 201 | -------------------------------------------------------------------------------- /智能语音助手/resources/common.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiansztiansz/voice-assistant/abfe44b365204f74dd1e779ea26166f9475febb4/智能语音助手/resources/common.res -------------------------------------------------------------------------------- /智能语音助手/resources/ding.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiansztiansz/voice-assistant/abfe44b365204f74dd1e779ea26166f9475febb4/智能语音助手/resources/ding.wav -------------------------------------------------------------------------------- /智能语音助手/resources/music_list.csv: -------------------------------------------------------------------------------- 1 | URL, 2 | https://link.hhtjim.com/163/1897927507.mp3, 3 | https://link.hhtjim.com/163/65766.mp3, 4 | https://link.hhtjim.com/163/25906124.mp3, 5 | https://link.hhtjim.com/163/67467.mp3, 6 | https://link.hhtjim.com/163/30612793.mp3, 7 | https://link.hhtjim.com/163/1405283464.mp3, 8 | https://link.hhtjim.com/163/449818741.mp3, 9 | https://link.hhtjim.com/163/1412263970.mp3, 10 | https://link.hhtjim.com/163/1299550532.mp3, 11 | https://link.hhtjim.com/163/475479888.mp3, 12 | https://link.hhtjim.com/163/1807799505.mp3, 13 | https://link.hhtjim.com/163/441491828.mp3, 14 | https://link.hhtjim.com/163/208891.mp3, 15 | https://link.hhtjim.com/163/1959667345.mp3, 16 | https://link.hhtjim.com/163/1867217766.mp3, 17 | https://link.hhtjim.com/163/465921195.mp3, 18 | https://link.hhtjim.com/163/1387581250.mp3, -------------------------------------------------------------------------------- /智能语音助手/resources/xiaozhixiaozhi.pmdl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiansztiansz/voice-assistant/abfe44b365204f74dd1e779ea26166f9475febb4/智能语音助手/resources/xiaozhixiaozhi.pmdl -------------------------------------------------------------------------------- /智能语音助手/snowboy-detect-swig.i: -------------------------------------------------------------------------------- 1 | // swig/Python/snowboy-detect-swig.i 2 | 3 | // Copyright 2016 KITT.AI (author: Guoguo Chen) 4 | 5 | %module snowboydetect 6 | 7 | // Suppress SWIG warnings. 8 | #pragma SWIG nowarn=SWIGWARN_PARSE_NESTED_CLASS 9 | %include "std_string.i" 10 | 11 | %{ 12 | #include "include/snowboy-detect.h" 13 | %} 14 | 15 | %include "include/snowboy-detect.h" 16 | 17 | // below is Python 3 support, however, 18 | // adding it will generate wrong .so file 19 | // for Fedora 25 on ARMv7. So be sure to 20 | // comment them when you compile for 21 | // Fedora 25 on ARMv7. 22 | %begin %{ 23 | #define SWIG_PYTHON_STRICT_BYTE_CHAR 24 | %} 25 | -------------------------------------------------------------------------------- /智能语音助手/snowboy-detect-swig.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiansztiansz/voice-assistant/abfe44b365204f74dd1e779ea26166f9475febb4/智能语音助手/snowboy-detect-swig.o -------------------------------------------------------------------------------- /智能语音助手/snowboydecoder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import collections 4 | import pyaudio 5 | import snowboydetect 6 | import time 7 | import wave 8 | import os 9 | import logging 10 | from ctypes import * 11 | from contextlib import contextmanager 12 | 13 | logging.basicConfig() 14 | logger = logging.getLogger("snowboy") 15 | logger.setLevel(logging.INFO) 16 | TOP_DIR = os.path.dirname(os.path.abspath(__file__)) 17 | 18 | RESOURCE_FILE = os.path.join(TOP_DIR, "resources/common.res") 19 | DETECT_DING = os.path.join(TOP_DIR, "resources/ding.wav") 20 | 21 | 22 | def py_error_handler(filename, line, function, err, fmt): 23 | pass 24 | 25 | 26 | ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p) 27 | 28 | c_error_handler = ERROR_HANDLER_FUNC(py_error_handler) 29 | 30 | 31 | @contextmanager 32 | def no_alsa_error(): 33 | try: 34 | asound = cdll.LoadLibrary("libasound.so") 35 | asound.snd_lib_error_set_handler(c_error_handler) 36 | yield 37 | asound.snd_lib_error_set_handler(None) 38 | except: 39 | yield 40 | pass 41 | 42 | 43 | class RingBuffer(object): 44 | """用于保存来自 PortAudio 的音频的环形缓冲区""" 45 | 46 | def __init__(self, size=4096): 47 | self._buf = collections.deque(maxlen=size) 48 | 49 | def extend(self, data): 50 | """将数据添加到缓冲区的末尾""" 51 | self._buf.extend(data) 52 | 53 | def get(self): 54 | """从缓冲区的开头检索数据并清除它""" 55 | tmp = bytes(bytearray(self._buf)) 56 | self._buf.clear() 57 | return tmp 58 | 59 | 60 | def play_audio_file(fname=DETECT_DING): 61 | """关键词检测到时,播放该声音文件 62 | 63 | :param str fname: wav文件路径 64 | :return: None 65 | """ 66 | ding_wav = wave.open(fname, "rb") 67 | ding_data = ding_wav.readframes(ding_wav.getnframes()) 68 | with no_alsa_error(): 69 | audio = pyaudio.PyAudio() 70 | stream_out = audio.open( 71 | format=audio.get_format_from_width(ding_wav.getsampwidth()), 72 | channels=ding_wav.getnchannels(), 73 | rate=ding_wav.getframerate(), 74 | input=False, 75 | output=True, 76 | ) 77 | stream_out.start_stream() 78 | stream_out.write(ding_data) 79 | time.sleep(0.2) 80 | stream_out.stop_stream() 81 | stream_out.close() 82 | audio.terminate() 83 | 84 | 85 | class HotwordDetector(object): 86 | """Snowboy解码器检测是否为`decoder_model`指定的关键字存在于麦克风输入流中。 87 | 88 | :param decoder_model: 解码器模型文件路径,字符串或字符串列表 89 | :param resource: 资源文件路径。 90 | :param sensitivity: 解码器灵敏度,浮点数列表中的一个浮点数。 91 | 值越大解码器越敏感。 如果提供了一个空列表,则 92 | 将使用模型中的默认灵敏度。 93 | :param audio_gain: 将输入量乘以该系数。 94 | :param apply_frontend: 如果为真,则应用前端处理算法。 95 | """ 96 | 97 | def __init__( 98 | self, 99 | decoder_model, 100 | resource=RESOURCE_FILE, 101 | sensitivity=[], 102 | audio_gain=1, 103 | apply_frontend=False, 104 | ): 105 | tm = type(decoder_model) 106 | ts = type(sensitivity) 107 | if tm is not list: 108 | decoder_model = [decoder_model] 109 | if ts is not list: 110 | sensitivity = [sensitivity] 111 | model_str = ",".join(decoder_model) 112 | 113 | self.detector = snowboydetect.SnowboyDetect( 114 | resource_filename=resource.encode(), model_str=model_str.encode() 115 | ) 116 | self.detector.SetAudioGain(audio_gain) 117 | self.detector.ApplyFrontend(apply_frontend) 118 | self.num_hotwords = self.detector.NumHotwords() 119 | 120 | if len(decoder_model) > 1 and len(sensitivity) == 1: 121 | sensitivity = sensitivity * self.num_hotwords 122 | if len(sensitivity) != 0: 123 | assert self.num_hotwords == len(sensitivity), ( 124 | "number of hotwords in decoder_model (%d) and sensitivity " 125 | "(%d) does not match" % (self.num_hotwords, len(sensitivity)) 126 | ) 127 | sensitivity_str = ",".join([str(t) for t in sensitivity]) 128 | if len(sensitivity) != 0: 129 | self.detector.SetSensitivity(sensitivity_str.encode()) 130 | 131 | self.ring_buffer = RingBuffer( 132 | self.detector.NumChannels() * self.detector.SampleRate() * 5 133 | ) 134 | 135 | def start( 136 | self, 137 | detected_callback=play_audio_file, 138 | interrupt_check=lambda: False, 139 | sleep_time=0.03, 140 | audio_recorder_callback=None, 141 | silent_count_threshold=15, 142 | recording_timeout=100, 143 | ): 144 | """ 145 | 启动语音检测器。 对于每个 `sleep_time` 秒,它检查 146 | 用于触发关键字的音频缓冲区。 如果检测到,则调用 147 | `detected_callback`中对应的函数,可以是单个 148 | 函数(单个模型)或回调函数列表(多个楷模)。 149 | 每个循环它还会调用“interrupt_check”——如果它返回 150 | True,然后跳出循环并返回。 151 | 152 | :param detected_callback: 一个函数或函数列表。 的数量 153 | 项目必须匹配模型的数量 154 | `解码器模型`。 155 | :param interrupt_check: 如果主循环返回 True 的函数 156 | 需要停下来。 157 | :param float sleep_time: 每个循环等待的秒数。 158 | :param audio_recorder_callback: 如果指定,这将在之后调用 159 | 已经说出一个关键字,并且在 160 | 紧跟在关键字之后的短语 161 | 被记录下来。 该功能将是 162 | 传递了文件的名称 163 | 短语被记录下来。 164 | :param silent_count_threshold: 指示必须听到多长时间的静音 165 | 标记一个短语的结尾 166 | 被记录。 167 | :param recording_timeout: 限制录音的最大长度。 168 | :return: None 169 | """ 170 | self._running = True 171 | 172 | def audio_callback(in_data, frame_count, time_info, status): 173 | self.ring_buffer.extend(in_data) 174 | play_data = chr(0) * len(in_data) 175 | return play_data, pyaudio.paContinue 176 | 177 | with no_alsa_error(): 178 | self.audio = pyaudio.PyAudio() 179 | self.stream_in = self.audio.open( 180 | input=True, 181 | output=False, 182 | format=self.audio.get_format_from_width(self.detector.BitsPerSample() / 8), 183 | channels=self.detector.NumChannels(), 184 | rate=self.detector.SampleRate(), 185 | frames_per_buffer=2048, 186 | stream_callback=audio_callback, 187 | ) 188 | 189 | if interrupt_check(): 190 | logger.debug("detect voice return") 191 | return 192 | 193 | tc = type(detected_callback) 194 | if tc is not list: 195 | detected_callback = [detected_callback] 196 | if len(detected_callback) == 1 and self.num_hotwords > 1: 197 | detected_callback *= self.num_hotwords 198 | 199 | assert self.num_hotwords == len(detected_callback), ( 200 | "Error: hotwords in your models (%d) do not match the number of " 201 | "callbacks (%d)" % (self.num_hotwords, len(detected_callback)) 202 | ) 203 | 204 | logger.debug("detecting...") 205 | 206 | state = "PASSIVE" 207 | while self._running is True: 208 | if interrupt_check(): 209 | logger.debug("detect voice break") 210 | break 211 | data = self.ring_buffer.get() 212 | if len(data) == 0: 213 | time.sleep(sleep_time) 214 | continue 215 | 216 | status = self.detector.RunDetection(data) 217 | if status == -1: 218 | logger.warning("Error initializing streams or reading audio data") 219 | 220 | # 用于处理关键字后短语记录的小型状态机 221 | if state == "PASSIVE": 222 | if status > 0: # key word found 223 | self.recordedData = [] 224 | self.recordedData.append(data) 225 | silentCount = 0 226 | recordingCount = 0 227 | message = "Keyword " + str(status) + " detected at time: " 228 | message += time.strftime( 229 | "%Y-%m-%d %H:%M:%S", time.localtime(time.time()) 230 | ) 231 | logger.info(message) 232 | callback = detected_callback[status - 1] 233 | if callback is not None: 234 | callback() 235 | 236 | if audio_recorder_callback is not None: 237 | state = "ACTIVE" 238 | continue 239 | 240 | elif state == "ACTIVE": 241 | stopRecording = False 242 | if recordingCount > recording_timeout: 243 | stopRecording = True 244 | elif status == -2: # silence found 245 | if silentCount > silent_count_threshold: 246 | stopRecording = True 247 | else: 248 | silentCount = silentCount + 1 249 | elif status == 0: # voice found 250 | silentCount = 0 251 | 252 | if stopRecording == True: 253 | fname = self.saveMessage() 254 | audio_recorder_callback(fname) 255 | state = "PASSIVE" 256 | continue 257 | 258 | recordingCount = recordingCount + 1 259 | self.recordedData.append(data) 260 | 261 | logger.debug("finished.") 262 | 263 | def saveMessage(self): 264 | """ 265 | 将存储在 self.recordedData 中的消息保存到带时间戳的文件中。 266 | """ 267 | filename = "output" + str(int(time.time())) + ".wav" 268 | data = b"".join(self.recordedData) 269 | 270 | # 使用 wave 保存数据 271 | wf = wave.open(filename, "wb") 272 | wf.setnchannels(1) 273 | wf.setsampwidth( 274 | self.audio.get_sample_size( 275 | self.audio.get_format_from_width(self.detector.BitsPerSample() / 8) 276 | ) 277 | ) 278 | wf.setframerate(self.detector.SampleRate()) 279 | wf.writeframes(data) 280 | wf.close() 281 | logger.debug("finished saving: " + filename) 282 | return filename 283 | 284 | def terminate(self): 285 | """ 286 | 终止音频流。 用户可以再次调用start()进行检测。 287 | return: None 288 | """ 289 | self.stream_in.stop_stream() 290 | self.stream_in.close() 291 | self.audio.terminate() 292 | self._running = False 293 | -------------------------------------------------------------------------------- /智能语音助手/snowboydetect.py: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by SWIG (http://www.swig.org). 2 | # Version 3.0.10 3 | # 4 | # Do not make changes to this file unless you know what you are doing--modify 5 | # the SWIG interface file instead. 6 | 7 | 8 | from sys import version_info as _swig_python_version_info 9 | 10 | if _swig_python_version_info >= (2, 7, 0): 11 | 12 | def swig_import_helper(): 13 | import importlib 14 | 15 | pkg = __name__.rpartition(".")[0] 16 | mname = ".".join((pkg, "_snowboydetect")).lstrip(".") 17 | try: 18 | return importlib.import_module(mname) 19 | except ImportError: 20 | return importlib.import_module("_snowboydetect") 21 | 22 | _snowboydetect = swig_import_helper() 23 | del swig_import_helper 24 | elif _swig_python_version_info >= (2, 6, 0): 25 | 26 | def swig_import_helper(): 27 | from os.path import dirname 28 | import imp 29 | 30 | fp = None 31 | try: 32 | fp, pathname, description = imp.find_module( 33 | "_snowboydetect", [dirname(__file__)] 34 | ) 35 | except ImportError: 36 | import _snowboydetect 37 | 38 | return _snowboydetect 39 | if fp is not None: 40 | try: 41 | _mod = imp.load_module("_snowboydetect", fp, pathname, description) 42 | finally: 43 | fp.close() 44 | return _mod 45 | 46 | _snowboydetect = swig_import_helper() 47 | del swig_import_helper 48 | else: 49 | import _snowboydetect 50 | del _swig_python_version_info 51 | try: 52 | _swig_property = property 53 | except NameError: 54 | pass # Python < 2.2 doesn't have 'property'. 55 | 56 | try: 57 | import builtins as __builtin__ 58 | except ImportError: 59 | import __builtin__ 60 | 61 | 62 | def _swig_setattr_nondynamic(self, class_type, name, value, static=1): 63 | if name == "thisown": 64 | return self.this.own(value) 65 | if name == "this": 66 | if type(value).__name__ == "SwigPyObject": 67 | self.__dict__[name] = value 68 | return 69 | method = class_type.__swig_setmethods__.get(name, None) 70 | if method: 71 | return method(self, value) 72 | if not static: 73 | if _newclass: 74 | object.__setattr__(self, name, value) 75 | else: 76 | self.__dict__[name] = value 77 | else: 78 | raise AttributeError("You cannot add attributes to %s" % self) 79 | 80 | 81 | def _swig_setattr(self, class_type, name, value): 82 | return _swig_setattr_nondynamic(self, class_type, name, value, 0) 83 | 84 | 85 | def _swig_getattr(self, class_type, name): 86 | if name == "thisown": 87 | return self.this.own() 88 | method = class_type.__swig_getmethods__.get(name, None) 89 | if method: 90 | return method(self) 91 | raise AttributeError( 92 | "'%s' object has no attribute '%s'" % (class_type.__name__, name) 93 | ) 94 | 95 | 96 | def _swig_repr(self): 97 | try: 98 | strthis = "proxy of " + self.this.__repr__() 99 | except __builtin__.Exception: 100 | strthis = "" 101 | return "<%s.%s; %s >" % ( 102 | self.__class__.__module__, 103 | self.__class__.__name__, 104 | strthis, 105 | ) 106 | 107 | 108 | try: 109 | _object = object 110 | _newclass = 1 111 | except __builtin__.Exception: 112 | 113 | class _object: 114 | pass 115 | 116 | _newclass = 0 117 | 118 | 119 | class SnowboyDetect(_object): 120 | __swig_setmethods__ = {} 121 | __setattr__ = lambda self, name, value: _swig_setattr( 122 | self, SnowboyDetect, name, value 123 | ) 124 | __swig_getmethods__ = {} 125 | __getattr__ = lambda self, name: _swig_getattr(self, SnowboyDetect, name) 126 | __repr__ = _swig_repr 127 | 128 | def __init__(self, resource_filename, model_str): 129 | this = _snowboydetect.new_SnowboyDetect(resource_filename, model_str) 130 | try: 131 | self.this.append(this) 132 | except __builtin__.Exception: 133 | self.this = this 134 | 135 | def Reset(self): 136 | return _snowboydetect.SnowboyDetect_Reset(self) 137 | 138 | def RunDetection(self, *args): 139 | return _snowboydetect.SnowboyDetect_RunDetection(self, *args) 140 | 141 | def SetSensitivity(self, sensitivity_str): 142 | return _snowboydetect.SnowboyDetect_SetSensitivity(self, sensitivity_str) 143 | 144 | def SetHighSensitivity(self, high_sensitivity_str): 145 | return _snowboydetect.SnowboyDetect_SetHighSensitivity( 146 | self, high_sensitivity_str 147 | ) 148 | 149 | def GetSensitivity(self): 150 | return _snowboydetect.SnowboyDetect_GetSensitivity(self) 151 | 152 | def SetAudioGain(self, audio_gain): 153 | return _snowboydetect.SnowboyDetect_SetAudioGain(self, audio_gain) 154 | 155 | def UpdateModel(self): 156 | return _snowboydetect.SnowboyDetect_UpdateModel(self) 157 | 158 | def NumHotwords(self): 159 | return _snowboydetect.SnowboyDetect_NumHotwords(self) 160 | 161 | def ApplyFrontend(self, apply_frontend): 162 | return _snowboydetect.SnowboyDetect_ApplyFrontend(self, apply_frontend) 163 | 164 | def SampleRate(self): 165 | return _snowboydetect.SnowboyDetect_SampleRate(self) 166 | 167 | def NumChannels(self): 168 | return _snowboydetect.SnowboyDetect_NumChannels(self) 169 | 170 | def BitsPerSample(self): 171 | return _snowboydetect.SnowboyDetect_BitsPerSample(self) 172 | 173 | __swig_destroy__ = _snowboydetect.delete_SnowboyDetect 174 | __del__ = lambda self: None 175 | 176 | 177 | SnowboyDetect_swigregister = _snowboydetect.SnowboyDetect_swigregister 178 | SnowboyDetect_swigregister(SnowboyDetect) 179 | 180 | 181 | class SnowboyVad(_object): 182 | __swig_setmethods__ = {} 183 | __setattr__ = lambda self, name, value: _swig_setattr(self, SnowboyVad, name, value) 184 | __swig_getmethods__ = {} 185 | __getattr__ = lambda self, name: _swig_getattr(self, SnowboyVad, name) 186 | __repr__ = _swig_repr 187 | 188 | def __init__(self, resource_filename): 189 | this = _snowboydetect.new_SnowboyVad(resource_filename) 190 | try: 191 | self.this.append(this) 192 | except __builtin__.Exception: 193 | self.this = this 194 | 195 | def Reset(self): 196 | return _snowboydetect.SnowboyVad_Reset(self) 197 | 198 | def RunVad(self, *args): 199 | return _snowboydetect.SnowboyVad_RunVad(self, *args) 200 | 201 | def SetAudioGain(self, audio_gain): 202 | return _snowboydetect.SnowboyVad_SetAudioGain(self, audio_gain) 203 | 204 | def ApplyFrontend(self, apply_frontend): 205 | return _snowboydetect.SnowboyVad_ApplyFrontend(self, apply_frontend) 206 | 207 | def SampleRate(self): 208 | return _snowboydetect.SnowboyVad_SampleRate(self) 209 | 210 | def NumChannels(self): 211 | return _snowboydetect.SnowboyVad_NumChannels(self) 212 | 213 | def BitsPerSample(self): 214 | return _snowboydetect.SnowboyVad_BitsPerSample(self) 215 | 216 | __swig_destroy__ = _snowboydetect.delete_SnowboyVad 217 | __del__ = lambda self: None 218 | 219 | 220 | SnowboyVad_swigregister = _snowboydetect.SnowboyVad_swigregister 221 | SnowboyVad_swigregister(SnowboyVad) 222 | 223 | # This file is compatible with both classic and new-style classes. 224 | -------------------------------------------------------------------------------- /智能语音助手/tts.py: -------------------------------------------------------------------------------- 1 | import websockets 2 | import asyncio 3 | from datetime import datetime 4 | import re 5 | import uuid 6 | 7 | SSML_text = """ 8 | 9 | 10 | {} 11 | 12 | """ 13 | 14 | 15 | # 调整时间 16 | def hr_cr(hr): 17 | corrected = (hr - 1) % 24 18 | return str(corrected) 19 | 20 | 21 | # 在正确的位置添加零,即 22:1:5 -> 22:01:05 22 | def fr(input_string): 23 | corr = "" 24 | i = 2 - len(input_string) 25 | while i > 0: 26 | corr += "0" 27 | i -= 1 28 | return corr + input_string 29 | 30 | 31 | # 生成所有格式正确的 X-Timestamp 32 | def getXTime(): 33 | now = datetime.now() 34 | return ( 35 | fr(str(now.year)) 36 | + "-" 37 | + fr(str(now.month)) 38 | + "-" 39 | + fr(str(now.day)) 40 | + "T" 41 | + fr(hr_cr(int(now.hour))) 42 | + ":" 43 | + fr(str(now.minute)) 44 | + ":" 45 | + fr(str(now.second)) 46 | + "." 47 | + str(now.microsecond)[:3] 48 | + "Z" 49 | ) 50 | 51 | 52 | # 用于实际与 websocket 通信的异步函数 53 | async def transferMsTTSData(SSML_text, outputPath): 54 | req_id = uuid.uuid4().hex.upper() 55 | print(req_id) 56 | # TOKEN来源 https://github.com/rany2/edge-tts/blob/master/src/edge_tts/constants.py 57 | # 查看支持声音列表 https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list?trustedclienttoken=6A5AA1D4EAFF4E9FB37E23D68491D6F4 58 | TRUSTED_CLIENT_TOKEN = "6A5AA1D4EAFF4E9FB37E23D68491D6F4" 59 | WSS_URL = ( 60 | "wss://speech.platform.bing.com/consumer/speech/synthesize/" 61 | + "readaloud/edge/v1?TrustedClientToken=" 62 | + TRUSTED_CLIENT_TOKEN 63 | ) 64 | endpoint2 = f"{WSS_URL}&ConnectionId={req_id}" 65 | async with websockets.connect( 66 | endpoint2, 67 | extra_headers={ 68 | "Pragma": "no-cache", 69 | "Cache-Control": "no-cache", 70 | "Origin": "chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold", 71 | "Accept-Encoding": "gzip, deflate, br", 72 | "Accept-Language": "en-US,en;q=0.9", 73 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" 74 | " (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 Edg/91.0.864.41", 75 | }, 76 | ) as websocket: 77 | message_1 = ( 78 | f"X-Timestamp:{getXTime()}\r\n" 79 | "Content-Type:application/json; charset=utf-8\r\n" 80 | "Path:speech.config\r\n\r\n" 81 | '{"context":{"synthesis":{"audio":{"metadataoptions":{' 82 | '"sentenceBoundaryEnabled":false,"wordBoundaryEnabled":true},' 83 | '"outputFormat":"audio-24khz-48kbitrate-mono-mp3"' 84 | "}}}}\r\n" 85 | ) 86 | await websocket.send(message_1) 87 | 88 | message_2 = ( 89 | f"X-RequestId:{req_id}\r\n" 90 | "Content-Type:application/ssml+xml\r\n" 91 | f"X-Timestamp:{getXTime()}Z\r\n" # This is not a mistake, Microsoft Edge bug. 92 | "Path:ssml\r\n\r\n" 93 | f"{SSML_text}" 94 | ) 95 | await websocket.send(message_2) 96 | 97 | # 检查关闭连接消息 98 | end_resp_pat = re.compile("Path:turn.end") 99 | audio_stream = b"" 100 | while True: 101 | response = await websocket.recv() 102 | # print(response) 103 | # 确保消息没有告诉我们停止 104 | if re.search(end_resp_pat, str(response)) == None: 105 | # 检查我们的响应是文本数据还是音频字节 106 | if type(response) == type(bytes()): 107 | # Extract binary data 108 | try: 109 | needle = b"Path:audio\r\n" 110 | start_ind = response.find(needle) + len(needle) 111 | audio_stream += response[start_ind:] 112 | except: 113 | pass 114 | else: 115 | break 116 | with open(f"{outputPath}.mp3", "wb") as audio_out: 117 | audio_out.write(audio_stream) 118 | 119 | 120 | async def mainSeq(SSML_text, outputPath): 121 | await transferMsTTSData(SSML_text, outputPath) 122 | 123 | 124 | class TTS: 125 | def __init__(self) -> None: 126 | pass 127 | 128 | def text2speech(text): 129 | format_text = SSML_text.format(text) 130 | asyncio.get_event_loop().run_until_complete( 131 | mainSeq(format_text, "./resources/tts") 132 | ) 133 | 134 | 135 | if __name__ == "__main__": 136 | TTS.text2speech("你好") 137 | -------------------------------------------------------------------------------- /智能语音助手/whisper.py: -------------------------------------------------------------------------------- 1 | from faster_whisper import WhisperModel 2 | 3 | model_size = "large-v1" 4 | 5 | # 如果你的显卡显存大于 2g,可以设置 device="cuda" 6 | model = WhisperModel(model_size, device="cpu", compute_type="int8") 7 | 8 | 9 | class ASR: 10 | def __init__(self) -> None: 11 | pass 12 | 13 | def speech2text(audio_path): 14 | segments, info = model.transcribe(audio_path, beam_size=5) 15 | for segment in segments: 16 | return segment.text 17 | 18 | 19 | if __name__ == "__main__": 20 | audio_path = "./src/test.wav" 21 | text = ASR.speech2text(audio_path) 22 | print("【语音识别结果】 %s" % (text)) 23 | -------------------------------------------------------------------------------- /第1集 软件安装.md: -------------------------------------------------------------------------------- 1 | 2 |

Windows 常用软件

3 | 4 | 5 |

6 | 7 | bilibili 8 |     9 | 10 | github 11 |     12 | 13 | huggingface 14 | 15 |

16 | 17 |

以下软件仅适用于windows系统,其他系统请自行下载

18 | 19 | 20 |
21 | 22 | git国内镜像下载链接: 23 | ``` 24 | https://registry.npmmirror.com/binary.html?path=git-for-windows/ 25 | ``` 26 | 27 |
28 | 29 | Navicat数据库下载链接: 30 | ``` 31 | https://www.cnblogs.com/marchxd/p/15580739.html 32 | ``` 33 | 34 |
35 | 36 | 37 | pycharm专业版: 38 | ``` 39 | https://mp.weixin.qq.com/s/fLPIt5fueBnZvyVJFEoyNg 40 | ``` 41 | 42 |
43 | 44 | 45 | python: 46 | ``` 47 | https://www.python.org/downloads/ 48 | ``` 49 | 50 |
51 | 52 | 53 | 向日葵远程控制: 54 | ``` 55 | https://sunlogin.oray.com/download?categ=personal 56 | ``` 57 | 58 |
59 | 60 | 61 | vs code 最流行代码编辑器: 62 | ``` 63 | https://code.visualstudio.com/ 64 | ``` 65 | 66 |
67 | 68 | 69 | postman测试软件: 70 | ``` 71 | https://www.postman.com/downloads/ 72 | ``` 73 | 74 |
75 | 76 | 77 | finalshell服务器软件: 78 | ``` 79 | http://www.hostbuf.com/t/988.html 80 | ``` 81 | 82 |
83 | 84 | 85 | xmind思维导图软件: 86 | ``` 87 | https://xmind.cn/ 88 | ``` 89 | 90 |
91 | 92 | 93 | fastgithub稳定连接: 94 | ``` 95 | https://pan.baidu.com/s/1xjthoqMWrJkYjtooLFUqzw?pwd=1234 96 | ``` 97 | 98 |
99 | 100 | 101 | snipaste截图软件: 102 | ``` 103 | https://zh.snipaste.com/ 104 | ``` 105 | 106 |
107 | 108 | 109 | obs视频录制软件: 110 | ``` 111 | https://obsproject.com/zh-cn/download 112 | ``` 113 | 114 |
115 | 116 | 117 | winrar压缩软件: 118 | ``` 119 | https://www.winrar.com.cn/ 120 | ``` 121 | 122 |
123 | 124 | 必剪视频剪辑软件: 125 | ``` 126 | https://bcut.bilibili.cn/ 127 | ``` 128 | 129 |
130 | 131 | 腾讯会议: 132 | ``` 133 | https://meeting.tencent.com/download/ 134 | ``` 135 | 136 |
137 | 138 | 139 | wps文档处理软件: 140 | ``` 141 | https://platform.wps.cn/ 142 | ``` 143 | 144 |
145 | 146 | 147 | 微信: 148 | ``` 149 | https://pc.weixin.qq.com/ 150 | ``` 151 | 152 |
153 | 154 | 155 | 百度网盘: 156 | ``` 157 | http://pan.baidu.com/download#win 158 | ``` 159 | 160 |
161 | 162 | 163 | 钉钉: 164 | ``` 165 | https://page.dingtalk.com/wow/z/dingtalk/simple/ddhomedownload#/ 166 | ``` 167 | 168 |
169 | 170 | 171 | 迅雷: 172 | ``` 173 | https://dl.xunlei.com/ 174 | ``` 175 | 176 |
177 | 178 | 179 | 微信: 180 | ``` 181 | https://pc.weixin.qq.com/ 182 | ``` 183 | 184 |
185 | 186 | 187 | 企业微信: 188 | ``` 189 | https://work.weixin.qq.com/#indexDownload 190 | ``` 191 | 192 |
193 | 194 | 195 | drawio流程图绘制软件: 196 | ``` 197 | https://github.com/jgraph/drawio-desktop/releases 198 | ``` -------------------------------------------------------------------------------- /第2集 python.md: -------------------------------------------------------------------------------- 1 | 2 |

Python 语法

3 | 4 | 5 |

6 | 7 | bilibili 8 |     9 | 10 | github 11 |     12 | 13 | huggingface 14 | 15 |

16 | 17 |

要想成为合格的 AI 打工人,python 必不可少

18 | 19 | 20 |
-------------------------------------------------------------------------------- /第3集 文本分类.md: -------------------------------------------------------------------------------- 1 | 2 |

文本分类

3 | 4 | 5 |

6 | 7 | bilibili 8 |     9 | 10 | github 11 |     12 | 13 | huggingface 14 | 15 |

16 | 17 |

文本分类可用于意图识别、情感分析和新闻分类等多领域

18 | 19 | 20 |
-------------------------------------------------------------------------------- /第4集 命名实体识别.md: -------------------------------------------------------------------------------- 1 | 2 |

命名实体识别

3 | 4 | 5 |

6 | 7 | bilibili 8 |     9 | 10 | github 11 |     12 | 13 | huggingface 14 | 15 |

16 | 17 |

命名实体识别主要用于信息抽取,将文本中的重要信息提取出来

18 | 19 | 20 |
--------------------------------------------------------------------------------