百度AnyQ之四——使用anyq的方式添加数据试验

1. 常用容器操作

常用到的进入容器命令行和开启服务的命令

# 开启docker
docker container exec -it anyq-faq /bin/bash
# 切换到服务脚本目录
cd /home/AnyQ-master/build/ 
# 如果使用了容器,那么容器stop 再start的时候,要重新source一下,不然还是找不到java
source ~/.bash_profile
# 执行solr服务
sh solr_script/anyq_solr.sh solr_script/sample_docs
# 执行faq服务
./run_server
# 浏览器输入
http://XXXX:8886/anyq?question=使用什么账号?
# solr查看,浏览器输入:
http://XXX:8900/solr/
"""
8886映射自8889,是anyq的接口
8900映射自8900,是solr的接口

# 如果报错java找不到
cd /home
export PATH=`pwd`/jdk1.8.0_171/bin:$PATH
java -version

# 上面只是暂时生效的配置,重新进入容器就又会丢掉,可以直接在bash中配置
cd ~
[root@567b3aed2b1c ~]$ ls -a  # 查看隐藏文件
.                .bash_logout   .cshrc             .tcshrc
..               .bash_profile  .gitconfig
anaconda-ks.cfg  .bashrc        .oracle_jre_usage
.bash_history    .cmake         .pki
# 在bash_profile文件中配置java_home
vi ~/.bash_profile
# 在最后一行添加
export JAVA_HOME=/home/jdk1.8.0_171/
export PATH=$PATH:$JAVA_HOME/bin
# 或者只添加下面一行(直接写自己对应的jdk的bin路径就可以)
export PATH=/home/jdk1.8.0_171/bin:$PATH


# 需要手动执行,不然不会生效
source ~/.bash_profile
# 验证是否生效
echo $PATH # 观察是否包含jdk的bin目录
echo $JAVA_HOME #是否和上面写的一样
"""

2. (尝试 较混乱)添加一个solrcore

参考:Solr04 - 在Jetty和Tomcat上部署Solr单机服务
(1) Solr工程对外通过SorlCore提供服务, 一个SolrCore相当于数据库中的一张表, 需要注意的是, 这个功能就相当于一个数据库中存在多张表;
(2) 将索引数据分SolrCore存储,方便对索引数据管理维护;

2.1 通过solr的管理UI界面添加solrcore

在这里插入图片描述
报错了,放弃
但是这个报错导致后续界面刷新后一直出错,参考:SolrCore Initialization Failures

在高版本的solr中,通过界面新建core的问题似乎已经解决了,但是在老版本中,不建议通过这种方式进行。

最好的方式就是重启solr

2.2 重启AnyQ中的solr

关键命令

cd /home/AnyQ-master/build/
# sh solr_deply.sh stop solr_home solr_port
sh solr_script/solr_deply.sh stop  ./solr-4.10.3-anyq 8900
# 关了之后再启动,就是重启
sh solr_script/solr_deply.sh start ./solr-4.10.3-anyq 8900
# 包含处理collection1的数据的启动
sh solr_script/anyq_solr.sh solr_script/sample_docs

成功的尝试
不过默认的solr是使用Djetty启动的,在solr_script/anyq_solr.sh脚本中,其实还涉及到一个脚本

SOLR_HOME=./solr-4.10.3-anyq
SOLR_SERVER=${SCRIPT_PATH}/solr_deply.sh
SOLR_PORT=8900
#start
/bin/bash ${SOLR_SERVER} start ${SOLR_HOME} ${SOLR_PORT}

/solr_deply.sh这个脚本,其内容:

function help() {
    echo "usage: sh solr_deply.sh start solr_home solr_port"
    echo "       sh solr_deply.sh stop solr_home solr_port"
}

参考刚刚看到的当使用重启命令,必须传入当初启动时的所有参数。Solr重启之前将被关闭。如果没有节点正在运行,restart将跳过关闭,直接启动Solr。,个人理解就是关闭就是完全杀掉,杀了之后启动,就是重启。。和电脑关机开机=重启,一个道理。试一下。


