nlp_feedback.cpp
Go to the documentation of this file.
1 #include "nlp/nlp_feedback.h"
2 #include <fstream>
3 #include <iostream>
4 #include <vector>
5 #include "common_config.h"
6 #include "file_operation.h"
7 #include "rapidjson/document.h"
8 #include "rapidjson/rapidjson.h"
10 #include "rapidjson/writer.h"
11 #include "tts/text_to_speech.h"
12 std::istream& operator>>(std::istream& str, CSVOperation& data)
13 {
14  data.readNextRow(str);
15  return str;
16 }
17 // 判断sub到的识别结果是否有效
18 bool ResultFeedback::resultIsValid(const std::string recog_result)
19 {
20  if (recog_result == "none_result")
21  {
22  return false;
23  }
24  else
25  {
26  recog_final_result_ = recog_result;
27  return true;
28  }
29 }
30 
31 bool ResultFeedback::isKeywordRepeated(std::string key_word)
32 {
33  for (int i = 0; i < (answer_table_.size() - 1); i++)
34  {
35  if (key_word == answer_table_[i][0])
36  {
37  return true;
38  }
39  }
40 
41  return false;
42 }
43 
45 {
47  answer_dictionary_[0] = "";
48 }
49 
50 // 根据交互模式配置文件检查识别出的关键词是否有对应的响应策略.
52 {
53  for (int i = 0; i < (answer_table_.size() - 1); i++)
54  {
56  {
57  for (int j = 0; j < 4; j++)
58  {
60  }
61  }
62  }
63 
64  if (answer_dictionary_[0] == "")
65  {
66  std::cout << "Can not find the answer corresponding to the keyword. Please check "
67  "the configuration file "
68  << std::endl;
69  return false;
70  }
71  return true;
72 }
73 
74 // 读取csv数据并存入answer_table_.
75 std::vector<std::vector<std::string>> ResultFeedback::readAnswerTable(std::string answer_config_file)
76 {
77  std::ifstream file(answer_config_file);
78  CSVOperation config_csv;
79  answer_table_ = config_csv.readAllCSV(file);
80  return answer_table_;
81 }
82 
83 // 返回一个反馈内容(包含语音和动作的反馈)
84 std::vector<std::string> ResultFeedback::answerContent()
85 {
86  return answer_dictionary_;
87 }
88 
89 // TODO and FIXME:
90 // 在xbot_sdk完成后,控制机器人可以直接调用xbot里的接口函数而非通过ROStopic控制
91 // 因为xbot_talker后续也需要构建sdk,所以nlp代码不应该包含ros相关。
92 // 为实现功能,将机器人控制的话题发布统一放在xbot_talker_ros里.
94 {
95  return std::stoi(answer_dictionary_[2]);
96 }
97 
98 // 监测是否需要机器人控制以及控制类型.
99 // FIXME:sdk完成后,此接口无需存在
101 {
102  return robotAction();
103 }
104 
105 // 此模式下应直接调用tts模块将answer_dictionary[1]里的answer文字转换成语音并播放
107 {
108  TextToSpeech text_to_speech;
109  bool ret;
110  ret = text_to_speech.audioConverter(tts_path_, answer_dictionary_[1].c_str());
111 }
112 
113 // 根据响应vector内的值调用不同的响应接口,如发布控制指令,播放音频文件等。
115 {
116  // csv 表格的第四列代表action_mode
118  int action_mode = std::stoi(answer_dictionary_[3]);
119  std::cout << "Action mode is: " << action_mode << std::endl;
120  std::cout << "Action mode is: " << answer_dictionary_[3] << std::endl;
121  switch (action_mode)
122  {
123  case PLAY_BEFORE_ACTION:
124  robotPlay();
125  robotAction();
126  break;
127 
128  case PLAY_AFTER_ACTION:
129  // TODO;
130  break;
131 
133  // TODO;
134  break;
135 
136  case PLAY_ONLY:
137  robotPlay();
138  break;
139  case ACTION_ONLY:
140  robotAction();
141  break;
142  default:
143  std::cout << "Error occurred in action_mode: " << action_mode << std::endl;
144  break;
145  }
146 }
147 
148 // 图灵请求参数格式为json,UTF-8编码.
149 void TuLingRobot::setAskJson(const std::string ask_str)
150 {
151  ask_json_ = "{\"reqType\": 0, \"perception\": {\"inputText\" : {\"text\": "
152  "\"" +
153  ask_str + "\"},"
154  "\"selfInfo\": {\"location\": {\"city\": \"北京\", \"province\": "
155  "\"\",\"street\": \"\"}}}, \"userInfo\": "
156  "{\"apiKey\":\"" +
157  tuling_key_ + "\", "
158  "\"userId\": \"0\"}}";
159 }
160 
161 size_t TuLingRobot::http_data_writer(void* data, size_t size, size_t nmemb, void* content)
162 {
163  long totalSize = size * nmemb;
164  std::string* symbolBuffer = (std::string*)content;
165  if (symbolBuffer)
166  {
167  symbolBuffer->append((char*)data, ((char*)data) + totalSize);
168  }
169  return totalSize;
170 }
171 
172 // HTTP POST请求图灵接口
174 {
175  int ret = 0;
176  CURL* pCurl = NULL;
177  CURLcode res;
178  curl_global_init(CURL_GLOBAL_ALL);
179  pCurl = curl_easy_init();
180  if (NULL != pCurl)
181  {
182  curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 2);
183  curl_easy_setopt(pCurl, CURLOPT_URL, tuling_url_.c_str());
184  curl_slist* plist = curl_slist_append(NULL, "Content-Type:application/json;charset=UTF-8");
185  curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, plist);
186  std::cout << "Ask Json String is:" << ask_json_ << std::endl;
187 
188  curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, ask_json_.c_str());
189 
190  curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, http_data_writer);
191  curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, (void*)&answer_json_);
192  res = curl_easy_perform(pCurl);
193  long responseCode = 0;
194  curl_easy_getinfo(pCurl, CURLINFO_RESPONSE_CODE, &responseCode);
195  if (res != CURLE_OK)
196  {
197  std::cout << "curl_easy_perform() failed:" << curl_easy_strerror(res) << std::endl;
198  exit(NLP_ERROR_CURL);
199  }
200  curl_easy_cleanup(pCurl);
201  }
202  curl_global_cleanup();
203  std::cout << "Tuling robot answer:" << answer_json_ << std::endl;
204 
205  return answer_json_;
206 }
207 
209 {
210  std::string result = answer_json_;
211  rapidjson::Document document;
212  document.Parse(answer_json_.c_str());
213 
214  if (document.HasParseError())
215  {
216  rapidjson::ParseErrorCode code = document.GetParseError();
217  std::cout << "JSON解析错误" << code << std::endl;
219  }
220 
221  if (document.HasMember("results"))
222  {
223  const rapidjson::Value& childValue = document["results"];
224 
225  for (rapidjson::SizeType i = 0; i < childValue.Size(); ++i)
226  {
227  const rapidjson::Value& resultUnit = childValue[i];
228  if (resultUnit.HasMember("values"))
229  {
230  const rapidjson::Value& contentWord = resultUnit["values"];
231 
232  const rapidjson::Value& text = contentWord["text"];
233  answer_text_ = text.GetString();
234  std::cout << answer_text_ << std::endl;
235  }
236  }
237  }
238  return answer_text_;
239 }
240 
242 {
243  ask_json_ = "";
244  answer_json_ = "";
245  answer_text_ = "";
246 }
std::istream & operator>>(std::istream &str, CSVOperation &data)
void setAskJson(const std::string ask_str)
设置图灵机器人对话请求参数.
std::string tts_path_
Definition: nlp_feedback.h:120
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:394
int actionDetect()
监测是否需要机器人控制以及控制类型..
std::vector< std::string > answerContent()
返回一个反馈内容(包含语音和动作的反馈).
static size_t http_data_writer(void *data, size_t size, size_t nmemb, void *content)
std::string callTulingApi()
请求图灵机器人接口,获取回答.
bool resultIsValid(const std::string recog_result)
判断语音识别结果是否为有效结果,若语音识别模块传来的结果!=none_result,则为有效.
std::string log_path
std::vector< std::string > answer_dictionary_
Definition: nlp_feedback.h:115
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Definition: document.h:2915
ParseErrorCode
Error code of parsing.
Definition: error.h:64
void keywordResponse(const std::string log_path)
根据响应vector内的值调用不同的响应接口,如发布控制指令,播放音频文件等.
GenericDocument< UTF8<> > Document
GenericDocument with UTF8 encoding.
Definition: document.h:3411
bool audioConverter(const std::string base_path, const char *src_text)
std::vector< std::vector< std::string > > readAllCSV(std::istream &str)
void uninitNLP()
一次处理结束后释放资源.
void readNextRow(std::istream &str)
std::string recog_final_result_
Definition: nlp_feedback.h:118
bool isKeywordRepeated(std::string key_word)
判断新加的关键词是否已被定义过.
common definitions and configuration
语音识别结果处理与机器人交互模块. TODO: 还需要添加版权、版本等信息
std::string textFromJson()
从图灵机器人的完整json回答中解析出最终需要的text回答.
void uninitTuling()
一次回答后释放资源.
bool keywordDetection()
根据交互模式answer_table_判断识别出的关键词是否有对应的响应策略. 若该关键词有对应的响应回复,存入响应向量answer_dictionary_(4).
std::vector< std::vector< std::string > > readAnswerTable(std::string answer_config_file)
读取离线对话库:defaultconfig/answer_dic.csv文件里的内容,存入answer_table_.
std::vector< std::vector< std::string > > answer_table_
Definition: nlp_feedback.h:116


xbot_talker
Author(s): wangxiaoyun
autogenerated on Sat Oct 10 2020 03:27:53