Open AI API连接问题

报错信息

raise error.APIConnectionError(
openai.error.APIConnectionError: Error communicating with OpenAI: HTTPSConnectionPool(host=’api.openai.com’, port=443): Max retries exceeded with url: /v1/chat/completions (Caused by ProxyError(‘Cannot connect to proxy.’, NewConnectionError(‘: Failed to establish a new connection: [WinError 10061] 由于目标计算机积极拒绝,无法连接。’)))

主要原因为代理的问题,需要魔法

继续阅读Open AI API连接问题

OBS录屏并配音

录制屏幕调研

因需要录制一段屏幕视频因此做了一个小小的调研,一共使用了三种方式录制。

第一种是通过OBS进行录制。OBS的官方网站为:https://obsproject.com/,在官网上下载相对应的客户端之后便可以录制。

第二种是通过谷歌浏览器的插件。参考知乎Chrome 录屏神器!自称“最强大”的屏幕录制和注释工具!这篇文章就可以。录制的感受是清晰度相对较低。

第三种是通过PPT。新建一个空白文档,选择“插入”,再选择“屏幕录制”,然后选择需要录制的区域的步骤即可。录制好之后右击,选择“将媒体另存为”即可保存视频。PPT有个问题是出现在选择区域的相关画面都会被录制进去,比如邮件弹窗,输入法的窗口等。

继续阅读OBS录屏并配音

Linux安装配置OpenJDK1.8

下载、解压JDK

首先下载压缩包

wget https://download.java.net/openjdk/jdk8u41/ri/openjdk-8u41-b04-linux-x64-14_jan_2020.tar.gz

然后解压

tar -zxvf openjdk-8u41-b04-linux-x64-14_jan_2020.tar.gz

配置JAVA_HOME环境变量

# 打开环境变量文件
vim .bashrc
# 子文件末尾追加
export JAVA_HOME=/home/user_name/java-se-8u41-ri
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
export PATH=${JAVA_HOME}/jre/bin:$PATH
# source一下,重新加载环境变量
source .bashrc

检查环境安装是否成功

输入:
java -version
输出:
openjdk version "1.8.0_41"
OpenJDK Runtime Environment (build 1.8.0_41-b04)
OpenJDK 64-Bit Server VM (build 25.40-b25, mixed mode)

参考

https://blog.csdn.net/linysuccess/article/details/108881251

faiss的安装及简单使用

pip安装

直接使用pip安装pip install faiss

在python环境中import faiss会报错

使用如下的命令安装可以成功

pip –default-time=1000 install -i https://pypi.tuna.tsinghua.edu.cn/simple faiss-cpu

conda安装

只安装cpu版本

$ conda install -c pytorch faiss-cpu

安装gpu+cpu版本

$ conda install -c pytorch faiss-gpu

指定cuda版本

$ conda install -c pytorch faiss-gpu cudatoolkit=10.2 # for CUDA 10.2

faiss的简单使用

构建数据集

使用xb矩阵建立索引,xb的每一行都是被检索的对象,维度是(nb,d) 。xq矩阵,是用来检索的向量集合的矩阵,对其中的每个向量,需要找到它的前K个相似向量,维度是(nq,d)。当只检索一个向量的时候,nq=1

import numpy as np
d = 64                           # dimension
nb = 100000                      # database size
nq = 10000                       # nb of queries
np.random.seed(1234)             # make reproducible
xb = np.random.random((nb, d)).astype('float32')
xb[:, 0] += np.arange(nb) / 1000.
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000.

建立索引并加入向量

Faiss中有多种类型的索引,使用最简单的索引类型:IndexFlatL2,这是暴力检索L2距离,也就是最常规的计算距离的方式。对于大部分索引类型而言,在建立它们时都包含训练阶段,但是对于IndexFlatL2这个索引,可以跳过这一步。 当索引被建立和训练之后,可以调用add和search这两种方法。 还可以使用两种查找索引状态的方法 is_trianed,来表明索引是否已经被训练过。ntotal来得到当前索引中向量的个数。对于一些类型的索引来说,还可以存储每个向量对应的整数ID(IndexFlatL2不行),如果没有提供ID,那么索引就是的第一个向量索引为0,第二个向量索引为1,以此类推。

import faiss                   # make faiss available
index = faiss.IndexFlatL2(d)   # build the index
print(index.is_trained)
index.add(xb)                  # add vectors to the index
print(index.ntotal)
  • 第一个print的结果:True,已经经过训练,IndexFlatL2不需要训练,因此为True
  • 第二个print的结果:10000,xb得维度是10000

检索

对于每个检索向量,都能从索引中得到前K近个向量。

k = 4                          # we want to see 4 nearest neighbors
D, I = index.search(xb[:5], k) # sanity check
print(I)
print(D)
D, I = index.search(xq, k)     # actual search
print(I[:5])                   # neighbors of the 5 first queries

参考

faiss包安装_Alicesla的博客-CSDN博客_faiss包安装

Faiss库使用方法(一) – 知乎 (zhihu.com)

安装mxnet报错OSError: libcudnn.so.8

安装流程

pip install mxnet-cu102

安装好了之后在python中import mxnet,报了OSError: libcudnn.so.8: cannot open shared object file: No such file or directory错误

解决方案

方案1

改变mxnet的版本,卸载之后重新尝试了mxnet-cu100和mxnet-cu110,依然报相同的错误,未解决

方案2

网上看了很多解决方案,因为没有sudo权限所以没有尝试

官网上看到docker的安装方法所以尝试

首先要安装NVIDIA的docker驱动,然后拉取镜像docker pull mxnet/python:gpu,mxnet/python 的docker hub里只有1.9版本的镜像,但在拉取镜像的过程中报错

这样可以选择拉取别人上传的镜像也可以拉取一个linux镜像重新搭建需要的cuda和cuDNN版本

拉取镜像构建容器参考Docker容器构建

方案3

最后的解决方法有点简单,兜兜转转一圈回来下载一个低版本的安装便成功了

pip install mxnet-cu102==1.6.0.post0 -i https://pypi.tuna.tsinghua.edu.cn/simple/

直接pip install mxnet-cu102安装的版本是1.9.1会报错,1.6.0版本没有报错

其他方案

在虚拟环境下装个10.1 cudatookit

先执行conda install cudatoolkit=10.1 -c pytorch
再pip install mxnet-cu101==1.5.1 -i https://pypi.tuna.tsinghua.edu.cn/simple/

上述方案也可以将mxnet安装成功

Docker构建容器

Docker概述

docker docs

docker hub

docker架构

Docker使用客户端-服务器架构。Docker客户端(client )与Docker守护进程(daemon)通信,后者负责构建、运行和分发Docker容器的繁重工作。Docker客户端和Docker守护进程可以在同一个系统上运行,也可以将Docker客户端连接到远程的Docker守护进程。Docker客户端和守护进程使用REST API通过UNIX套接字(sockets )或网络接口通信。另一个Docker客户端是Docker Compose,它允许使用由一组容器组成的应用程序。

图片来自docker官方网站https://docs.docker.com/get-started/overview/

镜像

镜像是一个只读的模板,包含创建Docker容器的说明。通常,一个镜像基于另一个镜像,并有一些额外的定制。例如,可以构建一个基于ubuntu镜像的镜像,安装Apache web服务器和应用程序,以及运行应用程序所需的配置细节。可以创建自己的镜像,也可以只使用其他人创建并在注册表中发布的镜像。要构建自己的镜像,需要创建一个Dockerfile,使用简单的语法定义创建和运行镜像所需的步骤。Dockerfile中的每一条指令都会在镜像中创建一个层。当更改Dockerfile并重建镜像时,只有那些更改的层会被重建。与其他虚拟化技术相比,这是使镜像轻量级、小巧和快速的部分原因。

容器

容器是镜像的可运行实例。

  • 可以使用Docker API或CLI创建、启动、停止、移动或删除容器。
  • 可以将容器连接到一个或多个网络,为其附加存储空间,甚至根据其当前状态创建新镜像。默认情况下,一个容器与其他容器及其宿主机是相对隔离的。
  • 可以控制容器的网络、存储或其他底层子系统与其他容器或主机的隔离程度。
  • 容器由它的镜像以及在创建或启动它时提供给它的配置选项定义。当容器被移除时,任何未存储在持久存储中的对其状态的更改都会消失。

容器是一个sandboxed process,与主机上的所有其他进程隔离。这种隔离利用了kernel namespaces和cgroups。可以在本地机器、虚拟机上运行或部署到云端;具有可移植性(可以在任何操作系统上运行);与其他容器隔离,并运行自己的软件、二进制文件和配置。

运行一个ubuntu容器,以交互方式连接到本地命令行会话,然后运行 /bin/bash

docker run -i -t ubuntu /bin/bash

当您运行此命令时,将发生以下情况(假设您使用默认注册表配置):

  1. 如果您没有本地的ubuntu镜像,Docker将从配置的注册表中拉取它,就像手动运行Docker pull ubuntu一样。
  2. Docker会创建一个新容器,就像手动运行Docker container create命令一样。
  3. Docker为容器分配了一个读写文件系统,作为它的最后一层。这允许一个正在运行的容器在其本地文件系统中创建或修改文件和目录。
  4. 由于没有指定任何网络选项,Docker会创建一个网络接口将容器连接到默认网络。这包括为容器分配IP地址。默认情况下,容器可以使用主机的网络连接连接到外部网络。
  5. Docker启动容器并执行/bin/bash.因为容器以交互方式运行,并且连接到终端(因为有-i和-t标志),所以可以使用键盘提供输入,同时将输出记录到终端。
  6. 当你输入exit来终止/bin/bash命令时,容器会停止,但不会被移除。您可以重新启动它或删除它。

容器镜像

当运行容器时,它使用一个隔离的文件系统。这个自定义文件系统由容器镜像提供。镜像包含容器的文件系统,它必须包含运行应用程序所需的一切——所有依赖项、配置、脚本、二进制文件等。镜像还包含容器的其他配置,如环境变量、要运行的默认命令和其他元数据。

Docker实践

第一步

在工程项目文件夹中写好Dockerfile,如下:

FROM 安装好anaconda3的镜像

ADD ./ /opt/test/

WORKDIR /opt/test/

RUN apt update -y && apt install -y libopenblas-dev

RUN /root/anaconda3/envs/cpu/bin/pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/

RUN chmod +x ./start.sh

CMD [“/bin/sh”,”-c”, “./start.sh”]

拉取一个具有相关配置和环境的镜像;

然后将当前文件夹中的文件添加到容器中/opt/test的目录下;

工作目录为/opt/text;

然后更新安装包并安装libopenblas-dev;

再安装项目依赖的第三方库;

运行当前目录下的start.sh文件

第二步

执行docker build -t image_name ./ –network=host

第三步

镜像构建好了之后使用docker run -itd -p 12345:12345 –name contrainer_name image_name构建容器

因为我的项目是一个web服务,因此设置了端口的对应关系,宿主机的端口12345,对应容器内的端口为12345

简单docker命令

列出本地镜像使用docker image命令

查看容器信息使用命令docker ps -a,得到容器ID(CONTAINER ID)。

使用命令docker exec -it CONTAINER ID /bin/bash进入容器

使用ctrl+D或者exit退出容器

使用docker start CONTAINER ID可以启动

复制本地文件到docker容器中docker cp

docker cp 源文件夹/文件 容器ID:目标文件夹

宿主机和docker中的文件关联 ,使用-v

例如:使用镜像bitnami/mxnet

docker run -itd –name mxnet1 -v /home/project/:/opt/test/ bitnami/mxnet

此命令将宿主机的文件和容器中的文件指向同一个地址,修改其中一个可以同步到另一个,比如在宿主机中添加一个文件,文件会同步到docker容器中

KMeans跑满CPU

问题描述

在调用sklearn.cluster中的KMeans时,cpu占用达100%,比如40核的cpu,最高4000%的cpu占用率

尝试解决方案

scikit-learn版本为0.24.2

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=k, random_state=123)
kmeans.fit(self.embeddings)
cluster_centers = kmeans.cluster_centers_
labels = kmeans.labels_