关闭solr
由于上面这个脚本文件使用的时候已经从tools文件夹复制到了build/solr_script文件夹中,所以直接

cd build/solr_script
# sh solr_deply.sh stop solr_home solr_port
sh solr_deply.sh stop  ./solr-4.10.3-anyq 8900

然后报错了。。。我都是root用户了,没法使用sudo,后来想到应该是路径有问题。
在这里插入图片描述
应该是

cd build
# sh solr_deply.sh stop solr_home solr_port
sh solr_script/solr_deply.sh stop  ./solr-4.10.3-anyq 8900

在这里插入图片描述
然后就成功了,这时候再去访问http://XXXX:8900/solr/#/collection1就什么都没有了。之前就算关了run_server也有,所以run_server和solr其实是两套服务。


启动solr
还是在关闭命令执行的那个目录下,命令差不多,stop改成start就好了。

sh solr_script/solr_deply.sh start ./solr-4.10.3-anyq 8900
> nohup: appending output to ‘nohup.out’
solr[8900] start success!

启动时提示的内容和当初直接sh solr_script/anyq_solr.sh solr_script/sample_docs的内容差不多,不过报错了,但是不是之前找不到配置文件的错误了。
在这里插入图片描述
参考:Caused by: org.apache.solr.common.SolrException: Index locked for write for core 正解✅

找到./build/solr-4.10.3-anyq/example/solr/mask_core/data/index,其中有一个write.data文件,删除,然后重启Solr即可。重启之后正确,而且可以看到新创建的mask_core这个solrcore了。
在这里插入图片描述
因为是直接复制的collection1这个文件夹,所以数据是一模一样的
在这里插入图片描述


部分正确,部分错误的解决
尝试直接执行包含数据读取的启动脚本,无效。后发现是因为该脚本中写死了参数:

ENGINE_NAME=collection1
SOLR_CONF=$SOLR_HOME/example/solr/collection1/conf

所以如果要构建多个solrCore,比如我的第二个solrcore叫mask_core(是一个和口罩相关的faq集合)。那么就需要把这个脚本文件复制一份,改掉里面的部分内容。 或者不执行这个脚本

💢无效!尝试解决

cd build
# 先关闭
sh solr_script/solr_deply.sh stop  ./solr-4.10.3-anyq 8900
# 然后不执行启动,而是直接执行
sh solr_script/anyq_solr.sh solr_script/sample_docs
> faq-file trans done
nohup: appending output to ‘nohup.out’
solr[8900] start success!
[{'indexed': True, 'stored': True, 'type': 'text_multi_lang', 'name': 'question'}, {'indexed': False, 'stored': True, 'type': 'string', 'name': 'answer'}]
{
  "responseHeader":{
    "status":0,
    "QTime":104}}

{"responseHeader":{"status":0,"QTime":73}}

{"responseHeader":{"status":0,"QTime":133}}

upload file success

无效,那就应该是别的原因造成的锁定。


💢失败的尝试
在anyq的构建中,有以下代码:

# 获取anyq定制solr,anyq示例配置
cp ../tools/anyq_deps.sh .
sh anyq_deps.sh #下载solr-4.10.2-anqy的下载包并解压

# 启动solr, 依赖python-json, jdk>=1.8
cp ../tools/solr -rp solr_script
sh solr_script/anyq_solr.sh solr_script/sample_docs

所以重启就重新运行以下这个脚本就好了,但是重新运行的时候显示java又找不到了。。

cd /home
export PATH=`pwd`/jdk1.8.0_171/bin:$PATH
java -version

但是其实那个脚本里是启动命令,而不是重启命令

SOLR_HOME=./solr-4.10.3-anyq
SOLR_SERVER=${SCRIPT_PATH}/solr_deply.sh
SOLR_PORT=8900
#start
/bin/bash ${SOLR_SERVER} start ${SOLR_HOME} ${SOLR_PORT}

没有找到很正确的重启方式,那就去创建这个丢失的文件好了,参考1.2.4,然后失败,继续回来,还是要重启

