在实际生产生活中,我们经常会遇到别人问我们问题,而且这个问题是常见的,那么我们就会感到很烦躁:为啥总有人问相似的问题?再仔细冷静一下:我们可不可以做一个机器人,他可以自动回答一些问题?今天本文,就通过简单的方法,在SCF上部署一个问答机器人/智能客服,来为各位有需求的小伙伴,解决实际问题,当然,这篇文章也算是抛砖引玉。一方面,扩展一下大家使用SCF的思路,另一方面温故一下如何打包的方法,最后也尝试使用新的触发方法:云API触发。
准备阶段
首先,我们要有一个数据库,存储我们的问答系统,我这里在腾讯云购买一个云数据库(MySQL),并建立表和字段等信息:
并且插入几个问题:
然后,通过本地编写代码,进行测试:
读取数据库:
代码语言:javascript复制def getAllDataFromDB(connection):
cursor = connection.cursor()
cursor.execute("""SELECT * FROM robot""")
results = cursor.fetchall()
data = [eve['question'] for eve in results]
return data
connection = pymysql.connect(host="",
user="",
password="",
port=int(),
db="MyScfTest",
charset='utf8',
cursorclass=pymysql.cursors.DictCursor)
questions = getAllDataFromDB(connection)
connection.close()
使用gensim库,利用TFIDF算法来进行文本相似度计算,jieba进行分词,整理为指定格式->gensim库将要对比的文档通过doc2bow转化为稀疏向量->再通过models中的tf-idf将语料库进行处理->特征值和稀疏矩阵相似度建立索引->最后的到相似结果。
代码如下:
代码语言:javascript复制def getAnswerList(sentence,questions,count=4):
documents = []
for eve_sentence in questions:
tempData = " ".join(jieba.cut(eve_sentence))
documents.append(tempData)
texts=[[word for word in document.split()] for document in documents]
frequency=defaultdict(int)
for text in texts:
for word in text:
frequency[word] =1
dictionary=corpora.Dictionary(texts)
new_xs=dictionary.doc2bow(jieba.cut(sentence))
corpus=[dictionary.doc2bow(text)for text in texts]
tfidf=models.TfidfModel(corpus)
featurenum=len(dictionary.token2id.keys())
sim=similarities.SparseMatrixSimilarity(tfidf[corpus],num_features=featurenum)[tfidf[new_xs]]
tempList = [(sim[i], questions[i]) for i in range(1,len(questions))]
tempList.sort(key=lambda x:x[0],reverse=True)
if len(tempList) >= count:
return tempList[0:count]
else:
return tempList
这里面的思路是,进行相似度获取,然后根据相似度,进行排序,相似度最高的在前面,最低的放到最后。然后传入的sentence是提出的问题,传入的questions是问题列表,count是返回相似度最高的问题的个数。假如说,数据库有20个问题,那么我在进行了问题的相似度分析之后,会得到一个相似度大小的列表,我对列表排序之后,选择前count个问题返回给用户。
完整代码:
代码语言:javascript复制import jieba,pymysql
from gensim import corpora,models,similarities
from collections import defaultdict
def getAllDataFromDB(connection):
cursor = connection.cursor()
cursor.execute("""SELECT * FROM robot""")
results = cursor.fetchall()
data = [eve['question'] for eve in results]
return data
def getDataFromDB(connection,question):
cursor = connection.cursor()
cursor.execute("""SELECT * FROM robot WHERE question = '%s'"""%question)
results = cursor.fetchall()
data = [(eve['question'],eve['answer']) for eve in results]
return data
def getAnswerList(sentence,questions,count=4):
documents = []
for eve_sentence in questions:
tempData = " ".join(jieba.cut(eve_sentence))
documents.append(tempData)
texts=[[word for word in document.split()] for document in documents]
frequency=defaultdict(int)
for text in texts:
for word in text:
frequency[word] =1
dictionary=corpora.Dictionary(texts)
new_xs=dictionary.doc2bow(jieba.cut(sentence))
corpus=[dictionary.doc2bow(text)for text in texts]
tfidf=models.TfidfModel(corpus)
featurenum=len(dictionary.token2id.keys())
sim=similarities.SparseMatrixSimilarity(tfidf[corpus],num_features=featurenum)[tfidf[new_xs]]
tempList = [(sim[i], questions[i]) for i in range(1,len(questions))]
tempList.sort(key=lambda x:x[0],reverse=True)
if len(tempList) >= count:
return tempList[0:count]
else:
return tempList
def putQuestion(question):
connection = pymysql.connect(host="",
user="",
password="",
port=int(),
db="MyScfTest",
charset='utf8',
cursorclass=pymysql.cursors.DictCursor)
questions = getAllDataFromDB(connection)
answers = [getDataFromDB(connection,eve[1]) for eve in getAnswerList(question,questions,count=2)]
connection.close()
return answers
sentence = "怎么触发SCF?"
print(putQuestion(sentence))
测试结果:
可以看到,在问题列表:
我们一共有5个问题,这5个问题,和"怎么触发SCF?"相似度最高的问题前两个是:那些事件可以触发SCF函数以及SCF支持那些语言。可以看出,得到的结果是类似的。
这个项目在实际生产中,可以是这样:
你问客服机器人一个问题,机器人给你一个回答,然后下面会说:更多相似问题:巴拉巴拉一堆。
上SCF阶段
函数进行打包,这里要记住,一定要在SCF一样的环境下打包才可以:
CentOS Python3.6
具体打包方法,可以参考文章:https://cloud.tencent.com/developer/article/1443081
打包之后,数据上传:
这里要说明的是,由于函数上传有大小限制,本函数上传了COS,通过COS加载到SCF中,并设置了超时时间为300s:
简单测试,运行结果如下:
代码语言:javascript复制def main_handler(event, context):
sentence = "怎么触发SCF?"
return putQuestion(sentence)
对main_handler进行修改:
首先定义测试模板:
然后修改:
代码语言:javascript复制def main_handler(event, context):
sentence = context["question"]
return putQuestion(sentence)
完整代码(已经删除了我数据库等敏感信息):
代码语言:javascript复制import jieba,pymysql
from gensim import corpora,models,similarities
from collections import defaultdict
def getAllDataFromDB(connection):
cursor = connection.cursor()
cursor.execute("""SELECT * FROM robot""")
results = cursor.fetchall()
data = [eve['question'] for eve in results]
return data
def getDataFromDB(connection,question):
cursor = connection.cursor()
cursor.execute("""SELECT * FROM robot WHERE question = '%s'"""%question)
results = cursor.fetchall()
data = [(eve['question'],eve['answer']) for eve in results]
return data
def getAnswerList(sentence,questions,count=4):
documents = []
for eve_sentence in questions:
tempData = " ".join(jieba.cut(eve_sentence))
documents.append(tempData)
texts=[[word for word in document.split()] for document in documents]
frequency=defaultdict(int)
for text in texts:
for word in text:
frequency[word] =1
dictionary=corpora.Dictionary(texts)
new_xs=dictionary.doc2bow(jieba.cut(sentence))
corpus=[dictionary.doc2bow(text)for text in texts]
tfidf=models.TfidfModel(corpus)
featurenum=len(dictionary.token2id.keys())
sim=similarities.SparseMatrixSimilarity(tfidf[corpus],num_features=featurenum)[tfidf[new_xs]]
tempList = [(sim[i], questions[i]) for i in range(1,len(questions))]
tempList.sort(key=lambda x:x[0],reverse=True)
if len(tempList) >= count:
return tempList[0:count]
else:
return tempList
def putQuestion(question):
connection = pymysql.connect(host="",
user="",
password="",
port=int(),
db="MyScfTest",
charset='utf8',
cursorclass=pymysql.cursors.DictCursor)
questions = getAllDataFromDB(connection)
answers = [getDataFromDB(connection,eve[1]) for eve in getAnswerList(question,questions,count=2)]
connection.close()
return answers
def main_handler(event, context):
sentence = context["question"]
return putQuestion(sentence)
目前,我们的云函数已经部署完成。
云API触发器
有些人对写云API的代码有点一脸懵逼,但是别担心:
https://console.cloud.tencent.com/api/explorer?Product=scf&Version=2018-04-16&Action=Invoke&SignVersion=
云API的Explorer是一个可以自动帮我们写代码的工具,大家可以通过这个工具,进行简答的在线调试:
大家可以看到,选择好了对应的功能,我们填写好对应的参数,通过点击在线调用->发送请求,获得到了结果。
此时我们可以点击代码生成:
我们可以看到系统为我们自动生成了Java、Python等6种语言的代码,这些代码是可以放到项目中直接运行。也就是说,你可以在自己的Node.js,.NET,Java等项目中,调用这个云函数,并且获得结果。
总结
本文是通过一个简单的算法,实现了简单的问答机器人工具。主要涉及到了:
1: 打包函数,可以参考文章中的地址
2:上传代码,可以通过cos上传
3:连接数据库的Demo
4:使用云API触发
当然,SCF的应用场景还有很多,我也会在以后的文章中,更多的和大家分享它的使用场景。