scikit-learn在0.23版本时会有n_jobs参数可以设置线程数,但是在降低版本之后,设置n_jobs参数依然会跑满cpu。下图是官方文档对n_jobs的解读。

考虑到之后高版本不会再使用n_jobs参数,所以未深究其中原因。

最终解决方案

在启动服务时设置线程数量可以解决该问题,如果设置为4个线程

OMP_NUM_THREADS=4 python run.py

PyTorch训练模型转ONNX

方法一

加载Pipeline

从transformers库中加载FeatureExtractionPipeline。如果知道要使用的模型的所有输入形状和配置,则可以不需要此步骤。使用 convert_graph_to_onnx 中的相应函数可以显着简化自定义模型的创建。生成的变量将用于torch导出调用。

from transformers import FeatureExtractionPipeline, AutoModel, AutoTokenizer, convert_graph_to_onnx

model_access = "my_model_dir"
model_pipeline = FeatureExtractionPipeline(
        model=AutoModel.from_pretrained(model_access),
        tokenizer=AutoTokenizer.from_pretrained(model_access, use_fast=True),
        framework="pt",
        device=-1)

config = model_pipeline.model.config
tokenizer = model_pipeline.tokenizer

with torch.no_grad():
    input_names, output_names, dynamic_axes, tokens = convert_graph_to_onnx.infer_shapes(model_pipeline, "pt")
    ordered_input_names, model_args = convert_graph_to_onnx.ensure_valid_input(
            model_pipeline.model, tokens, input_names)