重新考虑重启,参考:solr 常用命令

bin/solr restart -help

当使用重启命令,必须传入当初启动时的所有参数。Solr重启之前将被关闭。如果没有节点正在运行,restart将跳过关闭,直接启动Solr。

去自己安装的solr的bin目录下看一下好了,输入上面的帮助命令,确实显示了一些信息:

Usage: solr restart [-f] [-c] [-h hostname] [-p port] [-d directory] [-z zkHost] [-m memory] [-e example] [-s solr.solr.home] [-a "additional-options"] [-V]

  -f            Start Solr in foreground; default starts Solr in the background
                  and sends stdout / stderr to solr-PORT-console.log

  -c or -cloud  Start Solr in SolrCloud mode; if -z not supplied, an embedded ZooKeeper
                  instance is started on Solr port+1000, such as 9983 if Solr is bound to 8983

  -h <host>     Specify the hostname for this Solr instance

但是这里有个问题,直接在前台启动solr。


2.3 直接复制collection1文件夹,然后再配置

第一步,复制整个文件夹

# 迭代复制,会把这个文件夹中所有内容都复制过去的,
# 目标文件夹不存在会自动创建的
cp -r ./collection1 ./mask_core

第二步,修改mask_core文件夹下core.properties

name=collection1
# 改为
name=mask_core

💢第三步,重启包含solr的服务,也就是重启solr,参考:AnyQ如何配置solr动态读取数据库——AnyQ系列之二,根据下面博主回答的评论,感觉可以尝试一下。这个重启方式错误,反正还是要重启

3. 正确路径

3.1 总结2(正确方式)

第一步,复制/home/Anyq-master/build/solr-4.10.3-anyq/example/solr中的整个collection1文件夹,比如新起的solrcore名称为mask_core,则就复制到同级目录

# 迭代复制,会把这个文件夹中所有内容都复制过去的,
# 目标文件夹不存在会自动创建的
cp -r ./collection1 ./mask_core

第二步,修改mask_core文件夹下core.properties

name=collection1
# 改为
name=mask_core

第三步,重启

cd /home/AnyQ-master/build/
# sh solr_deply.sh stop solr_home solr_port
sh solr_script/solr_deply.sh stop  ./solr-4.10.3-anyq 8900
# 关了之后再启动,就是重启
sh solr_script/solr_deply.sh start ./solr-4.10.3-anyq 8900


# 包含处理collection1的数据的启动(一般不建议使用)
sh solr_script/anyq_solr.sh solr_script/sample_docs

第四步,如果第三步执行后,启动solr界面报错SolrException: Index locked for write for core,类似下面:
在这里插入图片描述
那么可以参考:Caused by: org.apache.solr.common.SolrException: Index locked for write for core 正解✅

找到./build/solr-4.10.3-anyq/example/solr/mask_core/data/index,其中有一个write.data文件,删除,然后重启Solr即可。重启之后就可以看到新创建的mask_core这个solrcore了。


碎碎念
一条一条加进去,如果有问题的话,直接搜索solr数据全量更新和增量更新。(虽然我现在也不理解,为什么17年的时候,AnyQ团队要选solr而不是ES,github的issue上也有人问能不能换成ES,🤐🤐)

3.2 按照anyq的方式初始化时批量加入自己的数据

3.2.1 anyq使用faq数据集的方式

打开这个anys_solr.sh脚本文件,可以看到:

# 前面定义了下面的这些

#start
/bin/bash ${SOLR_SERVER} start ${SOLR_HOME} ${SOLR_PORT}

# set schema
python ${SOLR_API} set_schema ${ENGINE_HOST} ${ENGINE_NAME} ${SCHEMA_FILE} ${SOLR_PORT}

# clear docs
python ${SOLR_API} clear_doc ${ENGINE_HOST} ${ENGINE_NAME} ${SOLR_PORT}

# upload docs
python ${SOLR_API} upload_doc ${ENGINE_HOST} ${ENGINE_NAME} ${SOLR_PORT} ${FAQ_JSON}

