C#使用词嵌入向量与向量数据库为大语言模型(LLM)赋能长期记忆实现私域问答机器人落地之openai接口平替

------------恢复内容开始------------

在上一篇文章中我们大致讲述了一下如何通过词嵌入向量的方式为大语言模型增加长期记忆,用于落地在私域场景的问题。其中涉及到使用openai的接口进行词嵌入向量的生成以及chat模型的调用

由于众所周知的原因,国内调用openai接口并不友好,所以今天介绍两款开源平替实现分别替代词嵌入向量和文本生成。

照例还是简单绘制一下拓扑图:

 从拓扑上来看还是比较简单的,一个后端服务用于业务处理,两个AI模型服务用于词嵌入向量和文本生成以及一个向量数据库(这里依然采用es,下同),接着我们来看看流程图:

从流程图上来讲,我们依然需要有两个阶段的准备,在一阶段,我们需要构建私域回答的文本,这些文本往往以字符串的形式被输入到嵌入接口,然后获取到嵌入接口的嵌入向量。再以es索引的方式被写入到向量库。而在第二阶段,也就是对外提供服务的阶段,我们会将用户的问题调用嵌入接口生成它的词嵌入向量,然后通过向量数据库的文本相似度匹配获取到近似的回答,比如提问“青椒炒肉时我的盐应该放多少”。向量库相似的文本里如果包含了和该烹饪有关的文本会返回1到多条回答。接着我们在后端构建一个prompt,和之前的文章类似。最后调用我们的文本生成模型进行问题的回答。整个流程结束。

接下来我们看看如何使用和部署这些模型以及c#相关代码的编写

重要:在开始之前,请确保你的部署环境安装了16G显存的Nvidia显卡或者48G以上的内存。前者用于基于显卡做模型推理,效果比较好,速度生成合理。后者基于CPU推理,速度较慢,仅可用于部署测试。如果基于显卡部署,需要单独安装CUDA11.8同时需要安装nvidia-docker2套件用于docker上的gpu支持,这里不再赘述安装过程

首先我们需要下载词嵌入模型,这里推荐使用text2vec-large-chinese这个模型,该模型针对中文文本进行过微调。效果较好。

下载地址如下:http://huggingface.co/GanymedeNil/text2vec-large-chinese/tree/main

我们需要下载它的pytorch_model.bin、config.json、vocab.txt这三个文件用于构建我们的词嵌入服务

接着我们在下载好的文件夹里,新建一个web.py。输入以下内容:

from fastapi import FastAPI
from pydantic import BaseModel
from typing import List
from transformers import AutoTokenizer, AutoModel
import torch

app = FastAPI()

# Load the model and tokenizer
model = AutoModel.from_pretrained("/app").half().cuda()
tokenizer = AutoTokenizer.from_pretrained("/app")


# Request body
class Sentence(BaseModel):
    sentence: str


@app.post("/embed")
async def embed(sentence: Sentence):
    # Tokenize the sentence and get the input tensors
    inputs = tokenizer(sentence.sentence, return_tensors='pt', padding=True, truncation=True, max_length=512)

    # Move inputs to GPU
    for key in inputs.keys():
        inputs[key] = inputs[key].to('cuda')

    # Run the model
    with torch.no_grad():
        outputs = model(**inputs)

    # Get the embeddings
    embeddings = outputs.last_hidden_state[0].cpu().numpy()

    # Return the embeddings as a JSON response
    return embeddings.tolist()

    以上是基于gpu版本的api。如果你没有gpu支持,那么可以使用以下代码:

from fastapi import FastAPI
from pydantic import BaseModel
from typing import List
from transformers import AutoTokenizer, AutoModel
import torch

app = FastAPI()

# Load the model and tokenizer
model = AutoModel.from_pretrained("/app").half()
tokenizer = AutoTokenizer.from_pretrained("/app")

# Request body
class Sentence(BaseModel):
    sentence: str

@app.post("/embed")
async def embed(sentence: Sentence):
    # Tokenize the sentence and get the input tensors
    inputs = tokenizer(sentence.sentence, return_tensors='pt', padding=True, truncation=True, max_length=512)

    # No need to move inputs to GPU as we are using CPU

    # Run the model
    with torch.no_grad():
        outputs = model(**inputs)

    # Get the embeddings
    embeddings = outputs.last_hidden_state[0].cpu().numpy()

    # Return the embeddings as a JSON response
    return embeddings.tolist()