# 如果想添加更多的输出,则必须相应地修改dynamic_axes和output_names。
del dynamic_axes["output_0"]  # Delete unused output
del dynamic_axes["output_1"]  # Delete unused output

output_names = ["output"]
dynamic_axes["output"] = {0: 'batch'}

# 导出模型到ONNX
model = torch.load("best_model.pth")
output = "best_model.onnx"
torch.onnx.export(
        model,
        model_args,
        f=output,
        input_names=input_names,
        output_names=output_names,
        dynamic_axes=dynamic_axes,
        do_constant_folding=True,
        use_external_data_format=False,
        enable_onnx_checker=True,
        opset_version=11)

# 检查 onnx model
onnx_model = onnx.load(output)
onnx.checker.check_model(onnx_model)
print('The model is checked!')

加载onnx模型进行推理

import numpy as np
from transformers import AutoTokenizer
import onnxruntime as rt
import time

onnx_model_path = "best_model.onnx"
model_path = "best-checkpoint"  # my_model_dir
tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False)
span = "输入"  # 输入的文本

opt = rt.SessionOptions()
sess = rt.InferenceSession(onnx_model_path)  # Loads the model
t0 = time.perf_counter()
model_input = tokenizer.encode_plus(span)
model_input = {name: np.atleast_2d(value) for name, value in model_input.items()}
onnx_result = sess.run(None, model_input)
onnx_result = onnx_result[0]
onnx_result = np.argmax(onnx_result, axis=-1)
print(time.perf_counter() - t0)

