当前位置: 首页 > news >正文

福布斯 AI 50 榜单中唯一开源向量数据库:Weaviate

本篇文章,聊聊福布斯全球网站前俩月发布的 2023 AI 50 榜单中的唯一一个开源的向量数据库:Weaviate。

它在数据持久化和容错性上表现非常好、支持混合搜索、支持水平扩展,同时又保持了轻量化。官方主打做 AI 时代的原生数据库,减少幻觉、数据泄漏和厂商绑定。

写在前面

本文相关的代码和配置,我开源在了 soulteary/weaviate-quickstart,有需要自取,欢迎“一键三连”。

言归正传,随着越来越多的传统数据库和搜索引擎对于向量数据检索能力的完善(MySQL、PostgreSQL、MongoDB、Elasticsearch、Redis、ClickHouse …),专用的向量数据库的能力要求被不断拔高,伴随着不时传来的“向量数据库已死”、“只是一个数据库功能”的观点,4 月 11 日福布斯全球网站发布的 2023 AI 50 榜单中,只有两家做向量数据库的公司登陆了名单。

第一家,是一直以来在北美市场生态建设做的非常好的“松果”(Pinecone),产品做的非常好,拥有目前最强的产品生态和文档建设,CEO 为前 AWS & Yahoo 的研发总监,年初刚刚发布了 Serverless 版本的新产品。你所知道的:Notion、微软、Shopify、Klarna(欧洲“支付宝”)、ClickUp、HubSpot、Help Scout、TaskUS、Disco、Frontier、GONG、Sixfold、Godaddy、InpharmD、YCombinator 等等都是他们的客户。他们在去年“寒冬”中就募集了 1 亿美元,目前公司估值 7.5 亿美元。

另外一家,是和 Pinecone 同年建立公司,但是选择了开源商业化路线的 Weaviate,在 2023 年公司人数只有 65 人( Pinecone 一半)的情况下,保持非常高的发布和产品迭代频率,B 轮融资 5000 万美元,目前估值 2 亿美元。Pinecone 支持的 Serverless SaaS 服务, Weaviate 同样也是支持的。

不论是从以下哪个角度来看,它都值得我们来试着使用,尤其是你需要稳定不出错的私有化部署,并且不希望进行复杂的运维时

  • 公司的资金充裕程度,或许是垂类创业公司中最宽松的,不需要快速变现能够让产品的迭代质量和目标更有保障。
  • 开发交付能力较好,一年多的时间里,保持了每周都有新版本发布,接近 80 个版本,配合相对完善的自动化测试,让用户可以放心的跟着软件走下去。
  • 所有写操作会立即保存,并且可以容忍程序或系统崩溃,对象和向量都可以随意操作(增删改查)。同时,你也可以随意的备份和恢复数据,不需要担心冗长的数据重建或者业务停服问题。
  • 软件生态越来越完善,从 OpenAI(包括 Azure OAI)、Google AI、AWS、Mistral、Cohere、HuggingFace 等等在线头部厂商到本地化的 Transformers 或其他方式运行的模型,都能快速的集成接入。
  • 部署简单,维护也同样简单,从一台笔记本到一整个集群,都可以使用它,毕竟是“云原生设计”,本地容器化还是云端基于云厂商组件快速扩展都不是问题,毕竟头部厂商和头部云厂商的云市场里都有它的身影。

熟悉我的朋友知道我使用 Dify 有一段时间了,在 Dify 的官方支持中,默认支持的几种向量数据库,最简单的选择一定是 Weaviate(或许最好的选择是 Qdrant,最经济的是 PG Vector,我们下篇再聊)。

好了,接下来,让我们来快速上手非常简单,数据相对安全可靠,并且程序本身不失轻量的向量数据库吧。

准备工作

为了让更多的朋友能够快速上手和复现,本篇文章使用 Docker 来作为基础环境。

Docker 运行环境

想顺滑的完成实践,推荐你安装 Docker,不论你的设备是否有显卡,都可以根据自己的操作系统喜好,参考这两篇来完成基础环境的配置《基于 Docker 的深度学习环境:Windows 篇》、《基于 Docker 的深度学习环境:入门篇》。当然,使用 Docker 之后,你还可以做很多事情,比如:之前几十篇有关 Docker 的实践,在此就不赘述啦。

向量化模型(Embedding Model)

本篇文章中,我选择的是阿里通义实验室的 GTE 向量模型,你可以在 HuggingFace 或者 ModelScope 上下载到模型。

  • https://huggingface.co/thenlper/gte-base-zh
  • https://modelscope.cn/models/iic/nlp_gte_sentence-embedding_chinese-base

至于模型的下载,你可以选择使用《节省时间:AI 模型靠谱下载方案汇总》这篇文章中提到的下载方法,快速的获取本来就不是很大的模型权重文件。

当然,如果你只想验证下向量数据库,了解下 GTE 模型的,也可以选择更小尺寸的 GTE Small,相比较上面的大尺寸模型,精度并未下降太多(当然,有资源的情况下,还是建议跑大一些的模型,效果会更棒)。

  • https://huggingface.co/thenlper/gte-small
  • https://modelscope.cn/models/iic/nlp_gte_sentence-embedding_chinese-small

在开源项目 soulteary/weaviate-quickstart 中,默认已经集成了身材不到 60M 的模型,你只需要下载开源项目的代码就好啦。

git clone https://github.com/soulteary/weaviate-quickstart.git
cd weaviate-quickstart

用于计算相似度的数据集

为了更好的演示语义检索,我从网上找了一份描述传统节气的内容,并整理为了一份简单的数据集:

