├── config.json
├── hotword
├── __init__.py
├── _snowboydetect.so
├── resources
│ ├── common.res
│ ├── ding.wav
│ ├── dong.wav
│ ├── models
│ │ ├── computer.umdl
│ │ ├── hey_extreme.umdl
│ │ ├── jarvis.umdl
│ │ ├── neoya.umdl
│ │ ├── smart_mirror.umdl
│ │ ├── snowboy.umdl
│ │ ├── subex.umdl
│ │ └── view_glass.umdl
│ ├── snowboy.raw
│ └── snowboy.wav
├── snowboydecoder.py
├── snowboydetect.py
└── try_again_detect.py
├── mouth
├── __init__.py
└── play.py
├── readme.md
├── stt_tts
├── __init__.py
├── baidu.py
└── baidu_tts_wav.py
├── temp
└── baidu_tts.py
└── tuling
├── __init__.py
├── baidu_robot.py
└── tuling123.py
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "key": "***************2b909949ba61"
3 | }
4 |
--------------------------------------------------------------------------------
/hotword/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/__init__.py
--------------------------------------------------------------------------------
/hotword/_snowboydetect.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/_snowboydetect.so
--------------------------------------------------------------------------------
/hotword/resources/common.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/common.res
--------------------------------------------------------------------------------
/hotword/resources/ding.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/ding.wav
--------------------------------------------------------------------------------
/hotword/resources/dong.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/dong.wav
--------------------------------------------------------------------------------
/hotword/resources/models/computer.umdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/models/computer.umdl
--------------------------------------------------------------------------------
/hotword/resources/models/hey_extreme.umdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/models/hey_extreme.umdl
--------------------------------------------------------------------------------
/hotword/resources/models/jarvis.umdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/models/jarvis.umdl
--------------------------------------------------------------------------------
/hotword/resources/models/neoya.umdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/models/neoya.umdl
--------------------------------------------------------------------------------
/hotword/resources/models/smart_mirror.umdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/models/smart_mirror.umdl
--------------------------------------------------------------------------------
/hotword/resources/models/snowboy.umdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/models/snowboy.umdl
--------------------------------------------------------------------------------
/hotword/resources/models/subex.umdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/models/subex.umdl
--------------------------------------------------------------------------------
/hotword/resources/models/view_glass.umdl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/models/view_glass.umdl
--------------------------------------------------------------------------------
/hotword/resources/snowboy.raw:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/snowboy.raw
--------------------------------------------------------------------------------
/hotword/resources/snowboy.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/hotword/resources/snowboy.wav
--------------------------------------------------------------------------------
/hotword/snowboydecoder.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import collections
4 | import pyaudio
5 | from . 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("try_again")
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 | DETECT_DONG = os.path.join(TOP_DIR, "resources/dong.wav")
21 |
22 | def py_error_handler(filename, line, function, err, fmt):
23 | pass
24 |
25 | ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)
26 |
27 | c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)
28 |
29 | @contextmanager
30 | def no_alsa_error():
31 | try:
32 | asound = cdll.LoadLibrary('libasound.so')
33 | asound.snd_lib_error_set_handler(c_error_handler)
34 | yield
35 | asound.snd_lib_error_set_handler(None)
36 | except:
37 | yield
38 | pass
39 |
40 | class RingBuffer(object):
41 | """Ring buffer to hold audio from PortAudio"""
42 |
43 | def __init__(self, size=4096):
44 | self._buf = collections.deque(maxlen=size)
45 |
46 | def extend(self, data):
47 | """Adds data to the end of buffer"""
48 | self._buf.extend(data)
49 |
50 | def get(self):
51 | """Retrieves data from the beginning of buffer and clears it"""
52 | tmp = bytes(bytearray(self._buf))
53 | self._buf.clear()
54 | return tmp
55 |
56 |
57 | def play_audio_file(fname=DETECT_DONG):
58 | """Simple callback function to play a wave file. By default it plays
59 | a Ding sound.
60 |
61 | :param str fname: wave file name
62 | :return: None
63 | """
64 | ding_wav = wave.open(fname, 'rb')
65 | ding_data = ding_wav.readframes(ding_wav.getnframes())
66 | with no_alsa_error():
67 | audio = pyaudio.PyAudio()
68 | stream_out = audio.open(
69 | format=audio.get_format_from_width(ding_wav.getsampwidth()),
70 | channels=ding_wav.getnchannels(),
71 | rate=ding_wav.getframerate(), input=False, output=True)
72 | stream_out.start_stream()
73 | stream_out.write(ding_data)
74 | time.sleep(0.2)
75 | stream_out.stop_stream()
76 | stream_out.close()
77 | audio.terminate()
78 |
79 |
80 | class HotwordDetector(object):
81 | """
82 | Snowboy decoder to detect whether a keyword specified by `decoder_model`
83 | exists in a microphone input stream.
84 |
85 | :param decoder_model: decoder model file path, a string or a list of strings
86 | :param resource: resource file path.
87 | :param sensitivity: decoder sensitivity, a float of a list of floats.
88 | The bigger the value, the more senstive the
89 | decoder. If an empty list is provided, then the
90 | default sensitivity in the model will be used.
91 | :param audio_gain: multiply input volume by this factor.
92 | :param apply_frontend: applies the frontend processing algorithm if True.
93 | """
94 |
95 | def __init__(self, decoder_model,
96 | resource=RESOURCE_FILE,
97 | sensitivity=[],
98 | audio_gain=1,
99 | apply_frontend=False):
100 |
101 | tm = type(decoder_model)
102 | ts = type(sensitivity)
103 | if tm is not list:
104 | decoder_model = [decoder_model]
105 | if ts is not list:
106 | sensitivity = [sensitivity]
107 | model_str = ",".join(decoder_model)
108 |
109 | self.recordedData = []
110 |
111 | self.detector = snowboydetect.SnowboyDetect(
112 | resource_filename=resource.encode(), model_str=model_str.encode())
113 | self.detector.SetAudioGain(audio_gain)
114 | self.detector.ApplyFrontend(apply_frontend)
115 | self.num_hotwords = self.detector.NumHotwords()
116 |
117 | if len(decoder_model) > 1 and len(sensitivity) == 1:
118 | sensitivity = sensitivity * self.num_hotwords
119 | if len(sensitivity) != 0:
120 | assert self.num_hotwords == len(sensitivity), \
121 | "number of hotwords in decoder_model (%d) and sensitivity " \
122 | "(%d) does not match" % (self.num_hotwords, len(sensitivity))
123 | sensitivity_str = ",".join([str(t) for t in sensitivity])
124 | if len(sensitivity) != 0:
125 | self.detector.SetSensitivity(sensitivity_str.encode())
126 |
127 | self.ring_buffer = RingBuffer(self.detector.NumChannels() * self.detector.SampleRate() * 5)
128 |
129 | def start(self, detected_callback=play_audio_file,
130 | interrupt_check=lambda: False,
131 | sleep_time=0.03,
132 | audio_recorder_callback=None,
133 | silent_count_threshold=10,
134 | recording_timeout=58):
135 | """
136 | Start the stt_tts detector. For every `sleep_time` second it checks the
137 | audio buffer for triggering keywords. If detected, then call
138 | corresponding function in `detected_callback`, which can be a single
139 | function (single model) or a list of callback functions (multiple
140 | models). Every loop it also calls `interrupt_check` -- if it returns
141 | True, then breaks from the loop and return.
142 |
143 | :param detected_callback: a function or list of functions. The number of
144 | items must match the number of models in
145 | `decoder_model`.
146 | :param interrupt_check: a function that returns True if the main loop
147 | needs to stop.
148 | :param float sleep_time: how much time in second every loop waits.
149 | :param audio_recorder_callback: if specified, this will be called after
150 | a keyword has been spoken and after the
151 | phrase immediately after the keyword has
152 | been recorded. The function will be
153 | passed the name of the file where the
154 | phrase was recorded.
155 | :param silent_count_threshold: indicates how long silence must be heard
156 | to mark the end of a phrase that is
157 | being recorded.
158 | :param recording_timeout: limits the maximum length of a recording.
159 | :return: None
160 | """
161 | self._running = True
162 |
163 | def audio_callback(in_data, frame_count, time_info, status):
164 | self.ring_buffer.extend(in_data)
165 | play_data = chr(0) * len(in_data)
166 | return play_data, pyaudio.paContinue
167 |
168 | with no_alsa_error():
169 | self.audio = pyaudio.PyAudio()
170 | self.stream_in = self.audio.open(
171 | input=True, output=False,
172 | format=self.audio.get_format_from_width(
173 | self.detector.BitsPerSample() / 8),
174 | channels=self.detector.NumChannels(),
175 | rate=self.detector.SampleRate(),
176 | frames_per_buffer=2048,
177 | stream_callback=audio_callback)
178 |
179 | if interrupt_check():
180 | logger.debug("detect stt_tts return")
181 | return
182 |
183 | tc = type(detected_callback)
184 | if tc is not list:
185 | detected_callback = [detected_callback]
186 | if len(detected_callback) == 1 and self.num_hotwords > 1:
187 | detected_callback *= self.num_hotwords
188 |
189 | assert self.num_hotwords == len(detected_callback), \
190 | "Error: hotwords in your models (%d) do not match the number of " \
191 | "callbacks (%d)" % (self.num_hotwords, len(detected_callback))
192 |
193 | logger.debug("detecting...")
194 |
195 | state = "PASSIVE"
196 | while self._running is True:
197 | if interrupt_check():
198 | logger.debug("detect stt_tts break")
199 | break
200 | data = self.ring_buffer.get()
201 | if len(data) == 0:
202 | time.sleep(sleep_time)
203 | continue
204 |
205 | status = self.detector.RunDetection(data)
206 | if status == -1:
207 | logger.warning("Error initializing streams or reading audio data")
208 |
209 | #small state machine to handle recording of phrase after keyword
210 | if state == "PASSIVE":
211 | if status > 0: # key word found
212 | self.recordedData = []
213 | # self.recordedData.append(data)
214 | silentCount = 0
215 | recordingCount = 0
216 | message = "Keyword " + str(status) + " detected at time: "
217 | message += time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
218 | logger.info(message)
219 | callback = detected_callback[status-1]
220 | if callback is not None:
221 | callback()
222 | if audio_recorder_callback is not None:
223 | state = "ACTIVE"
224 | continue
225 |
226 | elif state == "ACTIVE":
227 | # print('--------------------------------')
228 | stopRecording = False
229 | if recordingCount > recording_timeout:
230 | stopRecording = True
231 | elif status == -2: #silence found
232 | if silentCount > silent_count_threshold:
233 | stopRecording = True
234 | else:
235 | silentCount = silentCount + 1
236 | elif status == 0: #stt_tts found
237 | silentCount = 0
238 |
239 | if stopRecording == True:
240 | fname = self.saveMessage()
241 | flag_m = audio_recorder_callback(fname)
242 | if flag_m == 1:
243 | logger.info("进入循环对话。。。")
244 | print('recording audio...', end='', flush=True)
245 | self.recordedData = []
246 | silentCount = 0
247 | recordingCount = 0
248 | # time.sleep(1)
249 | self.ring_buffer.get()
250 | # 我们能发现这个清空缓存的方法比睡眠有效
251 | play_audio_file()
252 |
253 | else:
254 | state = "PASSIVE"
255 | continue
256 |
257 | recordingCount = recordingCount + 1
258 | self.recordedData.append(data)
259 |
260 | logger.debug("finished.")
261 |
262 | def saveMessage(self):
263 | """
264 | Save the message stored in self.recordedData to a timestamped file.
265 | """
266 | filename = '../temp/output' + str(int(time.time())) + '.wav'
267 | data = b''.join(self.recordedData)
268 |
269 | #use wave to save data
270 | wf = wave.open(filename, 'wb')
271 | wf.setnchannels(1)
272 | wf.setsampwidth(self.audio.get_sample_size(
273 | self.audio.get_format_from_width(
274 | self.detector.BitsPerSample() / 8)))
275 | wf.setframerate(self.detector.SampleRate())
276 | wf.writeframes(data)
277 | wf.close()
278 | logger.debug("finished saving: " + filename)
279 | return filename
280 |
281 | def terminate(self):
282 | """
283 | Terminate audio stream. Users can call start() again to detect.
284 | :return: None
285 | """
286 | self.stream_in.stop_stream()
287 | self.stream_in.close()
288 | self.audio.terminate()
289 | self._running = False
290 |
--------------------------------------------------------------------------------
/hotword/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 |
9 |
10 |
11 | from sys import version_info as _swig_python_version_info
12 | if _swig_python_version_info >= (2, 7, 0):
13 | def swig_import_helper():
14 | import importlib
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 | _snowboydetect = swig_import_helper()
22 | del swig_import_helper
23 | elif _swig_python_version_info >= (2, 6, 0):
24 | def swig_import_helper():
25 | from os.path import dirname
26 | import imp
27 | fp = None
28 | try:
29 | fp, pathname, description = imp.find_module('_snowboydetect', [dirname(__file__)])
30 | except ImportError:
31 | import _snowboydetect
32 | return _snowboydetect
33 | if fp is not None:
34 | try:
35 | _mod = imp.load_module('_snowboydetect', fp, pathname, description)
36 | finally:
37 | fp.close()
38 | return _mod
39 | _snowboydetect = swig_import_helper()
40 | del swig_import_helper
41 | else:
42 | import _snowboydetect
43 | del _swig_python_version_info
44 | try:
45 | _swig_property = property
46 | except NameError:
47 | pass # Python < 2.2 doesn't have 'property'.
48 |
49 | try:
50 | import builtins as __builtin__
51 | except ImportError:
52 | import builtins
53 |
54 | def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
55 | if (name == "thisown"):
56 | return self.this.own(value)
57 | if (name == "this"):
58 | if type(value).__name__ == 'SwigPyObject':
59 | self.__dict__[name] = value
60 | return
61 | method = class_type.__swig_setmethods__.get(name, None)
62 | if method:
63 | return method(self, value)
64 | if (not static):
65 | if _newclass:
66 | object.__setattr__(self, name, value)
67 | else:
68 | self.__dict__[name] = value
69 | else:
70 | raise AttributeError("You cannot add attributes to %s" % self)
71 |
72 |
73 | def _swig_setattr(self, class_type, name, value):
74 | return _swig_setattr_nondynamic(self, class_type, name, value, 0)
75 |
76 |
77 | def _swig_getattr(self, class_type, name):
78 | if (name == "thisown"):
79 | return self.this.own()
80 | method = class_type.__swig_getmethods__.get(name, None)
81 | if method:
82 | return method(self)
83 | raise AttributeError("'%s' object has no attribute '%s'" % (class_type.__name__, name))
84 |
85 |
86 | def _swig_repr(self):
87 | try:
88 | strthis = "proxy of " + self.this.__repr__()
89 | except __builtin__.Exception:
90 | strthis = ""
91 | return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
92 |
93 | try:
94 | _object = object
95 | _newclass = 1
96 | except __builtin__.Exception:
97 | class _object:
98 | pass
99 | _newclass = 0
100 |
101 | class SnowboyDetect(_object):
102 | __swig_setmethods__ = {}
103 | __setattr__ = lambda self, name, value: _swig_setattr(self, SnowboyDetect, name, value)
104 | __swig_getmethods__ = {}
105 | __getattr__ = lambda self, name: _swig_getattr(self, SnowboyDetect, name)
106 | __repr__ = _swig_repr
107 |
108 | def __init__(self, resource_filename, model_str):
109 | this = _snowboydetect.new_SnowboyDetect(resource_filename, model_str)
110 | try:
111 | self.this.append(this)
112 | except __builtin__.Exception:
113 | self.this = this
114 |
115 | def Reset(self):
116 | return _snowboydetect.SnowboyDetect_Reset(self)
117 |
118 | def RunDetection(self, *args):
119 | return _snowboydetect.SnowboyDetect_RunDetection(self, *args)
120 |
121 | def SetSensitivity(self, sensitivity_str):
122 | return _snowboydetect.SnowboyDetect_SetSensitivity(self, sensitivity_str)
123 |
124 | def SetHighSensitivity(self, high_sensitivity_str):
125 | return _snowboydetect.SnowboyDetect_SetHighSensitivity(self, high_sensitivity_str)
126 |
127 | def GetSensitivity(self):
128 | return _snowboydetect.SnowboyDetect_GetSensitivity(self)
129 |
130 | def SetAudioGain(self, audio_gain):
131 | return _snowboydetect.SnowboyDetect_SetAudioGain(self, audio_gain)
132 |
133 | def UpdateModel(self):
134 | return _snowboydetect.SnowboyDetect_UpdateModel(self)
135 |
136 | def NumHotwords(self):
137 | return _snowboydetect.SnowboyDetect_NumHotwords(self)
138 |
139 | def ApplyFrontend(self, apply_frontend):
140 | return _snowboydetect.SnowboyDetect_ApplyFrontend(self, apply_frontend)
141 |
142 | def SampleRate(self):
143 | return _snowboydetect.SnowboyDetect_SampleRate(self)
144 |
145 | def NumChannels(self):
146 | return _snowboydetect.SnowboyDetect_NumChannels(self)
147 |
148 | def BitsPerSample(self):
149 | return _snowboydetect.SnowboyDetect_BitsPerSample(self)
150 | __swig_destroy__ = _snowboydetect.delete_SnowboyDetect
151 | __del__ = lambda self: None
152 | SnowboyDetect_swigregister = _snowboydetect.SnowboyDetect_swigregister
153 | SnowboyDetect_swigregister(SnowboyDetect)
154 |
155 | class SnowboyVad(_object):
156 | __swig_setmethods__ = {}
157 | __setattr__ = lambda self, name, value: _swig_setattr(self, SnowboyVad, name, value)
158 | __swig_getmethods__ = {}
159 | __getattr__ = lambda self, name: _swig_getattr(self, SnowboyVad, name)
160 | __repr__ = _swig_repr
161 |
162 | def __init__(self, resource_filename):
163 | this = _snowboydetect.new_SnowboyVad(resource_filename)
164 | try:
165 | self.this.append(this)
166 | except __builtin__.Exception:
167 | self.this = this
168 |
169 | def Reset(self):
170 | return _snowboydetect.SnowboyVad_Reset(self)
171 |
172 | def RunVad(self, *args):
173 | return _snowboydetect.SnowboyVad_RunVad(self, *args)
174 |
175 | def SetAudioGain(self, audio_gain):
176 | return _snowboydetect.SnowboyVad_SetAudioGain(self, audio_gain)
177 |
178 | def ApplyFrontend(self, apply_frontend):
179 | return _snowboydetect.SnowboyVad_ApplyFrontend(self, apply_frontend)
180 |
181 | def SampleRate(self):
182 | return _snowboydetect.SnowboyVad_SampleRate(self)
183 |
184 | def NumChannels(self):
185 | return _snowboydetect.SnowboyVad_NumChannels(self)
186 |
187 | def BitsPerSample(self):
188 | return _snowboydetect.SnowboyVad_BitsPerSample(self)
189 | __swig_destroy__ = _snowboydetect.delete_SnowboyVad
190 | __del__ = lambda self: None
191 | SnowboyVad_swigregister = _snowboydetect.SnowboyVad_swigregister
192 | SnowboyVad_swigregister(SnowboyVad)
193 |
194 | # This file is compatible with both classic and new-style classes.
195 |
196 |
197 |
--------------------------------------------------------------------------------
/hotword/try_again_detect.py:
--------------------------------------------------------------------------------
1 | # import sys
2 | # sys.path.append("你的Ass的目录")
3 | # print(sys.path)
4 | # 以上代码仅需在树莓派环境部署时使用
5 |
6 | from hotword import snowboydecoder
7 | import signal
8 | import os
9 |
10 | from stt_tts.baidu import rec_speak_to_text
11 | from stt_tts.baidu_tts_wav import text_to_speak
12 | from tuling.tuling123 import get_response
13 | from tuling.baidu_robot import get_result
14 |
15 | from mouth.play import play_audio_file_playsound
16 | from mouth.play import play_audio_file_change_to_mp3
17 | from mouth.play import play_audio_file_pygame
18 | from mouth.play import play_wave_pyaudio
19 |
20 | interrupted = False
21 | session_id = ""
22 | stop_key_words = ['不聊了', '你歇着吧', '我走了', '我不想聊了']
23 |
24 |
25 | def audioRecorderCallback(fname):
26 | global session_id
27 | flag_m = 0
28 | print("converting audio to text")
29 | sentence = rec_speak_to_text(fname)
30 | if isinstance(sentence, int):
31 | if sentence == 1:
32 | robot_answer_fname = text_to_speak("网络错误,请稍后重试。")
33 | elif sentence == 0:
34 | if session_id == "":
35 | robot_answer_fname = text_to_speak("你喊我咋啥也不说呢。")
36 | else:
37 | robot_answer_fname = text_to_speak("你怎么突然不说话了呢,那我也不理你了。")
38 | session_id = ""
39 | else:
40 | flag_end = 0
41 | for one_stop_key_word in stop_key_words:
42 | if one_stop_key_word in sentence:
43 | flag_end = 1
44 | break
45 | if flag_end == 1:
46 | robot_answer_fname = text_to_speak("那拜拜咯!下回再聊,你早找我哦,我会想你的。")
47 | session_id = ""
48 | else:
49 | # robot_answer = get_response(sentence)
50 | robot_answer, session_id = get_result(sentence, session_id)
51 | robot_answer_fname = text_to_speak(robot_answer)
52 | flag_m = 1
53 | play_audio_file_playsound(robot_answer_fname)
54 | # print(fname)
55 | # print(robot_answer_fname)
56 | os.remove(fname)
57 | os.remove(robot_answer_fname)
58 |
59 | return flag_m
60 |
61 |
62 |
63 | def detectedCallback():
64 | snowboydecoder.play_audio_file()
65 | print('recording audio...', end='', flush=True)
66 |
67 | def signal_handler(signal, frame):
68 | global interrupted
69 | interrupted = True
70 |
71 |
72 | def interrupt_callback():
73 | global interrupted
74 | return interrupted
75 |
76 | # if len(sys.argv) == 1:
77 | # print("Error: need to specify model name")
78 | # print("Usage: python demo.py your.model")
79 | # sys.exit(-1)
80 |
81 | # model = sys.argv[1]
82 |
83 | model = "resources/models/smart_mirror.umdl"
84 |
85 | # capture SIGINT signal, e.g., Ctrl+C
86 | signal.signal(signal.SIGINT, signal_handler)
87 |
88 | detector = snowboydecoder.HotwordDetector(model, sensitivity=0.38)
89 | print('Listening... Press Ctrl+C to exit')
90 |
91 | # main loop
92 | detector.start(detected_callback=detectedCallback,
93 | audio_recorder_callback=audioRecorderCallback,
94 | interrupt_check=interrupt_callback,
95 | sleep_time=0.01)
96 |
97 | detector.terminate()
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/mouth/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/mouth/__init__.py
--------------------------------------------------------------------------------
/mouth/play.py:
--------------------------------------------------------------------------------
1 | from playsound import playsound
2 | from pydub import AudioSegment
3 | import pyaudio
4 | import wave
5 | import os
6 | import time
7 | import pygame
8 |
9 | CHUNK = 1024
10 |
11 |
12 | def play_audio_file_playsound(fname):
13 | playsound(fname)
14 |
15 |
16 | def play_audio_file_pygame(fname):
17 | pygame.mixer.init()
18 | pygame.mixer.music.load(fname)
19 | pygame.mixer.music.play()
20 | while pygame.mixer.music.get_busy() == True:
21 | continue
22 |
23 |
24 | def play_wave_pyaudio(filename):
25 | wf = wave.open(filename, 'rb')
26 |
27 | p = pyaudio.PyAudio()
28 | stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
29 | channels=wf.getnchannels(),
30 | rate=wf.getframerate(),
31 | output=True)
32 |
33 | data = wf.readframes(CHUNK)
34 |
35 | while data:
36 | stream.write(data)
37 | data = wf.readframes(CHUNK)
38 |
39 | stream.stop_stream()
40 | stream.close()
41 |
42 | p.terminate()
43 |
44 |
45 | def play_audio_file_change_to_mp3(fname):
46 | song = AudioSegment.from_mp3(fname)
47 | filename = '../temp/baidu' + str(int(time.time())) + '1.mp3'
48 | song.export(filename, format="wav")
49 | play_wave_pyaudio(filename)
50 | os.remove(filename)
51 |
52 |
53 | if __name__ == "__main__":
54 | play_audio_file_playsound("../temp/baidu1564470005.mp3")
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # 智能助手 Try Again
2 |
3 | ## 注意
4 | 尽量先看完整个介绍再动手,过些天会有相关的制作过程的教学
5 | 视频上传,目前还未处理完。
6 |
7 | [本项目制作的视频教程](https://www.bilibili.com/video/av61588252)
8 |
9 | ## 新的版本,可玩性更好一点
10 |
11 | dev分之
12 |
13 | ## 效果
14 |
15 | 请看视频教程第六集
16 |
17 | ###目前测试成功的运行平台
18 |
19 | 1. Ubuntu18.04
20 | 2. 树莓派3B+
21 | 3. 理论上支持大部分Linux系统
22 |
23 | ## 思路
24 | ### 唤醒模块
25 |
26 | 使用snowboy。
27 |
28 | 1. 唤醒模块一旦唤醒,暂时就不工作。直到该次唤醒工作结束后再
29 | 继续工作
30 | 2. 唤醒之后,我们检查网络状态
31 |
32 | ### 录音模块
33 |
34 | PyAudio
35 |
36 | 1. 10s之内没有人说话就自动关闭
37 |
38 | 系统继续进入等待唤醒状态
39 |
40 | 2. 10s之后如果唤醒人继续在讲话,那么我们需要继续录音
41 |
42 | 如果录音长度超过30s,我们就暂停录音,提示你也太啰嗦了
43 | 否则我们就正常的进入下一步
44 |
45 | 3. 录制完成的音频,存储成wav,流处理的方式直接进行stt处理
46 |
47 | 录音完成之后我们的录音模块暂时就停止工作
48 |
49 | ### 语音转文字stt
50 |
51 | Baidu stt
52 |
53 | 1. 将使用百度的python的stt
54 | 2. 返回文字,我们接收文字。
55 | 3. 如果我们返回文字是空的或者其他的错误,我们提示您能再说
56 | 一遍吗,我没听清楚(自动进入录音状态)。出错后跟出错
57 | 提示,做出相应的反馈,网络错误(进入待唤醒状态)
58 |
59 | ### 对话机器人
60 |
61 | tuling123.com的对话机器人
62 |
63 | 1. 我们免费对话机器人
64 | 2. 需要上传我们文字
65 | 3. 返回他的答案
66 | 4. 返回出错,处理方式同上
67 |
68 | ### 文字转语音模块tts
69 |
70 | 百度tts模块
71 |
72 | 1. 将对话机器人,返回文字转换成语音
73 | 2. 返回语音如果出错,我们处理同上
74 |
75 | ### 播放模块
76 |
77 | PyAudio
78 |
79 | 1. 将这个语音播放出来
80 |
81 | ### 主体控制模块
82 |
83 | 1. 当对话机器人回应唤醒人的时候,是否自动进入下一轮的录音
84 | 或者,是回应完之后就进入待唤醒状态。
85 | 2. 如果加入只能家具控制,那么我们需要两种方式来做
86 |
87 | a. 我们从这个stt返回后的语句中查询对应的关键字,然后
88 | 处理。
89 | b. 使用其他的唤醒词,Again Try。
90 |
91 | ### nlp的意图匹配模块
92 |
93 | 示例:
94 |
95 | 我说:帮我把灯打开
96 |
97 | 系统(明白是我要打开我的灯,而不是和它聊天):打开灯
98 |
99 | 我不想聊了
100 |
101 | 系统要退出循环聊天
102 |
103 |
104 |
105 |
106 | ## 开始手动配置
107 |
108 | ### 唤醒模块
109 |
110 | 1.配置snowboy的编译环境
111 |
112 | sudo apt-get install python-pyaudio python3-pyaudio sox
113 |
114 | sudo pip install pyaudio
115 |
116 | sudo pip3 install pyaudio
117 |
118 | cd 你的项目根目录/
119 |
120 | mkdir SBCompile
121 |
122 | wget http://downloads.sourceforge.net/swig/swig-3.0.10.tar.gz
123 |
124 | sudo apt-get install libpcre3 libpcre3-dev
125 |
126 | ls
127 |
128 | tar -zxvf swig-3.0.10.tar.gz
129 |
130 | cd swig-3.0.10/
131 |
132 | ./configure --prefix=/usr --without-clisp --without-maximum-compile-warnings && make
133 |
134 | sudo make install
135 |
136 | sudo install -v -m755 -d /usr/share/doc/swig-3.0.10
137 |
138 | sudo cp -v -R Doc/* /usr/share/doc/swig-3.0.10
139 |
140 | sudo apt-get install libatlas-base-dev
141 |
142 | cd ..
143 |
144 | mkdir rec_voice
145 |
146 | cd rec_voice/
147 |
148 | ls
149 |
150 | rec 1.wav
151 |
152 | ls
153 |
154 | 编译snowboy的准备工作结束
155 |
156 | cd ..
157 |
158 | git clone https://github.com/Kitt-AI/snowboy.git
159 |
160 | (这个是我没看明白,下面这句不用执行,把视频看下去就知道了)
161 | sudo apt-get install libmagic-dev libatlas-base-dev
162 |
163 | cd snowboy/
164 |
165 | cd swig/
166 |
167 | cd Python/
168 |
169 | make
170 |
171 | cd ..
172 |
173 | cd Python3/
174 |
175 | make
176 |
177 | exit
178 |
179 | ### 语音识别模块
180 |
181 | sudo pip3 install baidu-aip
182 |
183 | exit
184 |
185 | ### 对话模块
186 |
187 | 主要是代码
188 |
189 | ### 语音合成模块
190 |
191 | 与语音识别模块一直,主要是写几个代码
192 |
193 | ### 语音播放模块
194 |
195 | sudo pip3 install playsound
196 |
197 | ## 运行
198 |
199 | 需要更新stt_tts下的appid ak sk,理论上就可以在hotword下
200 | 的try_again_detect.py直接运行就行。实际上可能需要安装一些库
201 | 大家最好就是看看上面的过程。默认的唤醒词是smart mirror
202 |
203 | 本项目主要的目的在于给大家一个手动制作一个智能音箱的示例
204 | 如果真的想要实用,建议使用本文最后的
205 | [Wukong](https://github.com/wzpan/wukong-robot)项目
206 |
207 | 本项目还有对应的教学视频,目前还未对一些秘钥进行打码,所以暂未
208 | 上传,之后将免费给大家。
209 |
210 |
211 | ## 相关物
212 |
213 | [百度语音技术](https://ai.baidu.com/tech/speech/asr)
214 |
215 | [Snowboy](https://snowboy.kitt.ai)
216 |
217 | [Tuling123代码源](https://github.com/littlecodersh/EasierLife/blob/master/Plugins/Tuling/tuling.py)
218 |
219 | [Tuling123官网](http://www.turingapi.com/)
220 |
221 | [emotibot](http://botfactory.emotibot.com/)
222 |
223 | [Wukong](https://github.com/wzpan/wukong-robot)
224 |
225 | [百度的对话机器人](https://ai.baidu.com/docs#/UNIT-v2-service-API/top)
226 |
227 | ## 所有权声明
228 |
229 | 1. 本项目所有外部资源来源于网络,如有问题,请联系我删除。
230 | 2. 本项目仅可用于个人DIY使用,禁止用于商业目的。
231 | 3. 本项目使用后造成的后果,本人一概不负责任。
232 | 4. 本项目立项目标是在于告诉大家怎么去建立这样一个系统,如果只是想搭建一个基于树莓派
233 | 等的智能系统,建议使用文中提到的WuKong项目,该项目由腾讯工程师建立。远远强于我这个
234 | 本科生。
235 | 5. 关于捐赠,若果真的想给就在B站投个币吧,或者以下二维码
236 |
237 | 
--------------------------------------------------------------------------------
/stt_tts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/stt_tts/__init__.py
--------------------------------------------------------------------------------
/stt_tts/baidu.py:
--------------------------------------------------------------------------------
1 | from aip import AipSpeech
2 | import time
3 |
4 | """ 你的 APPID AK SK """
5 | APP_ID = '11684493'
6 | API_KEY = 'XYShi1grKEeqssWISnhr3EupVLLliChi'
7 | # SECRET_KEY = '***************************'
8 | SECRET_KEY = '18XEgGeDdWfHKZ8lUbsZLynRzQOtwpSN'
9 |
10 | # 由于公开的秘钥不好,所以不给
11 | client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
12 |
13 | # 读取文件
14 | def get_file_content(filePath):
15 | with open(filePath, 'rb') as fp:
16 | return fp.read()
17 |
18 | # 识别本地文件
19 | def rec_speak_to_text(fname):
20 | result = 0
21 | try:
22 | sentence = client.asr(get_file_content(fname), 'wav', 16000, {
23 | 'dev_pid': 1536,
24 | })
25 | print(sentence)
26 | if sentence['err_no'] == 0:
27 | result_list = sentence['result']
28 | for i, one in enumerate(result_list):
29 | if i != 0:
30 | result = result + "。" + one
31 | else:
32 | result = one
33 | except:
34 | return 1
35 | return result
36 |
37 |
38 | def text_to_speak(sentence):
39 | try:
40 | result = client.synthesis(sentence, 'zh', 4, {
41 | 'vol': 6,
42 | 'spd': 6,
43 | 'pit': 5,
44 | })
45 | filename = '../temp/baidu' + str(int(time.time())) + '.mp3'
46 | # 识别正确返回语音二进制 错误则返回dict 参照下面错误码
47 | if not isinstance(result, dict):
48 | with open(filename, 'wb') as f:
49 | f.write(result)
50 | except:
51 | return "../temp/net_error.mp3"
52 | return filename
53 |
54 |
55 | if __name__ == "__main__":
56 | # s = rec_speak_to_text("../temp/output1564468756.wav")
57 | # print(s)
58 | text_to_speak("网络错误,请稍后重试。")
--------------------------------------------------------------------------------
/stt_tts/baidu_tts_wav.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | import sys
3 | import json
4 | import time
5 |
6 | from urllib.request import urlopen
7 | from urllib.request import Request
8 | from urllib.error import URLError
9 | from urllib.parse import urlencode
10 | from urllib.parse import quote_plus
11 |
12 | API_KEY = '4E1BG9lTnlSeIf1NQFlrSq6h'
13 | SECRET_KEY = '544ca4657ba8002e3dea3ac2f5fdd241'
14 | ACCESS_TOKEN = '24.28cff53af4acb2cf08649af5802eac0e.2592000.1567086565.282335-16920155'
15 | # 发音人选择, 基础音库:0为度小美,1为度小宇,3为度逍遥,4为度丫丫,
16 | # 精品音库:5为度小娇,103为度米朵,106为度博文,110为度小童,111为度小萌,默认为度小美
17 | PER = 111
18 | # 语速,取值0-15,默认为5中语速
19 | SPD = 5
20 | # 音调,取值0-15,默认为5中语调
21 | PIT = 5
22 | # 音量,取值0-9,默认为5中音量
23 | VOL = 5
24 | # 下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
25 | AUE = 6
26 |
27 | FORMATS = {3: ".mp3", 4: ".pcm", 5: ".pcm", 6: ".wav"}
28 | FORMAT = FORMATS[AUE]
29 |
30 | CUID = "123456PYTHON"
31 |
32 | TTS_URL = 'http://tsn.baidu.com/text2audio'
33 |
34 |
35 | class DemoError(Exception):
36 | pass
37 |
38 |
39 | """ TOKEN start """
40 |
41 | TOKEN_URL = 'http://openapi.baidu.com/oauth/2.0/token'
42 | SCOPE = 'audio_tts_post' # 有此scope表示有tts能力,没有请在网页里勾选
43 |
44 |
45 | def fetch_token():
46 | print("fetch token begin")
47 | params = {'grant_type': 'client_credentials',
48 | 'client_id': API_KEY,
49 | 'client_secret': SECRET_KEY}
50 | post_data = urlencode(params)
51 | post_data = post_data.encode('utf-8')
52 | req = Request(TOKEN_URL, post_data)
53 | try:
54 | f = urlopen(req, timeout=5)
55 | result_str = f.read()
56 | except URLError as err:
57 | print('token http response http code : ' + str(err.code))
58 | result_str = err.read()
59 | result_str = result_str.decode()
60 |
61 | print(result_str)
62 | result = json.loads(result_str)
63 | print(result)
64 | if ('access_token' in result.keys() and 'scope' in result.keys()):
65 | if not SCOPE in result['scope'].split(' '):
66 | raise DemoError('scope is not correct')
67 | print('SUCCESS WITH TOKEN: %s ; EXPIRES IN SECONDS: %s' % (result['access_token'], result['expires_in']))
68 | return result['access_token']
69 | else:
70 | raise DemoError('MAYBE API_KEY or SECRET_KEY not correct: access_token or scope not found in token response')
71 | """ TOKEN end """
72 |
73 |
74 | def text_to_speak(text):
75 | token = ACCESS_TOKEN
76 | tex = quote_plus(text) # 此处TEXT需要两次urlencode
77 | print("AAAAAAAAAA" + tex)
78 | params = {'tok': token, 'tex': tex, 'per': PER, 'spd': SPD, 'pit': PIT, 'vol': VOL, 'aue': AUE, 'cuid': CUID,
79 | 'lan': 'zh', 'ctp': 1} # lan ctp 固定参数
80 |
81 | data = urlencode(params)
82 | print('test on Web Browser' + TTS_URL + '?' + data)
83 |
84 | req = Request(TTS_URL, data.encode('utf-8'))
85 | has_error = False
86 | try:
87 | f = urlopen(req)
88 | result_str = f.read()
89 |
90 | headers = dict((name.lower(), value) for name, value in f.headers.items())
91 |
92 | has_error = ('content-type' not in headers.keys() or headers['content-type'].find('audio/') < 0)
93 | except URLError as err:
94 | print('asr http response http code : ' + str(err.code))
95 | result_str = err.read()
96 | has_error = True
97 |
98 | save_filename = '../temp/baidu' + str(int(time.time())) + FORMAT
99 | save_file = "error.txt" if has_error else save_filename
100 | with open(save_file, 'wb') as of:
101 | of.write(result_str)
102 |
103 | if has_error:
104 | result_str = str(result_str, 'utf-8')
105 | print("tts api error:" + result_str)
106 |
107 | print("result saved as :" + save_file)
108 | return save_file
109 |
110 |
111 | if __name__ == '__main__':
112 | fname = text_to_speak("网络错误,请稍后重试。")
113 | print(fname)
--------------------------------------------------------------------------------
/temp/baidu_tts.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | import sys
3 | import json
4 |
5 | from urllib.request import urlopen
6 | from urllib.request import Request
7 | from urllib.error import URLError
8 | from urllib.parse import urlencode
9 | from urllib.parse import quote_plus
10 |
11 | API_KEY = '4E1BG9lTnlSeIf1NQFlrSq6h'
12 | SECRET_KEY = '544ca4657ba8002e3dea3ac2f5fdd241'
13 | ACCESS_TOKEN = '24.28cff53af4acb2cf08649af5802eac0e.2592000.1567086565.282335-16920155'
14 | # 发音人选择, 基础音库:0为度小美,1为度小宇,3为度逍遥,4为度丫丫,
15 | # 精品音库:5为度小娇,103为度米朵,106为度博文,110为度小童,111为度小萌,默认为度小美
16 | PER = 4
17 | # 语速,取值0-15,默认为5中语速
18 | SPD = 5
19 | # 音调,取值0-15,默认为5中语调
20 | PIT = 5
21 | # 音量,取值0-9,默认为5中音量
22 | VOL = 5
23 | # 下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
24 | AUE = 6
25 |
26 | FORMATS = {3: "mp3", 4: "pcm", 5: "pcm", 6: "wav"}
27 | FORMAT = FORMATS[AUE]
28 |
29 | CUID = "123456PYTHON"
30 |
31 | TTS_URL = 'http://tsn.baidu.com/text2audio'
32 |
33 |
34 | class DemoError(Exception):
35 | pass
36 |
37 |
38 | """ TOKEN start """
39 |
40 | TOKEN_URL = 'http://openapi.baidu.com/oauth/2.0/token'
41 | SCOPE = 'audio_tts_post' # 有此scope表示有tts能力,没有请在网页里勾选
42 |
43 |
44 | def fetch_token():
45 | print("fetch token begin")
46 | params = {'grant_type': 'client_credentials',
47 | 'client_id': API_KEY,
48 | 'client_secret': SECRET_KEY}
49 | post_data = urlencode(params)
50 | post_data = post_data.encode('utf-8')
51 | req = Request(TOKEN_URL, post_data)
52 | try:
53 | f = urlopen(req, timeout=5)
54 | result_str = f.read()
55 | except URLError as err:
56 | print('token http response http code : ' + str(err.code))
57 | result_str = err.read()
58 | result_str = result_str.decode()
59 |
60 | print(result_str)
61 | result = json.loads(result_str)
62 | print(result)
63 | if ('access_token' in result.keys() and 'scope' in result.keys()):
64 | if not SCOPE in result['scope'].split(' '):
65 | raise DemoError('scope is not correct')
66 | print('SUCCESS WITH TOKEN: %s ; EXPIRES IN SECONDS: %s' % (result['access_token'], result['expires_in']))
67 | return result['access_token']
68 | else:
69 | raise DemoError('MAYBE API_KEY or SECRET_KEY not correct: access_token or scope not found in token response')
70 | """ TOKEN end """
71 |
72 |
73 | def text_to_speak(text):
74 | token = ACCESS_TOKEN
75 | tex = quote_plus(text) # 此处TEXT需要两次urlencode
76 | print("AAAAAAAAAA" + tex)
77 | params = {'tok': token, 'tex': tex, 'per': PER, 'spd': SPD, 'pit': PIT, 'vol': VOL, 'aue': AUE, 'cuid': CUID,
78 | 'lan': 'zh', 'ctp': 1} # lan ctp 固定参数
79 |
80 | data = urlencode(params)
81 | print('test on Web Browser' + TTS_URL + '?' + data)
82 |
83 | req = Request(TTS_URL, data.encode('utf-8'))
84 | has_error = False
85 | try:
86 | f = urlopen(req)
87 | result_str = f.read()
88 |
89 | headers = dict((name.lower(), value) for name, value in f.headers.items())
90 |
91 | has_error = ('content-type' not in headers.keys() or headers['content-type'].find('audio/') < 0)
92 | except URLError as err:
93 | print('asr http response http code : ' + str(err.code))
94 | result_str = err.read()
95 | has_error = True
96 |
97 | save_file = "error.txt" if has_error else 'result.' + FORMAT
98 | with open(save_file, 'wb') as of:
99 | of.write(result_str)
100 |
101 | if has_error:
102 | result_str = str(result_str, 'utf-8')
103 | print("tts api error:" + result_str)
104 |
105 | print("result saved as :" + save_file)
106 | return save_file
107 |
108 |
109 | if __name__ == '__main__':
110 | fname = text_to_speak("你好。")
111 | print(fname)
--------------------------------------------------------------------------------
/tuling/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIOCW/EasyAss/fe2addd9561e3b5b33653636e4092c91b7959531/tuling/__init__.py
--------------------------------------------------------------------------------
/tuling/baidu_robot.py:
--------------------------------------------------------------------------------
1 | import urllib
2 | import ssl
3 | import json
4 | import random
5 |
6 | # # client_id 为官网获取的AK, client_secret 为官网获取的SK
7 | # host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=ak&client_secret=sk'
8 | # request = urllib.request.Request(host)
9 | # request.add_header('Content-Type', 'application/json; charset=UTF-8')
10 | # response = urllib.request.urlopen(request)
11 | # content = response.read()
12 | # if (content):
13 | # print(content)
14 | #
15 | # content.decode('utf-8')
16 | # content = json.loads(content)
17 | # print(content['access_token'])
18 |
19 | #-*- version: Python3.0 -*
20 | #-*- coding: UTF-8 -*
21 | import urllib.request
22 |
23 | headers = {'Content-Type':'application/json'}
24 | # access_token = content['access_token']
25 | access_token = '24.28cff53af4acb2cf08649af5802eac0e.2592000.1567086565.282335-16920155'
26 | print(access_token)
27 |
28 |
29 | def get_result(question, session_id):
30 | url = 'https://aip.baidubce.com/rpc/2.0/unit/service/chat?access_token=' + access_token
31 | post_data = '{"log_id":"try_again88888888",' \
32 | '"version":"2.0",' \
33 | '"service_id":"S20770",' \
34 | '"session_id":"' + session_id + '",' \
35 | '"request":{"query":"' + question + '","user_id":"88888"},' \
36 | '"dialog_state":{"contexts":{"SYS_REMEMBERED_SKILLS":["1057"]}}}'
37 | try:
38 | request = urllib.request.Request(url,data=post_data.encode('utf-8'),headers=headers)
39 | response = urllib.request.urlopen(request)
40 | content = response.read().decode("utf-8")
41 | content = json.loads(content)
42 | except:
43 | return "哦哦,我卡住了", None
44 | if content:
45 | # print(content)
46 | result = content['result']
47 | # print(result)
48 | session_id = result['session_id']
49 | # print(session_id)
50 | response = result['response_list'][0]
51 | # print(response)
52 | action_list = response['action_list']
53 | l = len(action_list)
54 | # print(l)
55 | r_int = random.randint(0, l - 1)
56 | # print(r_int)
57 | action = action_list[r_int]
58 | # print(action)
59 | say = action['say']
60 | print(say)
61 | return say, session_id
62 | return "哦哦,我卡住了", None
63 |
64 |
65 | "{'result': " \
66 | "{" \
67 | "'version': '2.0'," \
68 | " 'timestamp': '2019-07-30 22:00:25.715'," \
69 | " 'service_id': 'S20770', " \
70 | "'log_id': 'try_again88888888'," \
71 | " 'session_id': 'service-session-id-1564495225715-0504cdd87fa54fad91e29012428bf5b4'," \
72 | " 'interaction_id': 'service-interactive-id-1564495225715-e69daa6019654b8c862a35dfc87d0123', " \
73 | "'response_list': " \
74 | "[{'status': 0," \
75 | " 'msg': 'ok'," \
76 | " 'origin': '71559'," \
77 | " 'schema': {'intent_confidence': 1.0, 'intent': 'BUILT_CHAT'}," \
78 | "'action_list':" \
79 | " [" \
80 | "{'action_id': '','refine_detail': {},'confidence': 1.0, 'custom_reply': '', 'say': '你好,想聊什么呢。~','type': 'chat'}, " \
81 | "{'action_id': '', 'refine_detail': {}, 'confidence': 1.0, 'custom_reply': '', 'say': '有礼貌的好孩子', 'type': 'chat'}, " \
82 | "{'action_id': '', 'refine_detail': {}, 'confidence': 1.0, 'custom_reply': '', 'say': '你好。咱们聊一会呀', 'type': 'chat'}" \
83 | "]," \
84 | " 'qu_res': {}}" \
85 | "], " \
86 | "'dialog_state': " \
87 | "{'contexts': {'SYS_REMEMBERED_SKILLS': []}, 'skill_states': {}}}, 'error_code': 0}"
88 |
89 |
90 | if __name__ == "__main__":
91 | response, session_id = get_result("现在几点了", "")
92 | print(response, session_id)
--------------------------------------------------------------------------------
/tuling/tuling123.py:
--------------------------------------------------------------------------------
1 | #coding=utf8
2 | import sys, os
3 | import requests, json
4 |
5 | try:
6 | with open('../config.json') as f: key = json.loads(f.read())['key']
7 | except:
8 | key = '' # if key is '', get_response will return None
9 | # raise Exception('There is something wrong with the format of you plugin/config/tuling.json')
10 |
11 | def get_response(msg, storageClass = None, userName = None, userid = 'ItChat'):
12 | print('tuling:' + msg)
13 | url = 'http://www.tuling123.com/openapi/api'
14 | payloads = {
15 | 'key': key,
16 | 'info': msg,
17 | 'userid': userid,
18 | }
19 | try:
20 | r = requests.post(url, data = json.dumps(payloads)).json()
21 | print(r)
22 | except:
23 | return
24 | if not r['code'] in (100000, 200000, 302000, 308000, 313000, 314000):
25 | return "对不起,我脑袋卡住了,回答不上来。"
26 | if r['code'] == 100000: # 文本类
27 | return '\n'.join([r['text'].replace('
','\n')])
28 | elif r['code'] == 200000: # 链接类
29 | return '\n'.join([r['text'].replace('
','\n'), r['url']])
30 | elif r['code'] == 302000: # 新闻类
31 | l = [r['text'].replace('
','\n')]
32 | for n in r['list']: l.append('%s - %s'%(n['article'], n['detailurl']))
33 | return '\n'.join(l)
34 | elif r['code'] == 308000: # 菜谱类
35 | l = [r['text'].replace('
','\n')]
36 | for n in r['list']: l.append('%s - %s'%(n['name'], n['detailurl']))
37 | return '\n'.join(l)
38 | elif r['code'] == 313000: # 儿歌类
39 | return '\n'.join([r['text'].replace('
','\n')])
40 | elif r['code'] == 314000: # 诗词类
41 | return '\n'.join([r['text'].replace('
','\n')])
42 |
43 | if __name__ == '__main__':
44 | try:
45 | ipt = input
46 | except:
47 | ipt = lambda: input('>')
48 | while True:
49 | a = ipt()
50 | print(get_response(a, 'ItChat'))
--------------------------------------------------------------------------------