这里我们使用一个简单的pyhont web框架fastapi对外提供服务。接着我们将之前下载的模型和py代码放在一起,并且创建一个 requirements.txt用于构建镜像时下载依赖, requirements.txt包含

torch
transformers
fastapi
uvicorn

其中前两个是模型需要使用的库/框架,后两个是web服务需要的库框架,接着我们在编写一个Dockerfile用于构建镜像:

FROM python:3.8-slim-buster

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Run app.py when the container launches
ENV MODULE_NAME=web 
ENV VARIABLE_NAME=app
ENV HOST=0.0.0.0
ENV PORT=80

# Run the application:
CMD uvicorn ${MODULE_NAME}:${VARIABLE_NAME} --host ${HOST} --port ${PORT}

接着我们就可以基于以上内容构建镜像了。直接执行docker build . -t myembed:latest等待编译即可

镜像编译完毕后,我们可以在本机运行它:docker run -dit --gpus all -p 8080:80 myembed:latest。注意如果你是cpu环境则不需要添加“--gpus all”。接着我们可以通过postman模拟访问接口,看是否可以生成向量,如果一切顺利,它将生成一个嵌套的多维数组,如下所示: 

 接着我们需要同样的办法去炮制语言大模型的接口,这里我们采用国内相对成熟的开源大语言模型Chat-glm-6b。首先我们新建一个文件夹,然后用git拉取它的web服务相关的代码:

git clone http://github.com/THUDM/ChatGLM-6B.git

接着我们需要下载它的模型权重文件,地址:http://huggingface.co/THUDM/chatglm-6b/tree/main。下载从pytorch_model-00001-of-00008.bin到pytorch_model-00008-of-00008.bin的8个权重文件放在git根目录

接着我们修改api.py的代码:

from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
from transformers import AutoTokenizer, AutoModel
import uvicorn, json, datetime
import torch
import asyncio

DEVICE = "cuda"
DEVICE_ID = "0"
CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE


def torch_gc():
    if torch.cuda.is_available():
        with torch.cuda.device(CUDA_DEVICE):
            torch.cuda.empty_cache()
            torch.cuda.ipc_collect()

app = FastAPI()

@app.post("/chat", response_class=StreamingResponse)
async def create_item(request: Request):
    global model, tokenizer
    json_post_raw = await request.json()
    json_post = json.dumps(json_post_raw)
    json_post_list = json.loads(json_post)
    prompt = json_post_list.get('prompt')
    history = json_post_list.get('history')
    max_length = json_post_list.get('max_length')
    top_p = json_post_list.get('top_p')
    temperature = json_post_list.get('temperature')
    
    last_response = ''
    async def stream_chat():
        nonlocal last_response,history
        for response, history in model.stream_chat(tokenizer,
                                                prompt,
                                                history=history,
                                                max_length=max_length if max_length else 2048,
                                                top_p=top_p if top_p else 0.7,
                                                temperature=temperature if temperature else 0.95):
            new_part = response[len(last_response):]
            last_response = response
            yield json.dumps(new_part,ensure_ascii=False)
            
    return StreamingResponse(stream_chat(), media_type="text/plain")


if __name__ == '__main__':
    tokenizer = AutoTokenizer.from_pretrained("/app", trust_remote_code=True)
    model = AutoModel.from_pretrained("/app", trust_remote_code=True).half().cuda()
    model.eval()
    uvicorn.run(app, host='0.0.0.0', port=80, workers=1)