[{"SolarTerms": "立春","Title": "木兰花·立春日作","Author": "陆游","Poem": "春盘春酒年年好,试戴银旛判醉倒。今朝一岁大家添,不是人间偏我老。","Description": "《月令七十二候集解》有载:“立,始建也。春气始而建立也。”在生生不息的春风中,一年的序幕由此开启。我们用一颗丰盈而善良的心,向着春意盎然的天地间走去。立春丨一候东风解冻,二候蜇虫始振,三候鱼陟负冰。"},{"SolarTerms": "雨水","Title": "早春呈水部张十八员外","Author": "韩愈","Poem": "天街小雨润如酥,草色遥看近却无。最是一年春好处,绝胜烟柳满皇都。","Description": "雨水是二十四节气之中的第二个节气,此时,气温回升、冰雪融化、降水增多,故取名为雨水。我们将要迎接的,不仅有温暖的晨曦,更是一场被东风吹来的,新的、充满生机的甘霖。雨水丨一候獭祭鱼;二候鸿雁来;三候草木萌动。"},{"SolarTerms": "惊蛰","Title": "走笔谢孟谏议寄新茶","Author": "卢仝","Poem": "闻道新年入山里,蛰虫惊动春风起。天子须尝阳羡茶,百草不敢先开花。","Description": "惊蛰,古称“启蛰”,预示着生命在这一刻重生。春的希望就在眼前,惊蛰过后,万物复苏,一派生机勃勃的景色。让我们且听风吟,且闻鸟语,邂逅最美的花开!惊蛰丨一候桃始华;二候仓庚(黄鹂)鸣;三候鹰化为鸠。"},{"SolarTerms": "春分","Title": "春日","Author": "朱熹","Poem": "胜日寻芳泗水滨,无边光景一时新。等闲识得东风面,万紫千红总是春。","Description": "春分,古时又称为“日中”、“仲春之月”。自此,进入春和日丽、万红千翠争媚时节。好花不常看,好景不常在,趁着风和日丽出门踏青,莫要辜负了好春光。春分丨一候元鸟至;二候雷乃发声;三候始电。"},{"SolarTerms": "清明","Title": "清明","Author": "杜牧","Poem": "清明时节雨纷纷,路上行人欲断魂。借问酒家何处有,牧童遥指杏花村。","Description": "清明是为春天而来,它将蓬勃的生机暗自酝酿。清明节,我们缅怀逝去的家人。清明节,我们思念远方的亲人。生活无遗憾,人世有牵挂!清明丨一候桐始华;二候田鼠化为鹌;三候虹始见。"},{"SolarTerms": "谷雨","Title": "晚春田园杂兴","Author": "范成大","Poem": "谷雨如丝复似尘,煮瓶浮蜡正尝新。牡丹破萼樱桃熟,未许飞花减却春。","Description": "雨我公田,雨其谷于水,播种时节到了。谷雨已至,愿你工作中一“谷”作气,事业高升;朋友间“谷”道热肠,人缘美好;生活中欢欣“谷”舞,快乐舒畅。谷雨丨一候萍始生;二候鸣鸠拂其羽;三候为戴任降于桑。"},{"SolarTerms": "立夏","Title": "初夏","Author": "朱淑真","Poem": "竹摇清影罩幽窗,两两时禽噪夕阳。谢却海棠飞尽絮,困人天气日初长。","Description": "立夏表示即将告别春天,是夏天的开始。立夏之美,在于希望。愿你所有的烦恼,都将随风而去,幸福的感觉似夏花弥漫!立夏丨一候蝼蝈鸣;二候蚯蚓出;三候王瓜生。"},{"SolarTerms": "小满","Title": "自桃川至辰州绝句四十有二","Author": "赵蕃","Poem": "一春多雨慧当悭,今岁还防似去年。玉历检来知小满,又愁阴久碍蚕眠。","Description": "小满,是一年中最有智慧的节气。小有所得,小有所望。我们的生活开始安稳顺遂,有沉静的增长,有从容的精进,小有知足,小有可期。小满丨一候苦菜秀;二候靡草死;三候麦秋至。"},{"SolarTerms": "芒种","Title": "梅雨五绝(其二)","Author": "范成大","Poem": "乙酉甲申雷雨惊,乘除却贺芒种晴。插秧先插蚤籼稻,少忍数旬蒸米成。","Description": "“芒种”也称为“忙种”“忙着种”,预示着要开始忙碌的田间生活。收获过后,又要种下新一轮,人们种下希望的同时,也种下了期待。仲夏至此始,未来皆可期!芒种丨一候螳螂生;二候鵙(jú)始鸣;三候反舌无声。"},{"SolarTerms": "夏至","Title": "积雨辋川庄作","Author": "王维","Poem": "积雨空林烟火迟,蒸藜炊黍饷东菑。漠漠水田飞白鹭,阴阴夏木啭黄鹂。","Description": "夏为大,至为极,万物到此壮大繁茂到极点、阳气也达到极致,所以是一年中夜最短、昼最长的一天。愿你在炎暑,有凉风袭人;愿你在夏日,有良人送爽;愿你向阳而立,拥抱无限生机!夏至丨一候鹿角解;二候蝉始鸣;三候半夏生。"},{"SolarTerms": "小暑","Title": "赠别王侍御赴上都","Author": "韩翃","Poem": "相思掩泣复何如,公子门前人渐疏。幸有心期当小暑,葛衣纱帽望回车。","Description": "小暑,表示季夏时节的正式开始。天气开始炎热,但还没到最热,故称“小暑”。小暑时节,心静自然凉。眼前无长物,窗下有清风。散热有心静,凉生为室空。小暑丨一候温风至;二候蟋蟀居宇;三候鹰始鸷。"},{"SolarTerms": "大暑","Title": "鹧鸪天","Author": "晁补之","Poem": "吉梦灵蛇朱夏宜。佳辰阿母会瑶池。竹风荷雨来消暑,玉李冰瓜可疗饥。","Description": "在骄阳的侵袭下,一年之中最热的时光,也就此拉开序幕。大暑时节,去见想见的人,去做想做的事,在前行的路上不断的遇见美好,遇见幸福,遇见心中期待的一切。大暑丨一候腐草为萤;二候土润溽暑;三候大雨时行。"},{"SolarTerms": "立秋","Title": "城中晚夏思山","Author": "齐己","Poem": "葛衣沾汗功虽健,纸扇摇风力甚卑。苦热恨无行脚处,微凉喜到立秋时。","Description": "立秋是秋季的第一个节气,意味着秋天真正开始了。秋天是思念的季节,思念在远方的亲人,思念外出未归的子女,思念相处一生的伴侣。愿我们能在这个收获的季节,让心灵充盈,满载而归!立秋丨一候凉风至;二候白露生;三候寒蝉鸣。"},{"SolarTerms": "处暑","Title": "早秋山中作","Author": "王维","Poem": "草间蛩响临秋急,山里蝉声薄暮悲。寂寞柴门人不到,空林独与白云期。","Description": "暑气将于这一天结束,秋意冉冉,从而开始一年之中最美好的秋高气爽的时节。白天要注意防暑,夜晚要记得添衣。暑去秋来,愿君务必珍重,秋日安康!处暑丨一候鹰乃祭鸟;二候天地始肃;三候禾乃登。"},{"SolarTerms": "白露","Title": "金陵城西楼月下吟","Author": "李白","Poem": "金陵夜寂凉风发,独上高楼望吴越。白云映水摇空城,白露垂珠滴秋月。","Description": "白露秋分夜,一夜凉一夜;一场秋雨一场凉,一场白露一场霜;白露白茫茫,谷子满田黄。成熟与收获,尽数来到眼前。沉重的汗水凝结成沉甸甸的果实,人们喜悦,感念,分享。白露丨一候鸿雁来;二候元鸟归;三候群鸟养羞。"},{"SolarTerms": "秋分","Title": "秋词二首(其二)","Author": "刘禹锡","Poem": "山明水净夜来霜,数树深红出浅黄。试上高楼清入骨,岂如春色嗾人狂。","Description": "秋分,天高云淡,气净风轻,是一个浪漫的节气。秋云飘逸,秋水如镜,处处迷人,令人陶醉。正是邀三五好友快意潇洒,观秋之华彩、赏世间美景的好时候。秋分丨一候雷始收声;二候蛰虫坯户;三候水始涸。"},{"SolarTerms": "寒露","Title": "秋兴八首·其七","Author": "杜甫","Poem": "波漂菰米沈云黑,露冷莲房坠粉红。关塞极天唯鸟道,江湖满地一渔翁。","Description": "《月令七十二候集解》中说:九月节,露气寒冷,将凝结也。又是一年寒露至,又是一年秋意浓。最美的秋在眼前,最美的风景在身边,用心珍惜方能长久!寒露丨一候鸿雁来宾;二候雀入大水为蛤;三候菊有黄华。"},{"SolarTerms": "霜降","Title": "村夜","Author": "白居易","Poem": "霜草苍苍虫切切,村南村北行人绝。独出前门望野田,月明荞麦花如雪。","Description": "从霜降当天起,暮秋已至天气凉,万物秋收冬藏。好柿成霜,喜从天降。活在当下,不留遗憾。岁岁年年,愿你安暖!霜降丨一候豺乃祭兽;二候草木黄落;三候蜇虫咸俯。"},{"SolarTerms": "立冬","Title": "初冬夜饮","Author": "杜牧","Poem": "淮阳多病偶求欢,客袖侵霜与烛盘。砌下梨花一堆雪,明年谁此凭阑干?","Description": "立冬,代表着冬季开始,万物收藏,规避寒冷。一岁年华,已近尾声。在今年的最后一季里,定要修身养心,持善悦己!立冬丨一候水始冰;二候地始冻;三候雉入大水为蜃。"},{"SolarTerms": "小雪","Title": "小雪","Author": "戴叔伦","Poem": "花雪随风不厌看,更多还肯失林峦。愁人正在书窗下,一片飞来一片寒。","Description": "小雪时雪还未盛,故称“小雪”。人生实苦,善待自己。在这个季节里,如果累了,就放松心情,再冷的天气,也要温暖自己的心!小雪丨一候虹藏不见;二候天气上升地气下降;三候闭塞而成冬。"},{"SolarTerms": "大雪","Title": "北风行","Author": "李白","Poem": "燕山雪花大如席,片片吹落轩辕台。幽州思妇十二月,停歌罢笑双蛾摧。","Description": "从这天起,大雪来临,寒冬已至。天雪鬃呼啸。待早上一睁眼,冰封的窗户就亮得耀目。风中闻草木,雪里见江山。想要记起和忘掉一切,只需这一场大雪。大雪丨一候鹃鸥不鸣;二候虎始交;三候荔挺出。"},{"SolarTerms": "冬至","Title": "邯郸冬至夜思家","Author": "白居易","Poem": "邯郸驿里逢冬至,抱膝灯前影伴身。想得家中夜深坐,还应说着远行人。","Description": "冬至,古称“至日”,“至”是极致的意思,冬藏之气至此而极。依着血缘的眷念,漂泊的游子都将踏上归家的旅途,冬至的温暖也安抚着每一个思归的心。冬至丨一候蚯蚓结;二候麋角解;三候水泉动。"},{"SolarTerms": "小寒","Title": "冬夜寄温飞卿","Author": "鱼玄机","Poem": "苦思搜诗灯下吟,不眠长夜怕寒衾。满庭木叶愁风起,透幌纱窗惜月沉。","Description": "小寒一过,就进入“出门冰上走”的三九天了。小寒,是一个充满希望的时节——此时旧岁近暮,新岁即将登场,坚毅的鸿雁已先开始启程北飞了。万物开始复苏,生机已然蠢动。小寒丨一候雁北乡,二候鹊始巢,三候雉始鸲。"},{"SolarTerms": "大寒","Title": "寒夜","Author": "杜耒","Poem": "寒夜客来茶当酒,竹炉汤沸火初红。寻常一样窗前月,才有梅花便不同。","Description": "大寒是这一年里的最后一个节气,也是一年中阴阳转换的重要时机。大寒过后,又是一年新的轮回。愿下个轮回,依旧有你相伴!大寒丨一候鸡乳;二候征鸟厉疾;三候水泽腹坚。"}
]

