├── 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 |
--------------------------------------------------------------------------------