其中,关于默认示例中的faq数据集,其实在这个脚本文件中有:

mkdir -p faq
SCHEMA_FILE=`pwd`/faq/schema_format
FAQ_JSON=`pwd`/faq/faq_json
python ${SCRIPT_PATH}/make_json.py $FAQ_FILE $SCHEMA_FILE $FAQ_JSON

其中,这个sh脚本是在./build目录中运行的,所以pwd指的就是build目录,所以要找到那个faq_json文件,其完整目录是/home/AnyQ-master/build/faq/faq_json。文件内容形式如下:
(就是这个顺序。。答案,然后问题,然后序号。。)

{
"answer": "您需要拥有一个百度账号,用来登录百度云,可以点击此处注册百度账户。如您以前拥有百度推广账户,同样可以登录百度云。", 
"question": "需要使用什么账号登录?", 
"id": "1"
}
{
"answer": "由于欠费停机、存储信息已满、信号网络延迟等原因没有及时收到验证码,这时请检查您的手机及话费余额,保证手机可正常接收短信后,请尝试重新获取验证码。", 
"question": "注册百度账户时收不到验证码怎么办?", 
"id": "2"
}

所以不难得出整个逻辑:

  1. mkdir -p faq 在当前执行目录,即build/文件夹下创建faq目录
  2. 定义两个变量
    SCHEMA_FILE=`pwd`/faq/schema_format
    FAQ_JSON=`pwd`/faq/faq_json
    
  3. 执行将doc文档转换为faq_json的脚本,
    python ${SCRIPT_PATH}/make_json.py $FAQ_FILE $SCHEMA_FILE $FAQ_JSON
  4. 主要就是AnyQ-master\tools\solr文件夹中的make_json.py脚本,其会接收调用时参数,然后读取对应的文件,并将其转换为一定的格式
    SCRIPT_PATH=$(dirname $0)
    FAQ_FILE=$1  # 就是sh执行时候传入的第一个参数,就是这里的 solr_script/sample_docs
    SCHEMA_FILE=`pwd`/faq/schema_format
    FAQ_JSON=`pwd`/faq/faq_json # 最后保存的名称
    python ${SCRIPT_PATH}/make_json.py $FAQ_FILE $SCHEMA_FILE $FAQ_JSON
    
    sh solr_script/anyq_solr.sh solr_script/sample_docs
  5. 所以如果要换自己的数据集,就重新指定一下sample_docs,或者直接替换掉其中的内容。

如果要将新上传的数据切换到mask_core而不是默认的collection1中,还需要注意:anyq_solr.sh这个脚本中写死了参数:

ENGINE_NAME=collection1
SOLR_CONF=$SOLR_HOME/example/solr/collection1/conf

所以如果要构建多个solrCore,比如我的第二个solrcore叫mask_core(是一个和口罩相关的faq集合)。那么就需要把这个脚本文件复制一份,改掉里面的部分内容。

3.2.2 删除solrcore中的数据

如果想要完全更新mask_core的数据,首先需要清空目前mask_core中从collection1中复制过来的数据。

<!-- 删除全部, 慎用 -->
<delete>
    <query>:</query>
</delete>
<commit/>

3.3 修改脚本以自己的数据作为solr启动时

3.3.1 整理数据格式

要保证自己的数据形式与AnyQ-master/tools/solr/sample_docs中数据格式一致,其格式其实是以tab分割的csv文件。

得到了一个关于口罩的问答数据集,有100个问答对。
在这里插入图片描述

注意:

  1. question或者answer内容中都不要有换行符,make_json.py文件写的比较简单。如下:
    有换行符的话,读行的时候,就会读错,所以如果有换行符的话,要提前处理掉。
  2. 注意,如果在windows上,默认open用的是GBK编码,但是如果是linux上,则是utf-8,保存的时候需要保证是utf-8的格式
  3. windows下处理的文件,最后一行会是一个换行符,要手动删除,不然也会报错line error