将上面的内容保存为 traditional-festival.json,数据集就准备就绪啦。

验证环境(可选)

虽然我们一般情况下,会将所有模型相关的部分都封装到容器环境中,尤其是 Python 相关的环境,让相关的程序在调用过程中的环境都更加纯粹、简单。

但是,考虑到很多同学并不会使用向量化模型(Embedding Model),所以这里我们增加一个简单的验证环境,来展示下如何使用向量化模型。

当然,即使不使用 Docker 作为 Python 运行环境,我们也可以使用诸如 Conda 等支持环境隔离的方案,来运行我们的程序代码。

你可以参考《在搭载 M1 及 M2 芯片 MacBook设备上玩 Stable Diffusion 模型》这篇文章中的“基础环境准备”部分,来完成 Conda 环境的配置和软件包镜像的配置,来快速的完成验证环境的准备。

当 Conda 就绪后,只需要执行下面的代码,就能够获得一个完全干净的环境啦:

conda create -n weaviate python=3.9 -y
conda activate weaviate

快速上手 AI 数据库的实践

快速上手非常简单,但是在这个过程中,我想相对详细、清晰的分享下一些了解后有助于你清晰的改进服务的技术细节。

快速上手 GTE 向量模型

为了快速上手模型,我们可以编写一段简单的程序,原始代码在 soulteary/weaviate-quickstart/usage1.py,注释比较详细就不展开赘述啦:

import torch.nn.functional as F
from transformers import AutoTokenizer, AutoModel# 定义输入内容
input_texts = ["天气好热,哪里有卖冰棍的","今天好冷,该多穿两件","夏天","冬天"
]# 指定预训练模型,在线模型 "thenlper/gte-base-zh",此处使用本地目录中的模型
model_id = "./thenlper/gte-small"# 加载分词器和模型
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModel.from_pretrained(model_id)# 对输入内容进行分词、编码
batch_dict = tokenizer(input_texts, max_length=512, padding=True, truncation=True, return_tensors='pt')# 获取 Embeddings
outputs = model(**batch_dict)
embeddings = outputs.last_hidden_state[:, 0]# 标准化 embeddings,使用 L2 归一化,使其长度为 1
embeddings = F.normalize(embeddings, p=2, dim=1)
# 计算相似度,选择第一个元素,和除了第一个元素进行比较
scores = (embeddings[:1] @ embeddings[1:].T) * 100
# 打印结果分数
print(scores.tolist())

将上面的代码保存为 usage1.py,我们就可以准备运行模型啦。想要通过上面的代码运行模型,我们还需要安装两个基础的 Python 依赖:

pip install torch transformers

当依赖安装完毕,我们可以执行 python usage1.py,执行结果类似下面:

# python usage1.py
[[80.17919921875, 82.7370376586914, 84.4228286743164]]

如果你觉得上面的代码比较冗长,我们还可以使用 Sentence Transformer 的方式来运行模型:

from sentence_transformers import SentenceTransformer
from sentence_transformers.util import cos_sim# 定义输入内容
sentences = ["天气好热,哪里有卖冰棍的","今天好冷,该多穿两件","夏天","冬天"
]# 指定预训练模型,在线模型 "thenlper/gte-base-zh",此处使用本地目录中的模型
model_id = "./thenlper/gte-small"# 加载 SentenceTransformer 模型
model = SentenceTransformer(model_id)
# 获取向量
embeddings = model.encode(sentences)
# 计算第一个句子(index 0)和第二个句子(index 1)的嵌入向量之间的余弦相似度,并打印结果
print(cos_sim(embeddings[0], embeddings[1]))

将上面的代码保存为 usage2.py,然后我们完成必要的依赖安装:

pip install sentence_transformers

然后,执行 python usage2.py,我们就能够得到相似度结果了:

# python usage2.py
tensor([[0.8448]])

这段代码保存在 soulteary/weaviate-quickstart/usage2.py,有需要可以自取。

了解了通常情况下,我们如何使用向量模型,那么接下来,我们来看看如何使用 Weaviate。

使用 Docker 启动 Weaviate 和 AI 服务

Weaviate 和其他向量数据库产品或者用户量更大的支持向量功能的数据库不同的是,它的原生向量模块。

我们可以使用下面的配置,一键启动一个能够将我们输入的普通文本内容,自动转换为向量检索、相似度计算的向量数据库服务。