方法二

pt2onnx

import os
import torch
from transformers import BertTokenizer, get_linear_schedule_with_warmup,BertForSequenceClassification, AdamW
import onnx

def pt2onnx_bert():
    pretrained_model = '../model/bert-base-chinese'
    onnx_path = 'api/onnx/bert-base-chinese-cls.onnx'
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    tokenizer = BertTokenizer.from_pretrained(pretrained_model)
    model = BertForSequenceClassification.from_pretrained(pretrained_model)
    model.eval()
    model.to(device)

    input_names = ['input_ids', 'attention_mask', 'token_type_ids']
    outputs_names = ['output']
    # 构造输入
    inputs = '输入'
    encode_dict = tokenizer.encode_plus(text=inputs,
                                        max_length=512,
                                        pad_to_max_length=True,
                                        return_tensors='pt',
                                        return_token_type_ids=True,
                                        return_attention_mask=True)

    input_ids = encode_dict['input_ids']
    attention_mask = encode_dict['attention_mask']
    token_type_ids = encode_dict['token_type_ids']

    dummy_input = {
        'input_ids': input_ids,
        'attention_mask': attention_mask,
        'token_type_ids': token_type_ids
    }
    with torch.no_grad():
        torch.onnx.export(model=model,
                          args=tuple(dummy_input.values()),
                          f=onnx_path,
                          opset_version=11,
                          input_names=input_names,
                          output_names=outputs_names,
                          dynamic_axes={'input_ids': {0: 'batch_size'},
                                        'attention_mask': {0: 'batch_size'},
                                        'token_type_ids': {0: 'batch_size'},
                                        'output': {0: 'batch_size'}}
                          )
    # 验证
    print(onnx.checker.check_model(onnx_path))

