介绍
最近闲来无事,仿照问答、客服类的需求,做了一个需求设计,本人是产品经理+开发,脾气比较暴躁,哦呵呵,上来一阵开发,帮大家分享软件开发经验,提升软件开发水平
系统导语
针对某高校招生咨询常见的一些业务提问,设计一个基于自动问答系统。用户可以用普通的问句对自动问答系统提问,自动问答系统将从知识库或者互联网中搜索相应的答案,然后把答案直接返回给用户,使用语言为中文。
系统功能
1.实现自动回答模块:
本系统实现对输入问题的自动回答,即根据用户输入问题,系统能自动搜索问答库,返回较合适的回答给用户。
2.实现后台数据库可视化操作模块:
本系统需要有强大的问答库支持,在不断完善问答库规模的同时,需要实现对问题库、回答库和关键词库等数据库的可视化管理,方便用户进行查询、添加、 删除和更新操作。
3.用户管理模块:
系统所有用户角色的管理,要有不同的角色和权限
4.数据库导出导入功能:
实现数据库中数据的批量导入导出功能。
5.参数设置:
在系统主界面中,实现相关参数的设置。参数设置包括针对某些常见问题的 回答设置,屏蔽一些不友好用户。
6.词库构建:
构建适用聊天环境的专门词汇库,结合现在的词汇库,确保系统回答的准确性。
7.多分句回复:
实现对多分句问话的回复。在实际的问答环境中,一条问答记录包含有多个分句,它们可能包含各自的问题,如:“学校在哪里?搭什么公交车?”能进行2个问题均能识别并回答。
8.相似度小于阀值通路的处理:
对相似度值小于阀值的处理。建立一个默认回答表,如果在问题库中找不到相似度值大于阀值的句子,就从该表中随机选取一个句子作为回复返回,应具备添加、删除的默认回答表的功能。
9.记录导出功能:
能将记录输入的问答文本和产生的回复到一个文本文件中,以备做机器学习的样本。
10.问题统计管理:
可自动统计用户关注信息,并做图表显示。
选做:可以考虑通过机器学习做成具备一定AI的形式。
开源地址
https://gitee.com/bysj2021/wenda
设计样例图
实现代码如下:
package com.ukefu.util.ai;
import java.io.IOException;
import java.util.List;
import org.lionsoul.jcseg.tokenizer.core.JcsegException;
import com.ukefu.core.UKDataContext;
import com.ukefu.webim.service.cache.CacheHelper;
import com.ukefu.webim.service.repository.AiConfigRepository;
import com.ukefu.webim.service.repository.SceneItemRepository;
import com.ukefu.webim.web.model.AiConfig;
import com.ukefu.webim.web.model.SceneItem;
public class AiUtils {
private static AiDicTrie aiDicTrie = new AiDicTrie();
/**
* 初始化 AI语料库
* @param orgi
* @throws IOException
* @throws JcsegException
*/
public static AiDicTrie init(String orgi) throws IOException, JcsegException{
aiDicTrie.clean();
SceneItemRepository sceneItemRes = UKDataContext.getContext().getBean(SceneItemRepository.class) ;
List<SceneItem> sceneItemList = sceneItemRes.findByOrgiAndItemtype(orgi, UKDataContext.AiItemType.USERINPUT.toString()) ;
for(SceneItem item : sceneItemList){
aiDicTrie.insert(item.getContent(), item.getSceneid());
}
return aiDicTrie;
}
public static AiDicTrie getAiDicTrie(){
return aiDicTrie ;
}
/**
* AI配置
* @param orgi
* @return
*/
public static AiConfig initAiConfig(String orgi){
AiConfig aiConfig = null;
if(UKDataContext.getContext() != null && (aiConfig = (AiConfig) CacheHelper.getSystemCacheBean().getCacheObject(UKDataContext.SYSTEM_CACHE_AI_CONFIG, orgi)) == null){
AiConfigRepository aiConfigRepository = UKDataContext.getContext().getBean(AiConfigRepository.class) ;
aiConfig = aiConfigRepository.findByOrgi(orgi) ;
if(aiConfig == null){
aiConfig = new AiConfig() ;
}else{
CacheHelper.getSystemCacheBean().put(UKDataContext.SYSTEM_CACHE_AI_CONFIG,aiConfig, orgi) ;
}
}
return aiConfig ;
}
}
实现代码如下:
package com.ukefu.util.ai;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.lionsoul.jcseg.extractor.impl.TextRankKeywordsExtractor;
import org.lionsoul.jcseg.tokenizer.core.ADictionary;
import org.lionsoul.jcseg.tokenizer.core.DictionaryFactory;
import org.lionsoul.jcseg.tokenizer.core.ISegment;
import org.lionsoul.jcseg.tokenizer.core.IWord;
import org.lionsoul.jcseg.tokenizer.core.JcsegException;
import org.lionsoul.jcseg.tokenizer.core.JcsegTaskConfig;
import org.lionsoul.jcseg.tokenizer.core.SegmentFactory;
public class DicSegment {
//创建JcsegTaskConfig分词配置实例,自动查找加载jcseg.properties配置项来初始化
private static JcsegTaskConfig config = new JcsegTaskConfig(true);
//创建默认单例词库实现,并且按照config配置加载词库
private static ADictionary dic = DictionaryFactory.createSingletonDictionary(config);
private synchronized static ISegment getSegment() throws JcsegException{
config.setAppendCJKSyn(false);
//追加拼音, 需要在jcseg.properties中配置jcseg.loadpinyin=1
config.setAppendCJKPinyin(false);
ISegment seg = SegmentFactory.createJcseg(
JcsegTaskConfig.COMPLEX_MODE,
new Object[]{config, dic}
);
return seg ;
}
//依据给定的ADictionary和JcsegTaskConfig来创建ISegment
//为了Api往后兼容,建议使用SegmentFactory来创建ISegment对象
//Segment 非线程安全,且切分速度非常快
public synchronized static String[] segment(String content) throws IOException, JcsegException{
IWord word = null;
List<String> words = new ArrayList<String>();
ISegment seg = getSegment();
seg.reset(new StringReader(content));
while ( (word = seg.next()) != null ) {
if(word.getValue().length() == 1 && isChineseByBlock(word.getValue().charAt(0))){
continue ;
}else{
words.add(word.getValue()) ;
}
}
return words.toArray(new String[words.size()]);
}
public static String[] keyword(String content) throws IOException, JcsegException{
return keyword(content , 20);
}
public static String[] keyword(String content , int num) throws IOException, JcsegException{
ISegment seg = getSegment();
TextRankKeywordsExtractor extractor = new TextRankKeywordsExtractor(seg);
extractor.setMaxIterateNum(100); //设置pagerank算法最大迭代次数,非必须,使用默认即可
extractor.setWindowSize(5); //设置textRank计算窗口大小,非必须,使用默认即可
extractor.setKeywordsNum(10); //设置最大返回的关键词个数,默认为10
List<String> keywords = extractor.getKeywords(new StringReader(content));
return keywords.toArray(new String[keywords.size()]);
}
public static boolean isChineseByBlock(char c) {
Character.UnicodeScript sc = Character.UnicodeScript.of(c);
if (sc == Character.UnicodeScript.COMMON) {
return true;
} else {
return false;
}
}
public static void loadDic(String path) throws IOException{
File dicPath = new File(path) ;
if(!dicPath.exists()){
dicPath.mkdirs() ;
}
dic.loadDirectory(path);
}
public static void removeWord(String word){
int inx = ADictionary.getIndex(word) ;
dic.remove(inx, word);
}
}
开发经验总结
基于springboot可以快速搭建开发环境
客服系统使用DWR技术对接即可
语义这一块可以自己思考设计方法、借助百度人工智能平台或者自己使用开源框架手撸
到此为止,大家一定学会了客服系统的开发方法了