version: "3.4"
services:weaviate:command:- --host- 0.0.0.0- --port- "8080"- --scheme- httpimage: semitechnologies/weaviate:1.25.5ports:- 8086:8080- 50051:50051volumes:- ./weaviate_data:/var/lib/weaviaterestart: on-failure:0environment:QUERY_DEFAULTS_LIMIT: 25# https://weaviate.io/developers/weaviate/configuration/authenticationAUTHENTICATION_APIKEY_ENABLED: "true"AUTHENTICATION_APIKEY_ALLOWED_KEYS: "soulteary,password"AUTHENTICATION_APIKEY_USERS: "soulteary,user@lab.io"AUTHORIZATION_ADMINLIST_ENABLED: "true"AUTHORIZATION_ADMINLIST_USERS: "soulteary,user@lab.io"PERSISTENCE_DATA_PATH: "/var/lib/weaviate"CLUSTER_HOSTNAME: "node1"ENABLE_MODULES: "text2vec-transformers"# Support enabled modules, ENABLE_MODULES: "text2vec-cohere,text2vec-huggingface,text2vec-palm,text2vec-openai,generative-openai,generative-cohere,generative-palm,ref2vec-centroid,reranker-cohere,qna-openai"# Only store vectors, DEFAULT_VECTORIZER_MODULE: "none"DEFAULT_VECTORIZER_MODULE: "text2vec-transformers"TRANSFORMERS_INFERENCE_API: "http://t2v-transformers:8080"t2v-transformers:image: soulteary/t2v-transformers:2024.06.27environment:# set to 1 to enableENABLE_CUDA: 0ports:- 9090:8080

上面的配置,就是 Weaviate 的全部配置啦,将上面的配置保存为 docker-compose.yml 之后,我们可以使用 docker compose up -d 启动这个服务。

接着,我们就能够使用各种各样的 “Weaviate SDK”,在各种传统的程序中,启用“向量检索”能力啦。

编写一个简单的向量检索程序

你可以选择 Python、JavaScript(TS)、Java、Go、PHP、Ruby、C# 等方式来完成 Weaviate 的调用。

本篇文章,我选择简单又高效的 Golang,从初始化 Weaviate 客户端实例到创建向量数据索引,再到使用我们的查询内容去查找数据库中最相近的内容,完整程序大概只需要 150 行:

package mainimport ("context""encoding/json""fmt""os""time""github.com/weaviate/weaviate-go-client/v4/weaviate""github.com/weaviate/weaviate-go-client/v4/weaviate/auth""github.com/weaviate/weaviate-go-client/v4/weaviate/graphql""github.com/weaviate/weaviate/entities/models"
)func init() {os.Setenv("WEAVIATE_INSTANCE_URL", "localhost:8086")os.Setenv("WEAVIATE_SCHEME", "http")os.Setenv("WEAVIATE_API_KEY", "soulteary")
}func CreateClient(host string, scheme string, key string) (*weaviate.Client, error) {cfg := weaviate.Config{Host:       host,Scheme:     scheme,AuthConfig: auth.ApiKey{Value: key},}client, err := weaviate.NewClient(cfg)if err != nil {return nil, err}return client, nil
}func CreateDB(client *weaviate.Client) error {classObj := &models.Class{Class:      "TraditionalFestival",Vectorizer: "text2vec-transformers",}// add the schemaerr := client.Schema().ClassCreator().WithClass(classObj).Do(context.Background())if err != nil {return err}buf, err := os.ReadFile("./traditional-festival.json")if err != nil {return err}var items []map[string]stringerr = json.Unmarshal(buf, &items)if err != nil {return err}objects := make([]*models.Object, len(items))for i := range items {objects[i] = &models.Object{Class: "TraditionalFestival",Properties: map[string]any{"SolarTerms":  items[i]["SolarTerms"],"Title":       items[i]["Title"],"Author":      items[i]["Author"],"Poem":        items[i]["Poem"],"Description": items[i]["Description"],},}}batchRes, err := client.Batch().ObjectsBatcher().WithObjects(objects...).Do(context.Background())if err != nil {return err}for _, res := range batchRes {if res.Result.Errors != nil {return fmt.Errorf("error: %v", res.Result.Errors)}}return nil
}func Query(client *weaviate.Client, queries []string) error {st := time.Now()fields := []graphql.Field{{Name: "solarTerms"},{Name: "title"},{Name: "author"},{Name: "poem"},{Name: "description"},}nearText := client.GraphQL().NearTextArgBuilder().WithConcepts(queries)result, err := client.GraphQL().Get().WithClassName("TraditionalFestival").WithFields(fields...).WithNearText(nearText).WithLimit(2).Do(context.Background())if err != nil {return err}fmt.Println()fmt.Println("Time:", time.Since(st))fmt.Println()buf, err := json.Marshal(result)if err != nil {return err}fmt.Printf("%v", string(buf))return nil
}func main() {hostURL := os.Getenv("WEAVIATE_INSTANCE_URL")scheme := os.Getenv("WEAVIATE_SCHEME")apikey := os.Getenv("WEAVIATE_API_KEY")// create a clientclient, err := CreateClient(hostURL, scheme, apikey)if err != nil {panic(err)}// try to create a databaseerr = CreateDB(client)if err != nil {fmt.Println("CreateDB", err)}// try to queryqueries := []string{"夏天吃瓜,冰棍也行吧"}fmt.Println("Queries", queries)err = Query(client, queries)if err != nil {fmt.Println("Query", err)}
}

上面的这段代码,同样保存在了项目中 soulteary/weaviate-quickstart/main.go,你可以自取。我们可以先进入本文提供的开源项目的根目录,并完成 Go 的依赖下载,两条命令即可(如果你不熟悉 Go,可以阅读《搭建可维护的 Golang 开发环境》这篇文章,快速初始化可维护的环境):

# cd weaviate-quickstart
# go mod tidygo: downloading gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
go: downloading github.com/kr/pretty v0.3.1
go: downloading github.com/rogpeppe/go-internal v1.11.0
go: downloading github.com/kr/text v0.2.0

接着,执行 go run main.go 运行程序,程序将自动创建向量数据的索引,并查询我们输入的内容,获取最相近的计算结果,最终的输出类似下面这样:

Queries [夏天吃瓜,冰棍也行吧]Time: 13.65638ms{"data":{"Get":{"TraditionalFestival":[{"author":"杜牧","description":"立冬,代表着冬季开始,万物收藏,规避寒冷。一岁年华,已近尾声。在今年的最后一季里,定要修身养心,持善悦己!立冬丨一候水始冰;二候地始冻;三候雉入大水为蜃。","poem":"淮阳多病偶求欢,客袖侵霜与烛盘。砌下梨花一堆雪,明年谁此凭阑干?","solarTerms":"立冬","title":"初冬夜饮"},{"author":"韩翃","description":"小暑,表示季夏时节的正式开始。天气开始炎热,但还没到最热,故称“小暑”。小暑时节,心静自然凉。眼前无长物,窗下有清风。散热有心静,凉生为室空。小暑丨一候温风至;二候蟋蟀居宇;三候鹰始鸷。","poem":"相思掩泣复何如,公子门前人渐疏。幸有心期当小暑,葛衣纱帽望回车。","solarTerms":"小暑","title":"赠别王侍御赴上都"}]}}}

是不是简单又有效呢?让我们来多了解几个简单的细节。

技术细节

在这里,再和大家展开聊几个技术细节吧。

封装一个 T2V Transformer 服务

在上面的 Docker 配置中,我们能够看到一个我定义的向量转换服务。

...t2v-transformers:image: soulteary/t2v-transformers:2024.06.27environment:# set to 1 to enableENABLE_CUDA: 0ports:- 9090:8080

这个 Docker 服务中的 soulteary/t2v-transformers:2024.06.27,包含了我们上文中提到的通义实验室团队的 GTE 模型。将 GTE 模型转换为一个可以被向量数据库调用的服务,其实也很简单。