同样的如果你是cpu版本的环境,你需要将(这里注意,如果你有显卡,但是显存并不足16G。那么可以考虑8bit或者4bit量化,具体参阅http://github.com/THUDM/ChatGLM-6B的readme.md)

model = AutoModel.from_pretrained("/app", trust_remote_code=True).half().cuda()

 修改为

model = AutoModel.from_pretrained("/app", trust_remote_code=True)

剩余的流程和之前部署向量模型类似,由于项目中已经包含了,创建对应的 requirements.txt,我们只需要创建类似词嵌入向量的Dockerfile即可编译。

FROM python:3.8-slim-buster
WORKDIR /app
ADD . /app
RUN pip install -r requirements.txt -i http://pypi.tuna.tsinghua.edu.cn/simple
CMD ["python", "api.py"]

完成后可以使用docker run -dit --gpus all -p 8081:80 myllm:latest启动测试,同样的使用postman模拟访问接口,顺利的话我们应该能够看到如下内容不要在意乱码的部分那是emoji没有正确解析的问题:

 

接下来我们需要构建c#后端代码,将这些基础服务连接起来,这里我使用一个本地静态字典来模拟词嵌入向量的存储和余弦相似度查询相似文本,就不再赘述使用es做向量库,两者的效果基本一致的。感兴趣的同学去搜索NEST库和es基于余弦相似度搜索相关的内容即可

核心代码如下,这里我提供两个接口,第一个接口用于获取前端输入的文本做词嵌入并进行存储,第二个接口用于回答问题。

///用于模拟向量库    
private Dictionary<string, List<double>> MemoryList = new Dictionary<string, List<double>>();
///用于计算相似度
double Compute(List<double> vector1, List<double> vector2) => vector1.Zip(vector2, (a, b) => a * b).Sum() / (Math.Sqrt(vector1.Sum(a => a * a)) * Math.Sqrt(vector2.Sum(b => b * b)));
...
    [HttpPost("/api/save")]
    public async Task<int> SaveMemory(string str)
    {
        if (!string.IsNullOrEmpty(str))
        {
            foreach (var x in memory.Split("\n").ToList())
            {
                if (!MemoryList.ContainsKey(x))
                {
                    MemoryList.Add(x, await GetEmbeding(x));
                    StateHasChanged();
                }
            }
        }
        return MemoryList.Count; 
    }
...
    [HttpPost("/api/chat")]
    public async IAsyncEnumerable<string> SendData(string content)
    {
        if (!string.IsNullOrEmpty(content))
        {
            var userquestionEmbeding = await GetEmbeding(content);
            var prompt = "";
            if (MemoryList.Any())
            {  //这里从向量库中获取到第一条,你可以根据实际情况设置比如相似度阈值或者返回多条等等
                prompt = MemoryList.OrderByDescending(x => Compute(userquestionEmbeding, x.Value)).FirstOrDefault().Key;
                prompt = $"你是一个问答小助手,你需要基于以下事实依据回答问题,事实依据如下:{prompt}。用户的问题如下:{Content}。不要编造事实依据,请回答:";
            }
            else
                prompt = Content;
            await foreach (var item in ChatStream(prompt))
            {
                yield return item;
            }
        }
    }

同时我们需要提供两个函数用于使用httpclient访问AI模型的api:

async IAsyncEnumerable<string> ChatStream(string x)
    {
        HttpClient hc = new HttpClient();
        var reqcontent = new StringContent(System.Text.Json.JsonSerializer.Serialize(new { prompt = x }));
        reqcontent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
        var response = await hc.PostAsync("http://192.168.1.100:8081/chat", reqcontent);
        if (response.IsSuccessStatusCode)
        {
            var responseStream = await response.Content.ReadAsStreamAsync();
            using (var reader = new StreamReader(responseStream, Encoding.UTF8))
            {
                string line;
                while ((line = await reader.ReadLineAsync()) != null)
                {
                    yield return line;
                }
            }
        }
    }
    async Task<List<double>> GetEmbeding(string x)
    {
        HttpClient hc = new HttpClient();
        var reqcontent = new StringContent(System.Text.Json.JsonSerializer.Serialize(new { sentence = x }));
        reqcontent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
        var result = await hc.PostAsync("http://192.168.1.100:8080/embed", reqcontent);
        var content = await result.Content.ReadAsStringAsync();
        var embed = System.Text.Json.JsonSerializer.Deserialize<List<List<double>>>(content);
        var embedresult = new List<double>();
        for (var i = 0; i < 1024; i++)
        {
            double sum = 0;
            foreach (List<double> sublist in embed)
            {
                sum += (sublist[i]);
            }
            embedresult.Add(sum / 1024);
        }
        return embedresult;
    }

  接下来我们可以测试一下效果,当模型没有引入记忆的情况下,询问一个问题,它会自己编造回答:

 接着我们在向量库中添加多条记忆后再进行问询,模型即可基本正确的对内容进行回答。

 

以上就是本次博客的全部内容,相比上一个章节我们使用基于openai的接口来讲基于本地部署应该更符合大多数人的情况,以上

本文转载于网络 如有侵权请联系删除

相关文章

  • AndroidManifest.xml详解

    AndroidManifest官方解释是应用清单(Manifest意思是货单),每个应用的根目录中都必须包含一个,并且文件名必须一模一样。这个文件中包含了APP的配置信息,系统需要根据里面的内容运行APP的代码,显示界面。AndroidManifest.xml样例以下XML文件为AndroidManifest.xml的一个简单示例,该示例为应用声明两个Activity。<?xmlversion="1.0"encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.example.myapp"> <!--Bewarethatthesevaluesareoverriddenbythebuild.grad

  • Kafka与Spark Streaming整合

    Kafka与SparkStreaming整合概述SparkStreaming是一个可扩展,高吞吐,容错能力强的实时流式处理处理系统。一般的系统架构图是,数据从一个源点,经过SparingStreaming处理,最后汇聚到一个系统。SparkStreaming的数据来源可以非常丰富,比如Kafka,Flume,Twitter,ZeroMQ,Kinesis或者是任何的TCPsockets程序。对于数据的处理,SparkStreaming提供了非常丰富的高级api,例如map,redue,joini和窗口函数等等。数据处理完成后,可以存储到其他地方,比如文件系统,对象存储,数据库。典型的数据处理流程图:概念简介RDD:ResilientDistributedDatasets,弹性分部署数据集,支持两种操作:转换(transformation)从现有的数据集创建一个新的数据集;动作(actions)在数据集上运行计算后,返回一个值给驱动程序。在这里简单理解为某个时间片的数据集合即可。DStream:和RDD概念有点类似,是RDD的集合,代表着整个数据流。简单来说SparkStreaming中的

  • 多家技术公司喊停的人脸识别业务,被这家波兰网站玩火了!

    大数据文摘出品作者:刘俊寰受弗洛伊德事件影响,6月10日,美国科技巨头IBM宣布正式放弃人脸识别技术,紧接着第二天,亚马逊表示停止对警方提供面部识别技术。BlackLivesMatter运动对全世界科技界以及人脸识别领域都产生了重要影响。在人脸识别技术饱受诟病的当下,偏偏就有这么一个新的人脸识别网站选择“逆流而上”。日前,波兰的一家面部识别网站PimEyes在国外掀起一股热议浪潮,任何人都能在网站上进行搜索,并且该网站表示,它们能够从Tumblr、YouTube、WordPress等社交媒体和新闻机构等公开网站上找到这个人的更多照片。听上去和年初火爆美国、如今惨遭起诉的ClearviewAI没有太大区别,不过,与ClearviewAI和全球警方和执法机构进行合作不同,PimEyes主要服务于保护个人隐私和防止滥用图像,但是这并不能阻止其他人上传自己的照片,针对此,PimEyes尚未置评。PimEyes测评:这个人脸识别网站到底有多强大?到底PimEyes有没有自己所宣称的那么强大,我们先来进行一次测评。首先,我们用英国首相BorisJohnson的照片先试一下水,结果发现,识别效果的确

  • 热点聚焦 | 5G与文化产业会碰撞出怎样的火花

    今年全国两会,新闻中心首次实现了5G信号全覆盖,不少代表委员积极关注5G的应用。近日,2019年世界移动通信大会在西班牙巴塞罗那举行。会上,华为发布了5G折叠屏手机,各大厂商也竞相推出5G应用解决方案,这让人们对5G时代满怀憧憬。在未来万物互联的时代,5G与文化产业会碰撞出怎样的火花?5G将为文化产业带来哪些机遇和挑战?光明图片/视觉中国【案例】日前,中国联通已完成对北京梅地亚中心新闻发布厅等区域的5G全覆盖,为参与全国两会报道的媒体记者提供5G网络。中国移动也在天安门广场、北京会议中心等地建设了5G网络,以保障“5G+4K”高清直播效果。5G会给老百姓带来什么?中国联通研究院院长张云勇委员这样描述:“清晨,5G路由器悦耳的声音叫醒你,智能床垫感知你的睡眠情况,然后连接咖啡机送上一杯浓淡相宜的咖啡……”在他看来,5G不仅快,而且非常智能,将改变行业,改变社会。那么,5G到底有多快?在业内有一个比喻:如果把2G比作自行车,3G就是摩托车,4G是汽车,5G则是高铁。“别看5G手机和4G手机看起来没什么区别,速度却是4G的好几倍,下载一部1G左右的高清大片只需要3秒钟。”张云勇委员说。对于文

  • 当Cocos2dx遇见Android,你猜猜

    简述:这篇文章适合已经用cocos2dx开发过游戏(demo也可以)的人和对cocos2dx有兴趣的人阅读。cocos2dx开发的游戏由GLSurfaceView加c、c++代码生成的.so组成。前者可以当做android里的普通view使用,比如放在一个布局里,弹一个popwindow,指定大小等。后者是通过在一个游戏引擎(cocos2dx)里用c,c++代码按照引擎的游戏框架进行开发后通过ndk编译生成的。下面我将通过演示如何在android端设置cocos2dx游戏界面的大小来说明cocos2dx引擎所运行的GLSurfaceView可以当成一个普通的view来使用。当创建一个cocos2dx工程后,会生成android工程目录。可以看到主Activity是继承自Cocos2dxActivity的。我们从oncreate函数一路跟下去可以看到init()方法,如下:publicvoidinit(){//FrameLayout ViewGroup.LayoutParamsframelayout_params= newViewGroup.LayoutParams(ViewGroup.

  • 从 Linux 操作系统谈谈 IO 模型(终)

    【这是一猿小讲的第86篇原创分享】Linux为什么要区分内核空间与用户空间? Linux操作系统的IO模型有哪几种?有啥区别? 常说的阻塞现象,到底是咋回事? 网络编程研发时,那块到底耗时最多,代码是否还有优化空间?前几期的分享,我们站在编码视角去聊JavaIO,旨在理解与编码,本次从Linux操作系统层面了解一下IO模型,这样方能做到知其然,知其所以然。 01.内核空间、用户空间 万事万物我们看到的皆是表象,操作系统也不例外。我们经常打交道的用户界面,是操作系统的外在表象,内核才是操作系统的内在核心。内核,可以访问受保护的内存空间,拥有访问底层硬件设备的所有权限(比如读写磁盘文件,分配回收内存,从网络接口读写数据等等)。为了内核的安全,操作系统将虚拟空间划分为内核空间(内核代码运行的地方)和用户空间(用户程序代码运行的地方)。内核空间和用户空间是隔离的,这样即使用户的程序崩溃了,内核也不受影响。另外,用户程序不能直接操作内核,需要通过系统调用来与内核进行通信(应用程序通过内核提供的接口来完成访问)。02.Socket通信流程Socket通信流程应该不再陌生,本次分享着重剖析图中圈住

  • minigui:解决gvfb编译报错undefined reference to symbol 'XkbGetIndicatorState'

    版权声明:本文为博主原创文章,转载请注明源地址。https://blog.csdn.net/10km/article/details/83380130minigui在linuxPC平台创建开发环境时,需要VirtualFrameBuffer支持(gvfb,qvfb),minigui官网提供了这两个程序的源码,需要自己下载编译并安装到自己的PC上。我用的是gvfb,minigui下载地址:http://www.minigui.org/downloads/gvfb-1.0.0.tar.gz编译安装过程不复杂: 编译需要cmake支持,如果没有请安装:sudoapt-getinstallcmake 还需要依赖gtk2.0,如果没有请安装:sudoapt-getinstalllibgtk2.0-dev#下载 wgethttp://www.minigui.org/downloads/gvfb-1.0.0.tar.gz #解包 tarxvfgvfb-1.0.0.tar.gz cdgvfb-1.0.0 mkdirbuild cdbuild #生成Makefile cmake.. #编译并安装 sud

  • 使用模式构建:近似值模式

    在MongoDB中文社区学习更多关于MongoDB的知识和技能假设现在有一个相当规模的城市,大约有3.9万人。人口的确切数字是相当不稳定的,人们会搬入搬出、有婴儿会出生、有人会死亡。我们也许要花上整天的时间来得到每天确切的居民数量。但在大多数情况下,39,000这个数字已经“足够好”了。同样,在许多我们开发的应用程序中,知道“足够好”程度的数字就可以了。如果一个“足够好”的数字就够了,那么这就是一个应用近似值模式的好机会。近似值模式在所需要的计算非常有挑战性或消耗的资源昂贵(时间、内存、CPU周期)时,如果精度不是首要考虑因素时,那么我们就可以使用近似值模式。再回顾一下人口问题,精确计算这个数字的成本是多少?从我开始计算起,它将会改变还是可能会改变?如果这个数字被报告为39,000,而实际上是39,012,这会对这个城市的规划战略产生什么影响?从应用程序的角度看,我们可以构建一个近似因子,它允许对数据库进行更少写入的同时仍然提供统计上有效的数字。例如,假设我们的城市规划是基于每10000人需要一台消防车,那么用100人作为这个计划的“更新”周期看起来就不错。“我们正接近下一个阈值了,最

  • 徐妈说,他常常因为不太会 Linux 而感到难过

    这些问题或者场景,你是否曾经遇到过?流量高峰期,服务器CPU使用率过高报警,你登录Linux上去top完之后,却不知道怎么进一步定位,到底是系统CPU资源太少,还是程序并发部分写的有问题?系统并没有跑什么吃内存的程序,但是敲完free命令之后,却发现系统已经没有什么内存了,那到底是哪里占用了内存?为什么?一大早就收到Zabbix告警,你发现某台存放监控数据的数据库主机CPU的I/OWait较高,这个时候该怎么办?Linux日志不会排查作为一个程序员,性能优化是无法避开的事情,不管是桌面应用还是web应用,不管是前端还是后端,不管是单点应用还是分布式系统,并且性能优化也是软件系统中最有挑战的工作之一,更是每个工程师都需要掌握的核心技能。但是在实际的工作中,很多情况下只能看到症状,却完全不知道该从哪儿下手去排查和解决它。网上的资料和书籍可以扩充底层知识体系,从虚拟化的原理、到操作系统和网络原理、再到Linux内核和硬件驱动程序等等。但是Linux性能优化是个系统工程,除了基础知识点之外,学习中还有两点是比较重要的,第一、要学习大量性能优化的思路和方法,尝试大量的Linux性能工具。第二、要

  • 边学边用Gradle:依赖管理

    什么是依赖管理?粗略的讲,依赖管理由两部分组成:项目的 dependencies(依赖项) 和 publications(发布项)。Gradle需要了解你的项目需要构建或运行的东西,以便找到它们。我们称这些传入的文件为项目的dependencies(依赖项)。Gradle需要构建并上传你的项目产生的东西。我们称这些传出的项目文件为 publications(发布项)。依赖简言为个人理解,细说为出处。若对简言不清楚,可查看理解细说部分。简言:根据配置获取依赖关系的过程为 dependencyresolution(依赖解析) 。项目运行时寻找到其依赖关系并使其可用的过程为dependencyresolution(依赖解析) 。细说:大多数项目都不是完全独立的,它们需要其它项目进行编译或测试等等 。举个例子,为了在项目中使用Hibernate,在编译的时候需要在classpath中添加一些Hibernate的jar路径.要运行测试的时候,需要在testclasspath中包含一些额外的jar,比如特定的JDBC驱动或者Ehcachejars.这些传入的文件构成上述项目的依赖。Gradle允许

  • 第12周Python学习周记

    &关于计划: 一、Numpy库的学习(学习完毕);二、Matplotlib的学习(进行中,预计13周之内完成);三、Markdown的学习(进行中);(本文内容参考于简书教程)&时间:第12周 &内容摘要: 一、1.当我们对数组进行操作的时候,我们需要注意一个很重要的概念——复制和视图 (1)完全不复制:(一个数据域,一个数组对象,多个名字)①简单的赋值不会创建数组对象或其数据的拷贝:>>>importnumpyasnp>>>a=np.arange(12)>>>b=a                #没有创建新的对象>>>bisa                  #a和b是同一数                          组对象的两个名字True>>>b.shape=3,4          #改变b的形状(同                      时改变b的形状——因为a                      和b引用同一数组对象)>>>

  • 给你的Windows加一个 「文件快速预览」功能

    在macOS中,有一个非常好用的功能叫做QuickLook,当你在Finder想要查看一个文件时,不需要打开,只需要选中以后按空格即可预览大部分常见文件,Windows中虽然没有这样的功能(自带的预览窗格很浪费资源还很慢),但是开发者们可不会放掉这样的功能,今天的主角QuickLook就是这样一个应用,同样的,它是开源免费的!使用帮助:①QuickLook有三种安装方式,普通的安装程序安装、便携版解压即可使用、win10应用商店UWP版(点击图片即可放大)安装版便携版UWP②打开应用以后,没有主界面,会在系统托盘区出现一个托盘,默认开机自启(心甘情愿的让他自启吧,很良心)③操作说明:空格键:预览/关闭预览ESC:关闭预览回车:运行程序并关闭预览CTRL+鼠标滚轮:缩放图片/文档鼠标滚轮:调节音量③QuickLook支持以下格式:图片:.png,.jpg,.bmpand.gif压缩包:.zip,.rar,.7zPDF文件文本文件MicrosoftWord(.doc,.docx),Excel(.xls,.xlsx)andPowerPoint(.ppt,.pptx)files(需要安装Off

  • 孙明俊:中国云计算产业发展现状

    7月15日至7月16日,由工业和信息化部指导,工信部电信研究院、中国通信标准化协会主办,数据中心联盟和云计算发展与政策论坛承办的"2014可信云服务大会"在北京国际会议中心盛大召开。本次会议以"可信中国云未来新生态"为主题,积极推动了国内可信云服务认证体系的建立,促进云计算产业良性发展。工信部总工程师张峰、财政部政府采购管理办公室主任王瑛、中央国家机关政府采购中心主任王力达、工信部电信研究院院长曹淑敏、中国通信标准化协会秘书长杨泽民、工信部通信发展司副司长陈家春等重量级嘉宾均出席了会议。其中数据中心联盟秘书长孙明俊也应邀出席了大会并发表精彩演讲"中国云计算产业发展现状"。以下为孙明俊演讲实录:孙明俊:感谢大家在这个时间,还留在这个会场,我演讲的内容是中国云计算发展状况。之所以要做这样一个情况的汇报,有两个方面的考虑。第一、整个的发展思路,都是根据云计算的发展情况来提出来的。第二我们也希望了解现在云计算的发展状况,看下一步可信云做什么样的工作。数据中心联盟我们可以做一些什么新的领域推动云计算的发展。首先我们来看一下,介绍中国的云

  • 前百度首席科学吴恩达与鸿海合建新公司 把AI引入工厂

    【TechWeb报道】12月15日消息,据国外媒体报道,前百度首席科学吴恩达(AndrewNg)周四宣布和苹果代工厂鸿海合建新公司Landing.ai,想把AI和机器学习引入工厂。Landing.AI旨在帮助企业进行人工智能转型。该公司称首先会关注制造业。吴恩达日前在旧金山的新闻发布会上展示了一个案例,在一家工厂的质量控制过程中使用AI进行外观检查。在很多工厂,是由工人查看从组装线下线的零部件是否存在缺陷。吴恩达播放了一段视频,显示一名工人将一块电路板放在与电脑连接的数字摄像机下方,电脑就能够辨识出零部件的缺陷。吴恩达说,通常情况下“训练”电脑视觉系统可能需要数千个样本图像,但Landing.ai的系统只需要五张训练图像,从而更容易适应工厂中的不同任务。Landing.ai官网介绍称,“人工智能可以通过自适应制造,自动质量控制,预测性维护等解决方案有效地应对当今制造业面临的挑战。我们已经为许多制造行业的合作伙伴提供了视觉检测,自动化控制,智能化校准以及问题根源分析等解决方案。”鸿海是Landing.ai的首个战略合作伙伴。吴恩达表示,7月以来Landing.ai就一直在与鸿海合作,但他

  • 手 Q 人脸识别动画实现详解

    前言开门见山,先来看下效果吧。看到这么酷炫的效果图,不得不赞叹一下我们的设计师。然而,站在程序员的角度上看,除了酷炫之外更多的是复杂。但是,上面我们所看到的还只是最简单的一种形态而已。更加复杂的情况是当存在多个人脸的时候进行主次脸动画的切换,摄像头移动的时候动画的追踪,多个动画的之间的时序控制等问题,总之,UI展示加上各种业务逻辑使得这个动画变得异常复杂。今天我们要讲解的是剔除业务逻辑之外的单纯UI上的实现。为什么是SurfaceView选择一种方案的同时要给出为什么不选择另一种的理由是什么。没错,为什么这里不用自定义Vew来完成绘图呢?既然自定义View也可以实现一般的动画效果,为什么还要引入SurfaceView呢?可以把View理解为一个经过系统优化的,可以用来高效执行一些帧数比较低动画的对象,但是对于灵活性更高的动画来说,View并不是最好的选择。同时,对于普通的View它们都是在应用程序的主线程中进行绘制的,我们知道在Android系统上我们不能够在主线程做一些耗时的操作,否则会引起ANR。对于一些游戏画面,或者摄像头预览、视频播放来说,它们的UI都比较复杂,而且要求能够进行

  • Hive安装与部署集成mysql

    前提条件: 1、一台配置好hadoop环境的虚拟机。hadoop环境搭建教程:稍后补充 2、存在hadoop账户。不存在的可以新建hadoop账户安装配置hadoop。 安装教程:   一、Mysql安装 1、安装mysql命令:Yuminstallmysql-server-y  (-y参数作用为所有需要输入yes的地方默认yes) 2、打开mysql服务:Servicemysqldstart 3、设置mysql服务开机自启动(也可以不设置,开机手动启动):chkconfig–addmysqld 4、进入mysql命令行:mysql -uroot -p  (root是账户不是必须root) 第一次进入不需要输密码可以直接:mysql命令进入mysql 5、设置密码-第一次没有密码情况下设置:mysqladmin-urootpasswordqixiao123    ->如果不在第5步设置,也可以在Mysql命令行下修改密码(先进入mysql):updateusersetpassword=password(‘新密

  • WEB自动化-08-Cypress 接口测试

    8接口测试   在服务和服务、系统和系统之间进行通信时,常常会使用到接口。通过接口测试,可以在项目早期更快发现问题。接口有很多类型,而现阶段使用的接口是基于HTTP协议的接口。 8.1Cypress支持的HTTP请求方式   在Cypress中发起HTTP请求时,需要使用到的命令为cy.request(),其基本语法格式如下所示: cy.request(url) cy.request(url,body) cy.request(method,url) cy.request(method,url,body) cy.request(options) 复制   主要参数详细信息如下所示: url   url(String),发起请求的接口地址。需要注意的事项如下所示:   1、如果cy.request()在cy.visit()后发起请求时,则Cypress将默认使用cy.visit()中的域名做为发起接口请求的域名地址,示例如下所示: cy.visit('https://www.surpassme.com/app') cy.request('users/add')//实际访问的URL:ht

  • springboot+aop切点记录请求和响应信息

      本篇主要分享的是springboot中结合aop方式来记录请求参数和响应的数据信息;这里主要讲解两种切入点方式,一种方法切入,一种注解切入;首先创建个springboot测试工程并通过maven添加如下依赖: <!--AOP--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!--阿里FastJson依赖--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.44</version> </dependency>复制   先来说方法的切点方式,需要创建个名为Log

  • 嵌入式编程中,如何使用复杂指针?

    1.说明 在C语言编程中,指针是最容易出错的地方,尤其是在很多指针同时出现的时候,看的眼花缭乱的,本文从嵌入式中常用的复杂角度进行分析,彻底搞清楚C语言中的容易弄错的指针使用问题。   2.函数指针与指针函数 在C语言中,函数是有他的地址,同理,函数有也有他的地址,如果如果我们把函数的地址赋值给函数指针,那么我们就可以间接的通过函数指针调用函数地址了。   函数指针的定义如下:   数据类型(*fun)(参数列表); 由于()的优先级高于*。   指针函数的定义如下:   数据类型*fun(参数列表); 其返回值为数据类型*。   实例:通过函数指针调用函数指针   第一步:定义函数指针   int*(*pfun)(int*,int*); 这里调用了一个数据类型为int*的函数指针,其中两个参数为两个int*。   第二步:定义指针函数   int*fun(int*,int*); 这里函数的返回值是int*。   第三步:实现函数指针   int*fun(int*a,

  • cocoapods公有库创建

    第一步:在git上创建一个项目(项目名为库名),并克隆到本地。    第二步:在本地仓库中创建一个项目PodDemo,并将我们想要共享的库单独放入一个文件夹        第三步:推送到远程仓库,并打上tag为0.0.1。    这里需要注意,打tag的目的是为了三方库可设置成以我们打的tag为版本定义 第四步:注册   podtrunkregisterfusheng_it@163.com "makeKeyReuse"     验证   podtrunkme   注册完成后,会有一封邮件发送到该邮箱,我们也可以打开发送到邮箱的链接验证是否成功 第五步:生成spec文件   1>cd./FSPodDemo/PodDemo //这里我们cd到项目目录    2>podspeccreate https://github.com/fushengit/FSPodDemo 红色部分为git上的项目地址   第六步:编辑spec文件       s.version:显示三方库版本的版本号   s.

  • STL容器中的erase函数调用问题

    自我感觉,erase函数返回一个迭代器,指向被删除元素的下一个位置,不是很合理。 啥也不说,直接上代码: intfindNum=2;   intarray[]={1,2,2,4,5,6};   vector<int>ivec(array,array+sizeof(array)/sizeof(*array));   for(vector<int>::iteratoriter=ivec.begin();i!=ivec.end(),iter++)   {      if(*iter==findNum)      {         iter=ivec.erase(iter);      

相关推荐

推荐阅读