def run(faq_file_str, format_file_str, json_file_str):
    """
    convert text file to json file, save schema file
    """
    idx = 0
    header = 0
    field_cnt = 0
    auto_id = False
    faq_file = open(faq_file_str, "r")
    for line in faq_file:
        arr = line.strip().split('\t')
        if header == 0:
            header = 1
            field_names = arr
            field_cnt = len(field_names)
            if 'question' not in field_names or 'answer' not in field_names:
                print >> sys.stderr, "need question and answer"
                sys.exit(6)
            if 'id' not in field_names:
                auto_id = True
            write_format_file(field_names, format_file_str)
            json_file = open(json_file_str, "w")
            continue
        if len(arr) != field_cnt:
            print >> sys.stderr, "line error"
            continue
        idx += 1
        data = dict([field_names[i], arr[i]] for i in range(field_cnt))
        if auto_id:
            data['id'] = str(idx)
        json_file.write(json.dumps(data, ensure_ascii=False))
        json_file.write("\n")
    json_file.close()
    faq_file.close()

3.3.2 上传文件

  • 为了防止出错,之前的容器被破坏,所以新开了一个容器。anyq-trace
  • 如果docker没有映射本地文件,那么可以直接vi mask_docs,然后把刚刚的内容复制上去

注意,复制过去的时候,前四个字符都会丢失,也就是question会显示为tion。。。需要手动调整一下。

3.3.3 不修改solrcore,只是修改上传的文件**

  • 注意之前的sample_docs是没有格式后缀的,所以这里也删除后缀,上传到镜像和sample_docs同级目录中。
  • 接下来执行:
    cp ../tools/solr -rp solr_script
    # 所以之前tools/solr中的脚本文件已经被复制到了build/solr_script中了
    sh solr_script/anyq_solr.sh solr_script/mask_docs
    
  • 执行成功,则提示:
    在这里插入图片描述
  • 可以访问solr界面,查看一下当前collection1中的数据,可以看到:不是16个了,而是100个,所以重新执行其实是清空了collection的数据,再新加入。
    在这里插入图片描述
  • 同时,查看schema Browser,可以看到,关于question,已经变成了当前这个FAQ数据集相关的内容。
    在这里插入图片描述
  • 然后访问faq服务,问问题,观察返回的内容。可以看到,后台打印出的log
    在这里插入图片描述
    在这里插入图片描述
  • 所以直接替换自己的FAQ集是完全没问题的

3.3.4 上传数据到另一个solr_core中

上面已经验证了替换FAQ数据的可行性,这次上传数据到新的solr_core中,尝试一下结果。

进行以下操作:

1.还是新建一个mask_docs,把处理好的faq数据复制进去的
2. 复制anyq_solr.sh文件得到anyq_solr_mask,并修改

cp anyq_solr.sh ./anyq_solr_mask.sh

# 将文件中所有的collection1改为mask_core
ENGINE_NAME=collection1
SOLR_CONF=$SOLR_HOME/example/solr/collection1/conf

注意观察,自己的solr-4.10.3-anyq/example/solr文件夹中,除了collection1之外,是否已经新建过sorlcore了,比如,我这里新建的就是mask_core
在这里插入图片描述
3. 启动solr服务并读入mask_docs数据

sh solr_script/anyq_solr_mask.sh solr_script/mask_docs

提示:
在这里插入图片描述
生成的中间文件faq_json就位于build/faq/faq_json中,除非把脚本中保存文件的名称改掉。
(注意,这个一旦上传成功,solr中就会一直保存着,因为已经在对应的solr_core存储成了data,所以后续可以直接启动solr服务,不用再读入数据了)
4. 打开solr的UI界面,刷新,可以看到,确实上传到了mask_core中,同时schema browser中查看question字段,显示也和1.5.3中相同
在这里插入图片描述
5. 启动faq服务,
在这里插入图片描述

失败,所以还是需要去看AnyQ中关于FAQ部分的实现逻辑,应该是哪里指定了collection1这个solrcore。

3.3.5 解决1.5.4的问题