Dockerfile 中的内容是这样的,我们只需要将 HuggingFace 或 ModelScope 中下载的模型,在构建服务的时候,扔到 /app/models/model 中即可:

FROM semitechnologies/transformers-inference:customCOPY ./thenlper/gte-small /app/models/model

然后,执行命令完成镜像的构建:

docker build -t soulteary/t2v-transformers:2024.06.27 .

最后,将服务的访问地址和启用模块名称,配置在 weaviate 容器服务的环境变量中即可。

version: "3.4"
services:weaviate:# 省略 ...environment:# 省略 ...CLUSTER_HOSTNAME: "node1"ENABLE_MODULES: "text2vec-transformers"DEFAULT_VECTORIZER_MODULE: "text2vec-transformers"TRANSFORMERS_INFERENCE_API: "http://t2v-transformers:8080"t2v-transformers:image: soulteary/t2v-transformers:2024.06.27environment:# set to 1 to enableENABLE_CUDA: 0ports:- 9090:8080

快速建立“结构化”的非结构化数据向量索引

想要搜索又快又好,或者完成向量和非向量的数据搜索,建立数据的向量索引过程就非常关键。

在上面的代码中,有一段代码是关键:

	objects := make([]*models.Object, len(items))for i := range items {objects[i] = &models.Object{Class: "TraditionalFestival",Properties: map[string]any{"SolarTerms":  items[i]["SolarTerms"],"Title":       items[i]["Title"],"Author":      items[i]["Author"],"Poem":        items[i]["Poem"],"Description": items[i]["Description"],},}}batchRes, err := client.Batch().ObjectsBatcher().WithObjects(objects...).Do(context.Background())

在上面的代码中,我们将下面的数据按照“字段”进行了数据入库:

[{"SolarTerms": "立春","Title": "木兰花·立春日作","Author": "陆游","Poem": "春盘春酒年年好,试戴银旛判醉倒。今朝一岁大家添,不是人间偏我老。","Description": "《月令七十二候集解》有载:“立,始建也。春气始而建立也。”在生生不息的春风中,一年的序幕由此开启。我们用一颗丰盈而善良的心,向着春意盎然的天地间走去。立春丨一候东风解冻,二候蜇虫始振,三候鱼陟负冰。"},
...
]

所以,除了像本文一样的查找之外,我们还可以在查询的过程中,使用其他字段内容进行数据聚合、过滤,或者排序等等,比如上面的搜索结果,我只想要作者“陆游”的结果,之前的代码可以改成这样:

where := filters.Where().WithPath([]string{"author"}).WithOperator(filters.Equal).WithValueString("陆游")result, err := client.GraphQL().Get().WithClassName("TraditionalFestival").WithFields(fields...).WithNearText(nearText).WithLimit(2).WithWhere(where).Do(context.Background())

再次执行代码,我们就可以得到过滤后的结果啦:

# go run main.go
Queries [夏天吃瓜,冰棍也行吧]Time: 16.928206ms{"data":{"Get":{"TraditionalFestival":[{"author":"陆游","description":"《月令七十二候集解》有载:“立,始建也。春气始而建立也。”在生生不息的春风中,一年的序幕由此开启。我们用一颗丰盈而善良的心,向着春意盎然的天地间走去。立春丨一候东风解冻,二候蜇虫始振,三候鱼陟负冰。","poem":"春盘春酒年年好,试戴银旛判醉倒。今朝一岁大家添,不是人间偏我老。","solarTerms":"立春","title":"木兰花·立春日作"}]}}}%        

向量数据落地存储的膨胀问题

默认情况下,我们启动 weaviate 数据库后,一个空的数据库目录大概是 112KB 左右。

du -hs weaviate_data                       
112K	weaviate_data

而本文中,我们使用和建立向量索引的数据是 12KB。

du -hs traditional-festival.json 
12K	traditional-festival.json

如果我们完成向量数据的索引,之前的数据库目录将膨胀至 556KB :

du -hs weaviate_data
556K	weaviate_data

增长的数据量相比原始数据,膨胀了 37 倍之多,在做内容的向量索引的时候,我们需要进行数据的容量预估。(目前 Weaviate 使用的量化方案是 PQ、BQ)

当然,解决这个问题的方法有很多,包括使用低维度一些的模型(本文使用的是 512 维的模型),或者不要对所有的内容都建立索引(本文对五个字段都进行了索引)。

以及,Weaviate 其实会自动检测我们的数据量的多少,并在合适的数据量量级下自动切换向量索引的方式为更节约资源的 HNSW。如果我们的吞吐量比较大,还可以使用水平扩展的方式,来完成容量和吞吐能力的提升。

最后

好了,这篇文章就先写到这里,下一篇类似的话题里,或许我们展开聊聊复杂一些的多路召回和相对准确的排序、打分策略。也或许聊聊赞誉度同样很高的其他的国产模型。

说起来这个月好忙,这篇文章已经拖了一个月多了,才整理成文,希望下个月可以更从容些。

–EOF


我们有一个小小的折腾群,里面聚集了一些喜欢折腾、彼此坦诚相待的小伙伴。

我们在里面会一起聊聊软硬件、HomeLab、编程上、生活里以及职场中的一些问题,偶尔也在群里不定期的分享一些技术资料。

关于交友的标准,请参考下面的文章:

苏洋:致新朋友:为生活投票,不断寻找更好的朋友

当然,通过下面这篇文章添加好友时,请备注实名和公司或学校、注明来源和目的,珍惜彼此的时间 😄

苏洋:关于折腾群入群的那些事


本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

本文作者: 苏洋

创建时间: 2024年06月27日
统计字数: 19042字
阅读时间: 39分钟阅读
本文链接: https://soulteary.com/2024/06/27/the-only-open-source-vector-database-on-the-forbes-ai-50-list-weaviate.html

相关文章:

福布斯 AI 50 榜单中唯一开源向量数据库:Weaviate

本篇文章,聊聊福布斯全球网站前俩月发布的 2023 AI 50 榜单中的唯一一个开源的向量数据库:Weaviate。 它在数据持久化和容错性上表现非常好、支持混合搜索、支持水平扩展,同时又保持了轻量化。官方主打做 AI 时代的原生数据库,减…...

信息学奥赛初赛天天练-38-CSP-J2021阅读程序-约数个数、约数和、埃氏筛法、欧拉筛法筛素数应用

PDF文档公众号回复关键字:20240628 2021 CSP-J 阅读程序3 1阅读程序(判断题1.5分 选择题3分 共计40分 ) 01 #include<stdio.h> 02 using namespace std; 03 04 #define n 100000 05 #define N n1 06 07 int m; 08 int a[N],b[N],c[N],d[N]; 09 int f[N],g[N]; 10 11 …...

第100+13步 ChatGPT学习:R实现决策树分类

基于R 4.2.2版本演示 一、写在前面 有不少大佬问做机器学习分类能不能用R语言&#xff0c;不想学Python咯。 答曰&#xff1a;可&#xff01;用GPT或者Kimi转一下就得了呗。 加上最近也没啥内容写了&#xff0c;就帮各位搬运一下吧。 二、R代码实现决策树分类 &#xff08;…...

Hi3861 OpenHarmony嵌入式应用入门--LiteOS MessageQueue

CMSIS 2.0接口中的消息&#xff08;Message&#xff09;功能主要涉及到实时操作系统&#xff08;RTOS&#xff09;中的线程间通信。在CMSIS 2.0标准中&#xff0c;消息通常是通过消息队列&#xff08;MessageQueue&#xff09;来进行处理的&#xff0c;以实现不同线程之间的信息…...