推理

from onnxruntime import GraphOptimizationLevel, InferenceSession, SessionOptions, get_all_providers

def create_model_for_provider(model_path: str, provider: str) -> InferenceSession:
    assert provider in get_all_providers(), f"provider {provider} not found, {get_all_providers()}"

    options = SessionOptions()
    #控制线程数
    options.intra_op_num_threads = 0
    options.graph_optimization_level = GraphOptimizationLevel.ORT_ENABLE_ALL
    session = InferenceSession(model_path, options, providers=[provider])
    return session

def onnx_inference(x):
    #CPUExecutionProvider
    ort_session = create_model_for_provider(onnx_model_path, 'CUDAExecutionProvider')
    encode_dict = tokenizer.batch_encode_plus(batch_text_or_text_pairs=x,
                                              max_length=MAX_SEQ_LEN,
                                              pad_to_max_length=True,
                                              return_tensors='pt',
                                              return_token_type_ids=False,
                                              return_attention_mask=True)

    inputs = {k: v.numpy() for k, v in encode_dict.items()}
    outputs = ort_session.run(None, inputs)
    # 不同的模型对应不同的以下代码
    outputs = outputs[0]
    outputs = np.argmax(outputs, axis=-1)
    result = []
    for out in outputs:
        result.append(id2label[out])
    return result

Cython编译python

from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension

extensions = [
    Extension(name='name1',
              sources=['source file'],
              include_dirs=['head files'],
              libraries=['library names'],
              library_dirs=['library directories']),
    Extension(name='name2',
              sources=['source file'],
              include_dirs=['head files'],
              libraries=['library names'],
              library_dirs=['library directories'])
]
# setup.py 放在 sources同目录
# 按照上述方式配置,会生成两个so,name1.so和name2.so
# 命令:python setup.pu build_ext,同时生成c文件和so
setup(
    name='name',
    # language_level=3指定python3
    ext_modules=cythonize(extensions, language_level=3)
)

参考

https://github.com/oborchers/sentence-transformers/blob/72da7293186700bff4fed8e81adcfe40a03be1d2/examples/onnx_inference/onnx_inference.ipynb

https://zhuanlan.zhihu.com/p/422290231

服务器后台远程复制文件scp

正常执行scp命令

从一台服务器复制文件夹到另一台服务器

scp -r origin_dir ip:target_dir

输入Ctrl+z暂停任务

使用bg命令将其放入后台

bg %1

使用jobs查看状态,已经在后台运行了

disown -h 将这个作业忽略HUP信号

查看运行状态和父进程号

ps -ef | grep scp

测试会话中断,任务继续运行不受影响

首先退出

exit

然后再查看状态

ps -ef | grep scp

参考

https://blog.csdn.net/sraing/article/details/85121543

ImportError: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `CXXABI_1.3.11′

报错信息

在docker中安装faiss后,测试可以正常导入,但是程序跑起来就会报错,报错信息如下:

ImportError: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `CXXABI_1.3.11′ not found (required by /root/anaconda3/envs/cpu/lib/python3.6/site-packages/faiss/../../../libfaiss.so)

解决方案

首先查看导入错误的目录上有什么文件,发现确实没有需要的“`CXXABI_1.3.11”

strings /usr/lib/x86_64-linux-gnu//libstdc++.so.6 | grep CXXABI

ll /usr/lib/x86_64-linux-gnu//libstdc++.so.6

find /usr -name “libstdc++.so.*”

find / -name “libstdc++.so.*”

cp /root/anaconda3/envs/cpu/lib/libstdc++.so.6.0.29 /usr/lib/x86_64-linux-gnu/

cd /usr/lib/x86_64-linux-gnu/

find /usr -name “libstdc++.so.*”

rm libstdc++.so.6

ln -s libstdc++.so.6.0.29 libstdc++.so.6

strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep CXXABI

参考

https://blog.csdn.net/wenroudebaozi/article/details/107564647