根据百度AnyQ之五——FAQ部分逻辑理解2. 执行时打印的log信息的第六步和第七步,可知,需要进行配置才能够在粗排阶段(即solr的关键词检索阶段,使用mask_core,而不是collection1)

build/example/conf/retrieval.conf文件中的engine_namecollection1改为mask_core

retrieval_plugin {
    name : "term_recall_1"
    type : "TermRetrievalPlugin"
    search_host : "127.0.0.1"
    search_port : 8900
    engine_name : "collection1"

在上面已经向mask_core中加入数据的基础上,直接执行./run_server进行测试。可以看到,已经修改成功了
在这里插入图片描述
结果也还不错,OK
在这里插入图片描述

4. 和mysql连接 💢(放弃)

参考:

网上大部分都会用到tomcat,不过我并不希望使用tomcat,所以主要参考上面第二个进行操作。

4.1 安装mysql

# 1.检测系统自带Mysql,并卸载
$ rpm -qa | grep mysql
mysql-libs-5.1.66-2.el6_3.x86_64
[root@hadoop eclipse]# rpm -e mysql-libs-5.1.66-2.el6_3.x86_64 --nodeps
# 2.通过网络安装MySQL (yum)
$ yum -y install mysql mysql-devel mysql-server

# 3.启动服务
# service mysqld start
开机自启动
# chkconfig mysqld on

# 4.设置用户和密码
#/usr/bin/mysqladmin -uroot password 'root'

# 5.进入
mysql -uroot -p123456

# 6.查看mysql用户
select host,user,password from mysql.user;
# 7.修改远程访问权限
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
# 8.重载授权表:
FLUSH PRIVILEGES;

后来考虑了一下,数据库配置似乎略显麻烦,如果可以直接使用solr本身的data做暂存,其实没必要再引入数据库,多一部分,维护就多一个麻烦。减少引入的组件,挺好的。

5. github上一些相关的issue

从代码里可以看道http接口方法
/anyq => anyq,"
“/solr/v1/delete => solr_delete,”
“/solr/v1/insert => solr_insert,”
“/solr/v1/update => solr_update,”
“/solr/v1/clear => solr_clear”

这些表情可能包含某些需要转义的字符,可自行转义,加入src/common/utils.cpp中的escape。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要实现提取问题中的参数并调用API,你需要进行以下步骤: 1. 对问题进行自然语言处理。你可以使用Python中的自然语言处理库,例如NLTK、spaCy、Stanford NLP等,来对问题进行分析和解析。 2. 从问题中提取参数。一旦你对问题进行了解析,就可以使用词性标注和命名实体识别等技术来提取参数。例如,如果问题是“北京天气怎么样?”,你可以使用命名实体识别来找到“北京”这个地点的参数。 3. 调用API。一旦你提取出了参数,就可以使用它们来调用相应的API。例如,如果你想要查询北京的天气,你可以使用天气API,并将“北京”作为参数传递给该API。 下面是一个简单的Python代码示例,演示如何从问题中提取参数并调用API: ```python import requests import json import nltk # 问题 question = "北京天气怎么样?" # 分词和词性标注 tokens = nltk.word_tokenize(question) tags = nltk.pos_tag(tokens) # 命名实体识别 ne_chunked = nltk.ne_chunk(tags) entities = [] for chunk in ne_chunked: if hasattr(chunk, 'label') and chunk.label() == 'GPE': entities.append(' '.join(c[0] for c in chunk)) # 调用API if len(entities) > 0: url = "http://api.openweathermap.org/data/2.5/weather?q={}&appid=your_app_id".format(entities[0]) response = requests.get(url) data = json.loads(response.text) print("天气:{}".format(data['weather'][0]['description'])) else: print("无法识别问题中的地点参数") ``` 在这个示例中,我们使用NLTK库对问题进行了分词和词性标注,然后使用命名实体识别找到了问题中的地点参数。接着,我们使用天气API来查询该地点的天气,并将查询结果输出到控制台中。 希望这个示例可以帮助你实现提取问题中的参数并调用API的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吨吨不打野

解决了问题,觉得还行就给点

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值