ffmpeg编码图象时报错Invalid buffer size, packet size * < expected frame_size *

使用ffmpeg将单个yuv文件编码转为jpg或其他图像格式时&#xff0c;报错&#xff1a; Truncating packet of size 11985408 to 3585 [rawvideo 0x1bd5390] Packet corrupt (stream 0, dts 1). image_3264_2448_0.yuv: corrupt input packet in stream 0 [rawvideo 0x1bd7c60…...

解决类重复的问题

1.针对AndroidX 类重复问题 解决办法&#xff1a; android.useAndroidXtrue android.enableJetifiertrue2.引用其他sdk出现类重复的问题解决办法&#xff1a;configurations {all { // You should exclude one of them not both of themexclude group: "com.enmoli"…...

使用 shell 脚本 统计app冷启动耗时

下面是一个 shell 脚本&#xff0c;它使用 参数将包名称作为参数--app&#xff0c;识别相应应用程序进程的 PID&#xff0c;使用 终止该进程adb shell kill&#xff0c;最后使用 重新启动该应用程序adb shell am start&#xff1a; #!/bin/bash# Check if package name is pro…...

使用容器部署redis_设置配置文件映射到本地_设置存储数据映射到本地_并开发java应用_连接redis---分布式云原生部署架构搭建011

可以看到java应用的部署过程,首先我们要准备一个java应用,并且我们,用docker,安装一个redis 首先我们去start.spring.io 去生成一个简单的web项目,然后用idea打开 选择以后下载 放在这里,然后我们去安装redis 在公共仓库中找到redis . 可以看到它里面介绍说把数据放到了/dat…...

第五节:如何使用其他注解方式从IOC中获取bean(自学Spring boot 3.x的第一天)

大家好&#xff0c;我是网创有方&#xff0c;上节我们实践了通过Bean方式声明Bean配置。咱们这节通过Component和ComponentScan方式实现一个同样功能。这节实现的效果是从IOC中加载Bean对象&#xff0c;并且将Bean的属性打印到控制台。 第一步&#xff1a;创建pojo实体类studen…...

Paragon NTFS与Tuxera NTFS有何区别 Mac NTFS 磁盘读写工具选哪个好

macOS系统虽然以稳定、安全系数高等优点著称&#xff0c;但因其封闭性&#xff0c;不能对NTFS格式磁盘写入数据常被人们诟病。优质的解决方案是使用磁盘管理软件Paragon NTFS for Mac&#xff08;点击获取激活码&#xff09;和Tuxera NTFS&#xff08;点击获取激活码&#xff0…...

EtherCAT主站IGH-- 2 -- IGH之coe_emerg_ring.h/c文件解析

EtherCAT主站IGH-- 2 -- IGH之coe_emerg_ring.h/c文件解析 0 预览一 该文件功能coe_emerg_ring.c 文件功能函数预览 二 函数功能介绍coe_emerg_ring.c 中主要函数的作用1. ec_coe_emerg_ring_init2. ec_coe_emerg_ring_clear3. ec_coe_emerg_ring_size4. ec_coe_emerg_ring_pus…...

psensor 的手势功能

psensor 的手势功能的移植过程 有时间再来写下...

使用 nvm 管理 Node 版本及 pnpm 安装

文章目录 GithubWindows 环境Mac/Linux 使用脚本进行安装或更新Mac/Linux 环境变量nvm 常用命令npm 常用命令npm 安装 pnpmNode 历史版本 Github https://github.com/nvm-sh/nvm Windows 环境 https://nvm.uihtm.com/nvm.html Mac/Linux 使用脚本进行安装或更新 curl -o- …...

uni-appx使用form表单页面初始化报错

因为UniFormSubmitEvent的类型时 e-->detail-->value,然后没有了具体值。所以页面初始化的时候 不能直接从value取值&#xff0c;会报错找不到 所以form表单里的数据我们要设置成一个对象来存放 这个问题的关键在于第22行代码 取值&#xff1a; 不能按照点的方式取值 …...

TiDB-从0到1-数据导出导入

TiDB从0到1系列 TiDB-从0到1-体系结构TiDB-从0到1-分布式存储TiDB-从0到1-分布式事务TiDB-从0到1-MVCCTiDB-从0到1-部署篇TiDB-从0到1-配置篇TiDB-从0到1-集群扩缩容 一、数据导出 TiDB中通过Dumpling来实现数据导出&#xff0c;与MySQL中的mysqldump类似&#xff0c;其属于…...

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-16自定义层

16自定义层 import torch import torch.nn.functional as F from torch import nnclass CenteredLayer(nn.Module):def __init__(self):super().__init__()#从其输入中减去均值#X.mean() 计算的是整个张量的均值#希望计算特定维度上的均值&#xff0c;可以传递 dim 参数。#例如…...

树莓派4设置

使用sudo命令时要求输入密码 以 sudo 为前缀的命令以超级用户身份运行。默认情况下&#xff0c;超级用户不需要密码。不过&#xff0c;您可以要求所有以 sudo 运行的命令都输入密码&#xff0c;从而提高 Raspberry Pi 的安全性。 要强制 sudo 要求输入密码&#xff0c;请为你…...

44.商城系统(二十五):k8s基本操作,ingress域名访问,kubeSphere可视化安装

上一章我们已经配置好了k8s集群,如果没有配置好先去照着上面的配。 一、k8s入门操作 1.部署一个tomcat,测试容灾恢复 #在主机器上执行 kubectl create deployment tomcat6 --image=tomcat:6.0.53-jre8#查看k8s中的所有资源 kubectl get all kubectl get all -o wide#查看po…...

MySQL高级查询

MySQL 前言 文本源自微博客 (www.microblog.store),且已获授权. 一. mysql基础知识 1. mysql常用系统命令 启动命令 net start mysql停止命令 net stop mysql登录命令 mysql -h ip -P 端口 -u 用户名 -p ​ 本机可以省略 ip mysql -u 用户名 -p 查看数据库版本 mysql --ve…...

聊聊啥项目适合做自动化测试

作为测试从业者&#xff0c;你是否遇到过这样的场景&#xff0c;某天公司大Boss找你谈话。 老板&#xff1a;小李&#xff0c;最近工作辛苦了 小李&#xff1a;常感谢您的认可&#xff0c;这不仅是对我个人的鼓励&#xff0c;更是对我们整个团队努力的认可。我们的成果离不开每…...

ROS2开发机器人移动

.创建功能包和节点 这里我们设计两个节点 example_interfaces_robot_01&#xff0c;机器人节点&#xff0c;对外提供控制机器人移动服务并发布机器人的状态。 example_interfaces_control_01&#xff0c;控制节点&#xff0c;发送机器人移动请求&#xff0c;订阅机器人状态话题…...

【强化学习】第02期:动态规划方法

笔者近期上了国科大周晓飞老师《强化学习及其应用》课程&#xff0c;计划整理一个强化学习系列笔记。笔记中所引用的内容部分出自周老师的课程PPT。笔记中如有不到之处&#xff0c;敬请批评指正。 文章目录 2.1 动态规划&#xff1a;策略收敛法/策略迭代法2.2 动态规划&#xf…...

安全技术和防火墙(二)

接上一节 备份和还原 iptables-save > /opt/iptables.bak iptables-restore < /opt/iptables.bak snat和dnat snat源地址转换 内网到外网 内网ip转换成可以访问外网的ip 内网的多个主机可以只有一个有效的公网ip地址访问外部网络 dnat 目的地址转发 外部用户&#…...

【51单片机入门】数码管原理

文章目录 前言共阴极与共阳极数码管多个数码管显示原理 总结 前言 在我们的日常生活中&#xff0c;数码管被广泛应用于各种电子设备中&#xff0c;如电子表、计时器、电子钟等。数码管的主要功能是显示数字和一些特殊字符。在这篇文章中&#xff0c;我们将探讨数码管的工作原理…...

三星DRAM、NAND,“又双叒叕”带头涨价了

据韩国媒体《每日经济新闻》报道&#xff0c;三星电子计划在第三季度上调服务器DRAM和企业级NAND闪存的价格&#xff0c;涨幅预计在15%-20%&#xff0c;主要受人工智能(AI)需求激增的推动。这一举措有望提振公司下半年业绩。 据《经济日报》报道援引业内消息&#xff0c;由于厂…...

星戈瑞FITC-PEG2000-Biotin的生物相容性

生物相容性是指材料与生物体之间相互作用时&#xff0c;材料对生物体无毒、无刺激&#xff0c;且能够被生物体接受并正常发挥其功能的特性。 FITC-PEG2000-Biotin作为一种荧光标记试剂&#xff0c;在细胞成像、药物传递和生物标志物检测等领域具有诸多应用前景。 FITC-PEG2000…...

数据资产管理的艺术:构建智能化、精细化的数据资产管理体系,从数据整合、分析到决策支持,为企业提供一站式的数据资产解决方案,助力企业把握数字时代的新机遇

一、引言 在数字化浪潮席卷全球的今天&#xff0c;数据已经成为企业最重要的资产之一。如何高效、安全地管理这些海量数据&#xff0c;从中提取有价值的信息&#xff0c;并将其转化为决策支持&#xff0c;是每个企业都必须面对的挑战。本文将探讨数据资产管理的艺术&#xff0…...

基于Java微信小程序校园自助打印系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f;感兴趣的可以先收藏起来&#xff0c;还…...

股票复盘思路

股票复盘是一个回顾和分析市场及个人交易决策的过程,旨在从过去的表现中学习并优化未来的投资策略。以下是一些基本的股票复盘步骤和关注点: 市场概况回顾: 观察并记录每日市场的整体表现,包括大盘指数涨跌、成交量变化。统计涨停和跌停个股的数量,了解市场情绪和活跃度。…...

OpenGL系列(六)摄像机

在 OpenGL系列&#xff08;六&#xff09;变换 中&#xff0c;一个目标物体经过模型矩阵、观察矩阵和投影矩阵的变换才能正常显示出来&#xff0c;其中模型矩阵主要针对目标物体&#xff0c;它会影响物体的位姿。观察矩阵和投影矩阵主要针对观察者而已&#xff0c;这两个变换决…...

一个端口配置两个vue和后端服务,nginx以及前后端服务怎么配?

nginx配置重点看server中的内容&#xff1a; worker_processes 8; pid /usr/local/nginx/logs/nginx.pid;events {# 此为 Linux 系统特为处理大批量文件描述符而作改进的 poll 事件模型use epoll;worker_connections 512; # 工作进程的最大连接数量# 允许同时接受多个网络连…...

295. 数据流的中位数

class MedianFinder {Queue<Integer> A,B;public MedianFinder() {A new PriorityQueue<>();//小根堆存储后半部分B new PriorityQueue<>((x,y)->(y-x));//大根堆存储前半部分}public void addNum(int num) {if(A.size()0 && B.size()0){B.add(…...

OCR训练和C#部署英文字符训练

PaddleOCR是一个基于飞桨开发的OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;系统。其技术体系包括文字检测、文字识别、文本方向检测和图像处理等模块。以下是其优点&#xff1a; 高精度&#xff1a;PaddleOCR采用深度学习算法进行训练…...

webpack【实用教程】

基础配置 配置的拆分和合并 通常 webpack 的配置文件会有3个 webpack.common.js 公共配置&#xff08;会被另外两个配置文件导入并合并&#xff09;webpack.dev.js 开发环境的配置webpack.prod.js 生产环境的配置 开发环境的本地服务 在 webpack.dev.js 中配置 devServer:…...

如何使用C++进行文件读写操作

在C中&#xff0c;我们可以使用标准库中的 <fstream>&#xff08;文件流&#xff09;来进行文件的读写操作。以下是一些基本的文件读写操作的示例。 读取文件 cpp复制代码 #include <fstream> #include <iostream> #include <string> int main() { s…...

Tensorflow Lite移动平台编译

Android平台编译 如果不做定制化操作,我们不需要自己编译TensorFlow Lite Android库。我们可以直接使用位于MavenCentral的TensorFlow Lite AAR。但是在某些情况下,我们需要本地编译TensorFlow Lite。例如,您可能正在构建一个包含operations selected from TensorFlow的自定…...

2024年6月24日-6月30日(ue5肉鸽视频p16-p25)

试过重点放在独立游戏上&#xff0c;有个indienova独立游戏团队是全职的&#xff0c;由于他们干了几个月&#xff0c;节奏暂时跟不上&#xff0c;紧张焦虑了。五一时也有点自暴自弃了&#xff0c;实在没必要&#xff0c;按照自己的节奏走即可。精力和时间也有限&#xff0c;放在…...

LeetCode.面试题17.24.最大子矩阵详解

问题描述 给定一个正整数、负整数和 0 组成的 N M 矩阵&#xff0c;编写代码找出元素总和最大的子矩阵。 返回一个数组 [r1, c1, r2, c2]&#xff0c;其中 r1, c1 分别代表子矩阵左上角的行号和列号&#xff0c;r2, c2 分别代表右下角的行号和列号。若有多个满足条件的子矩阵…...

云动态摘要 2024-06-28

给您带来云厂商的最新动态&#xff0c;最新产品资讯和最新优惠更新。 最新优惠与活动 [新客专享]WeData 限时特惠 腾讯云 2024-06-21 数据分类分级管理&#xff0c;构建数据安全屏障 &#xff0c;仅需9.9元&#xff01; 云服务器ECS试用产品续用 阿里云 2024-04-14 云服务器…...

六、资产安全—信息分级资产管理与隐私保护(CISSP)

目录 1.信息分级 2.信息分级方法 3.责任的层级 4.资产管理 5.隐私数据管理角色 6.数据安全控制 7.数据保护方案 8.使用安全基线 六、资产安全—数据管理(CISSP): 五、身份与访问管理—身份管理和访问控制管理(CISSP): 1.信息分级 信息分级举列: 2.信息分级方…...

香港服务器托管对外贸行业必要性和优势

在当今全球化的经济环境下&#xff0c;外贸企业面临着前所未有的机遇与挑战。其中&#xff0c;服务器托管的选择对于外贸企业的运营效率和市场拓展具有举足轻重的作用。香港服务器&#xff0c;凭借其独特的地理位置、优质的网络环境和卓越的服务性能&#xff0c;一直是外贸企业…...

Vue Router 导航守卫,多次执行的解决方案

Vue Router 是 Vue.js 官方提供的路由器,它用于处理单页应用(SPA)中的路由导航。在 Vue Router 中,导航守卫是非常重要的功能,它可以在路由跳转之前或之后执行一些特定的操作。但是,如果你不小心,导航守卫可能会多次执行,这可能会导致一些问题。本文将介绍如何避免导航…...

SpringBoot集成道历(实现道历日期查询)

官网地址&#xff1a;官网地址https://6tail.cn/calendar/api.html 1、导入依赖 <dependency><groupId>cn.6tail</groupId><artifactId>lunar</artifactId><version>1.3.9</version></dependency><dependency><group…...

面对.rmallox勒索病毒:如何有效防范及应对

引言&#xff1a; 在当今数字化社会&#xff0c;网络安全问题日益严重&#xff0c;勒索病毒成为企业和个人不可忽视的威胁之一。最近出现的.rmallox勒索病毒更是给全球各地的用户带来了严重的数据安全问题。本文将探讨.rmallox勒索病毒的特点、感染方式及应对策略&#xff0c;…...

嘉立创学习

1.两个设置&#xff0c;一般用左边那个 2.焊盘分类 基本焊盘 热风盘&#xff1a;也叫花焊盘&#xff08;负片&#xff09; 隔离焊盘&#xff1a;外面那圈黑色&#xff0c;用作隔离&#xff08;负片&#xff09; 钢网层&#xff1a;&#xff08;锡膏&#xff09; 阻焊层&…...

ECharts 响应式设计

ECharts 响应式设计 ECharts 是一个由百度开源的,基于 JavaScript 的可视化库,它提供了一系列丰富的图表类型和灵活的配置选项,使得数据可视化变得简单而高效。在当今数据驱动的世界中,ECharts 已经成为许多开发者和设计师的首选工具,用于创建交互式和视觉吸引力强的图表…...

基于java语言+springboot技术架构开发的 互联网智能3D导诊系统源码支持微信小程序、APP 医院AI智能导诊系统源码

基于java语言springboot技术架构开发的 互联网智能3D导诊系统源码支持微信小程序、APP 医院AI智能导诊系统源码 一、智慧导诊系统开发原理 导诊系统从原理上大致可分为基于规则模板和基于数据模型两类。 1、基于规则推理的方法通过人工建立症状、疾病和科室之间的对应规则实现…...

MySQL事务——Java全栈知识(31)

1、事务的特性 原子性&#xff08;Atomicity&#xff09;&#xff1a;事务是不可分割的最小操作单元&#xff0c;要么全部成功&#xff0c;要么全部失败。 一致性&#xff08;Consistency&#xff09;&#xff1a;事务完成时&#xff0c;必须使所有的数据都保持一致状态。 隔离…...

2毛钱不到的2A同步降压DCDC电压6V频率1.5MHz电感2.2uH封装SOT23-5芯片MT3520B

前言 2A&#xff0c;2.3V-6V输入&#xff0c;1.5MHz 同步降压转换器&#xff0c;批量价格约0.18元 MT3520B 封装SOT23-5 丝印AS20B5 特征 高效率&#xff1a;高达 96% 1.5MHz恒定频率操作 2A 输出电流 无需肖特基二极管 2.3V至6V输入电压范围 输出电压低至 0.6V PFM 模式可在…...

Ubuntu安装、更新和删除软件

Ubuntu安装、更新和删除软件 问题命令行直接安装、更新和删除软件命令行直接安装软件命令行直接更新软件命令行直接删除软件 手动下载后命令行安装、更新和删除软件手动下载后命令行安装软件手动下载后命令行更新软件手动下载后命令行删除软件 手动下载后在桌面环境下安装、更新…...

python 实现docx指定语言翻译(不丢失格式)

我这边有个需求需要把一份docx翻译成指定语言的文档并且保存&#xff0c;研究了下&#xff0c;记录。 首先先安装依赖 pip install python-docx1.1.2 googletrans4.0.0rc1 python-docx是用来读取docx的&#xff0c;googletrans使用来翻译的。 googletrans PyPI 这个是官方文…...

2024微信小程序期末大作业-点奶茶微信小程序(后端nodejs-server)(附下载链接)_微信小程序期末大作业百度网盘下载

菜单展示 购物车展示&#xff1a; 提交订单&#xff1a; 支付详情页展示&#xff1a; 订单查看&#xff1a; 查看历史消费&#xff1a; 部分代码展示&#xff1a; <!--pages/home/home.wxml--> <block wx:for"{{listData}}" wx:key"itemlist&qu…...

Shell学习——Shell变量

文章目录 Shell变量使用变量只读变量删除变量变量类型字符串变量&#xff1a; 在 Shell中&#xff0c;变量通常被视为字符串。整数变量&#xff1a; 在一些Shell中&#xff0c;你可以使用 declare 或 typeset 命令来声明整数变量。数组变量&#xff1a; Shell 也支持数组&#…...

新加坡很火的slots游戏代投Facebook广告新流量趋势

新加坡很火的slots游戏代投Facebook广告新流量趋势 在新加坡这片充满活力的土地上&#xff0c;Slots游戏以其独特的魅力和吸引力&#xff0c;迅速成为了许多玩家的心头好。而Facebook&#xff0c;作为全球最大的社交媒体平台之一&#xff0c;为Slots游戏的推广提供了得天独厚的…...

昇思25天学习打卡营第17天|ChatGLM-6B聊天demo

一、简介&#xff1a; 本次实验&#xff0c;基于MindNLP和ChatGLM6B模型搭建一个小的聊天应用&#xff0c;ChatGLM6B 是基于 GLM-4 模型开发的开源对话机器人&#xff0c;拥有 62 亿个参数&#xff0c;能够进行自然流畅的语言交流。在对话中&#xff0c;ChatGLM6B 可以胜任文案…...

类继承-多继承虚继承

#include<iostream> using namespace std; class A1 { public:int a 10;}; class A2 { public:int b 20; }; class B :public A1, public A2 { public:int c 30; }; int main(){B b;cout << b.a << b.b << b.c << endl;return 0; } 如果基类…...

15万级!2.0T+2.0T双擎+8AT,大5座SUV!

最近汽车圈热度大多聚集在比亚迪汽车,比亚迪汽车新发布了两款全新中级车型,并且定价极低,不少消费者对此非常关注。其实除了比亚迪汽车有新车上市以外,还有一系列的新车也陆续上市了,只不过关注的小伙伴不多。近期广汽传祺GS8的5座豪华版正式迎来上市,厂家指导价15.98万元…...

比亚迪又放大招,e平台3.0Evo及首款车型发布

在去年的早些时候,比亚迪发布了e平台3.0,相较于e平台的前两代,e平台3.0针对安全性、强度、空间利用率、电池利用率都有了很大的提升,可以说比亚迪终于在电驱平台上达到了完全体,几乎弥补了之前平台的短板,目前已经应用于品牌旗下的多款车型上面,实际的体验也的确有了明显…...

C# 数组/集合排序

一&#xff1a;基础类型集合排序 /// <summary> /// 排序 /// </summary> /// <param name"isReverse">顺序是否取反</param> public static void Sort<T>(this IList<T> array, bool isReverse false)where T : IComparable …...

markdown语法保存

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...

一文读懂 javascript 函数返回值

文章导读&#xff1a;AI 辅助学习前端&#xff0c;包含入门、进阶、高级部分前端系列内容&#xff0c;当前是 JavaScript 的部分&#xff0c;瑶琴会持续更新&#xff0c;适合零基础的朋友&#xff0c;已有前端工作经验的可以不看&#xff0c;也可以当作基础知识回顾。 这篇文章…...

项目成功的关键要素:进度管理

在项目管理中&#xff0c;进度管理是决定项目成败的关键因素之一。它关乎项目能否在预定的时间范围内高效、准确地完成既定目标。 一、进度管理的重要性 1、时间控制&#xff1a;项目的成功往往与时间的把握息息相关。进度管理能够确保项目在既定的时间框架内有序进行&#x…...