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

Elasticsearch:探索 CLIP 替代方案

作者:来自 Elastic Jeffrey Rengifo 及 Tomás Murúa

分析图像到图像和文本到图像搜索的 CLIP 模型的替代方案。

在本文中,我们将通过一个模拟房地产网站的实际示例介绍 CLIP 多模态模型,探索替代方案,并分析它们的优缺点,该网站允许用户使用图片作为参考来搜索房产。

什么是 CLIP?

CLIP(Contrastive Language–Image Pre-training - 对比语言 - 图像预训练)是由 OpenAI 创建的神经网络,使用图像和文本对进行训练,以解决在文本和图像之间寻找相似性的任务,并对 “零样本” 图像进行分类,因此模型不是使用固定标签进行训练的,而是我们为模型提供未知类别,以便它可以对我们提供的图像进行分类。

CLIP 一直是最先进的模型,你可以在此处阅读有关它的更多文章:

  • 实现图像搜索
  • 如何实现图像相似性搜索

然而,随着时间的推移,出现了更多的替代方案。

在本文中,我们将使用房地产示例介绍 CLIP 的两种替代方案的优缺点。以下是我们在本文中将遵循的步骤的摘要:

基本配置:CLIP 和 Elasticsearch

在我们的示例中,我们将使用 Python 创建一个带有交互式 UI 的小项目。我们将安装一些依赖项,例如 Python 转换器,这将授予我们访问我们将使用的某些模型的权限。

创建一个文件夹 /clip_comparison 并按照此处的安装说明进行操作。完成后,安装 Elasticsearch 的 Python 客户端、Cohere SDK 和 Streamlit:

注意:作为一种选择,我建议使用 Python 虚拟环境 (venv)。如果你不想在计算机上安装所有依赖项,这将非常有用。

pip install elasticsearch==8.15.0 cohere streamlit

Streamlit 是一个开源 Python 框架,可让你使用少量代码轻松获得 UI。

我们还将创建一些文件来保存稍后将使用的指令:

  • app.py:UI 逻辑。
  • /services/elasticsearch.py​​:Elasticsearch 客户端初始化、查询和批量 API 调用以索引文档。
  • /services/models.py:用于生成嵌入的模型实例和方法。
  • index_data.py:用于从本地源索引图像的脚本。
  • /data:我们的数据集目录。

我们的应用程序结构应如下所示:

/clip_comparison|--app.py|--index_data.py|--/data|--/venv # If you decide to use venv|--/services|-- __init__.py|-- models.py|-- elasticsearch.py

配置 Elasticsearch

按照以下步骤存储示例图像。然后我们将使用 knn 向量查询搜索它们。

注意:我们也可以存储文本文档,但对于此示例,我们将仅在图像中搜索。

索引映射

访问 Kibana 开发工具(从 Kibana:Management > Dev Tools)以使用这些映射构建数据结构:

[ ]
PUT clip-images
{"mappings": {"properties": {"image_name": {"type": "text","fields": {"keyword": {"type": "keyword"}}},"image_embedding": {"type": "dense_vector","dims": 768,"index": "true","similarity": "cosine"},"image_data": {"type": "binary"}}}
}PUT embed-images
{"mappings": {"properties": {"image_name": {"type": "text","fields": {"keyword": {"type": "keyword"}}},"image_embedding": {"type": "dense_vector","dims": 1024,"index": "true","similarity": "cosine"},"image_data": {"type": "binary"}}}
}
PUT jina-images
{"mappings": {"properties": {"image_name": {"type": "text","fields": {"keyword": {"type": "keyword"}}},"image_embedding": {"type": "dense_vector","dims": 768,"index": "true","similarity": "cosine"},"image_data": {"type": "binary"}}}
}

字段类型 dense_vector 将存储模型生成的嵌入。字段 binary 将以 base64 格式存储图像。

注意:将图像以二进制形式存储在 Elasticsearch 中不是一个好习惯。我们这样做只是为了这个例子的实际目的。建议使用静态文件存储库。

现在来看看代码。我们需要做的第一件事是使用 cloud id 和 api-key 初始化 Elasticsearch 客户端。在文件 /services/elasticsearch.py​​ 的开头写入以下代码:

[ ]
from elasticsearch import Elasticsearch, exceptions, helpers
ELASTIC_ENDPOINT = "https://your-elastic-endpoint.com:9243"
ELASTIC_API_KEY = "your-elasticsearch-api-key"
# Elasticsearch client
es_client = Elasticsearch(ELASTIC_ENDPOINT,api_key=ELASTIC_API_KEY,
)
# index documents using bulk api
def index_images(index_name: str, images_obj_arr: list):actions = [{"_index": index_name,"_source": {"image_data": obj["image_data"],"image_name": obj["image_name"],"image_embedding": obj["image_embedding"],},}for obj in images_obj_arr]try:response = helpers.bulk(es_client, actions)return responseexcept exceptions.ConnectionError as e:return e# knn search
def knn_search(index_name: str, query_vector: list, k: int):query = {"size": 4,"_source": ["image_name", "image_data"],"query": {"knn": {"field": "image_embedding","query_vector": query_vector,"k": k,"num_candidates": 100,"boost": 10,}},}try:response = es_client.search(index=index_name, body=query)return responseexcept exceptions.ConnectionError as e:return e
# match all query
def get_all_query(index_name: str):query = {"size": 400,"source": ["image_name", "image_data"],"query": {"match_all": {}},}try:return es_client.search(index=index_name, body=query)except exceptions.ConnectionError as e:return e

配置模型

要配置模型,请将模型实例及其方法放入此文件中:/services/models.py。

Cohere Embed-3 模型作为 Web 服务工作,因此我们需要一个 API 密钥才能使用它。你可以在此处免费获取一个。试用限制为每分钟 5 次调用,每月 1,000 次调用。

要配置模型并使图像可在 Elasticsearch 中搜索,请按照以下步骤操作:

  • 使用 CLIP 将图像转换为向量
  • 将图像像量存储在 Elasticsearch 中
  • 将我们要与存储的图像进行比较的图像或文本向量化。
  • 运行查询以将上一步的条目与存储的图像进行比较并获取最相似的图像。
[ ]
# /services/models.py
# dependencies
import base64
import io
import cohere
from PIL import Image
from transformers import CLIPModel, CLIPProcessor, AutoModel
COHERE_API_KEY = "your-cohere-api-key"
## CLIP model call
clip_model = CLIPModel.from_pretrained("openai/clip-vit-large-patch14")
clip_processor = CLIPProcessor.from_pretrained("openai/clip-vit-large-patch14")
# JinaCLip model call
jina_model = AutoModel.from_pretrained("jinaai/jina-clip-v1", trust_remote_code=True)
# Cohere client initialization
co = cohere.ClientV2(COHERE_API_KEY)

配置 CLIP

要配置 CLIP,我们需要在 models.py 文件中添加生成图像和文本嵌入的方法。

# /services/models.py
# convert images to vector using CLIP
async def clip_image_embeddings(image: Image.Image):try:inputs = clip_processor(images=image, return_tensors="pt", padding=True)outputs = clip_model.get_image_features(**inputs)return outputs.detach().cpu().numpy().flatten().tolist()except Exception as e:print(f"Error generating embeddings: {e}")return None
# convert text to to vector
async def clip_text_embeddings(description: str):try:inputs = clip_processor([description], padding=True, return_tensors="pt")outputs = clip_model.get_text_features(**inputs)return outputs.detach().cpu().numpy().flatten().tolist()except Exception as e:print(f"Error generating embeddings: {e}")return None

对于所有模型,你需要声明类似的方法:一个用于从图像生成嵌入(clip_image_embeddings),另一个用于从文本生成嵌入(clip_text_embeddings)。

outputs.detach().cpu().numpy().flatten().tolist() 链是一种将 pytorch tensors 转换为更可用格式的常见操作:

  • .detach():从计算图中删除张量,因为我们不再需要计算梯度。
  • .cpu():将 tensors 从 GPU 移动到 CPU,因为 numpy 仅支持 CPU。
  • .numpy():将 tensors 转换为 numPy 数组。
  • .flatten():转换为 1D 数组。
  • .toList():转换为 Python 列表。

此操作将多维 tensor 转换为可用于嵌入操作的纯数字列表。

现在让我们看一些 CLIP 替代方案。

竞争对手 1:JinaCLIP

JinaCLIP 是 Jina AI 开发的 CLIP 变体,专门用于改进多模态应用中的图像和文本搜索。它通过增加图像和文本表示的灵活性来优化 CLIP 性能。

与原始 OpenAI CLIP 模型相比,JinaCLIP 在文本转文本、文本转图像、图像转文本和图像转图像任务中表现更好,如下图所示:

ModelText-TextText-to-ImageImage-to-TextImage-Image
jina-clip-v10.4290.8990.8030.916
openai-clip-vit-b160.1620.8810.7560.816
%increase vs OpenAI CLIP165%2%6%12%

它能够提高不同类型查询的精度,因此非常适合需要更精确、更详细分析的任务。

你可以在此处阅读有关 JinaCLIP 的更多信息。

要在我们的应用中使用 JinaCLIP 并生成嵌入,我们需要声明以下方法:

[ ]
# /services/models.py
# convert images to vector using JinaClip model
async def jina_image_embeddings(image: Image.Image):try:image_embeddings = jina_model.encode_image([image])return image_embeddings[0].tolist()except Exception as e:print(f"Error generating embeddings: {e}")return None
# convert text to vector
async def jina_text_embeddings(description: str):try:text_embeddings = jina_model.encode_text(description)return text_embeddings.tolist()except Exception as e:print(f"Error generating embeddings: {e}")return None

竞争对手 2:Cohere Image Embeddings V3

Cohere 开发了一种名为 Embed-3 的图像嵌入模型,它是 CLIP 的直接竞争对手。主要区别在于 Cohere 专注于企业数据(如图表、产品图像和设计文件)的表示。Embed-3 使用一种先进的架构,可以降低对文本数据的偏见风险,这目前是 CLIP 等其他多模态模型的劣势,因此它可以在文本和图像之间提供更精确的结果。

你可以在下方看到 Cohere 的图表,该图表显示了在这种数据中使用 Embed 3 与 CLIP 相比的改进结果:

有关更多信息,请访问 Embed3。

就像我们对之前的模型所做的那样,让我们​​声明使用 Embed 3 的方法:

[ ]
# /services/models.py
# convert images to vector using Cohere Embed model
async def embed_image_embeddings(image: Image.Image):try:img_byte_arr = io.BytesIO()image.save(img_byte_arr, format="JPEG")img_byte_arr = img_byte_arr.getvalue()stringified_buffer = base64.b64encode(img_byte_arr).decode("utf-8")content_type = "image/jpeg"image_base64 = f"data:{content_type};base64,{stringified_buffer}"response = co.embed(model="embed-english-v3.0",input_type="image",embedding_types=["float"],images=[image_base64],)return response.embeddings.float_[0]except Exception as e:print(f"Error generating embeddings: {e}")return None
# convert text to vector
async def embed_text_embeddings(description: str):try:response = co.embed(texts=[description],model="embed-english-v3.0",input_type="classification",embedding_types=["float"],)return response.embeddings.float_[0]except Exception as e:print(f"Error generating embeddings: {e}")return None

准备好函数后,让我们通过在文件 index_data.py 中添加以下代码来在 Elasticsearch 中索引数据集:

[ ]
# dependencies
import asyncio
import base64
import os
from PIL import Image
from services.elasticsearch import index_images
from services.models import (clip_image_embeddings,embed_image_embeddings,jina_image_embeddings,
)
# function to encode images
def encode_image_to_base64(image_path):with open(image_path, "rb") as img_file:return base64.b64encode(img_file.read()).decode("utf-8")
async def main():# folder with imagesfolder_path = "./data"jina_obj_arr = []embed_obj_arr = []clip_obj_arr = []for filename in os.listdir(folder_path):img_path = os.path.join(folder_path, filename)print(f"Processing {filename}...")try:image_data = Image.open(img_path)# generating images embeddingsclip_result, embed_result, jina_result = await asyncio.gather(clip_image_embeddings(image_data),embed_image_embeddings(image_data),jina_image_embeddings(image_data),)image_base64 = encode_image_to_base64(img_path)# building documentsjina_obj_arr.append({"image_name": filename,"image_embedding": jina_result,"image_data": image_base64,})embed_obj_arr.append({"image_name": filename,"image_embedding": embed_result,"image_data": image_base64,})clip_obj_arr.append({"image_name": filename,"image_embedding": clip_result,"image_data": image_base64,})except Exception as e:print(f"Error with {filename}: {e}")print("Indexing images in Elasticsearch...")# indexing imagesjina_count, _ = index_images(jina_index, jina_obj_arr)cohere_count, _ = index_images(embed_index, cohere_obj_arr)openai_count, _ = index_images(clip_index, openai_obj_arr)print("Cohere count: ", cohere_count)print("Jina count: ", jina_count)print("OpenAI count: ", openai_count)
if __name__ == "__main__":asyncio.run(main())

使用以下命令对文档进行索引:

python index_data.py

一旦数据集被索引,我们就可以创建 UI。

测试 UI

创建 UI

我们将使用 Streamlit 构建 UI 并并排比较这三种替代方案。

要构建 UI,我们首先将导入和依赖项添加到文件 app.py:

[ ]
# app.py
import asyncio
import base64
from io import BytesIO
import streamlit as st
from PIL import Image
from services.elasticsearch import get_all_query, knn_search
# declared functions imports
from services.models import (clip_image_embeddings,clip_text_embeddings,embed_image_embeddings,embed_text_embeddings,jina_image_embeddings,jina_text_embeddings,
)

对于此示例,我们将使用两个视图;一个用于图像搜索,另一个用于查看图像数据集:

[ ]
# app.py
if "selected_view" not in st.session_state:st.session_state.selected_view = "Index"
def change_view(view):st.session_state.selected_view = view
st.sidebar.title("Menu")
if st.sidebar.button("Search image"):change_view("Index")
if st.sidebar.button("All images"):change_view("Images")

让我们添加搜索图像的视图代码:

[ ]
if st.session_state.selected_view == "Index":# Index pagest.title("Image Search")col1, col_or, col2 = st.columns([2, 1, 2])uploaded_image = Nonewith col1:uploaded_image = st.file_uploader("Upload image", type=["jpg", "jpeg", "png"])with col_or:st.markdown("<h3 style='text-align: center; margin-top: 50%;'>OR</h3>",unsafe_allow_html=True,)input_text = Nonewith col2:st.markdown("<div style='display: flex; margin-top: 3rem;  align-items: center; height: 100%; justify-content: center;'>",unsafe_allow_html=True,)input_text = st.text_input("Type text")st.markdown("</div>", unsafe_allow_html=True)st.write("")st.write("")search_button = st.markdown("""<style>.stButton>button {width: 50%;height: 50px;font-size: 20px;margin: 0 auto;display: block;}</style>""",unsafe_allow_html=True,)submit_button = st.button("Search")if uploaded_image:st.image(uploaded_image, caption="Uploaded Image", use_container_width=True)if submit_button:if uploaded_image or input_text:async def fetch_embeddings():data = Noneif uploaded_image:image = Image.open(uploaded_image)data = imageelif input_text:data = input_text# Getting image or text embeddingsif uploaded_image:openai_result, cohere_result, jina_result = await asyncio.gather(clip_image_embeddings(data),embed_image_embeddings(data),jina_image_embeddings(data),)elif input_text:openai_result, cohere_result, jina_result = await asyncio.gather(clip_text_embeddings(data),embed_text_embeddings(data),jina_text_embeddings(data),)return openai_result, cohere_result, jina_resultresults = asyncio.run(fetch_embeddings())openai_result, cohere_result, jina_result = resultsif openai_result and cohere_result and jina_result:# calling knn queryclip_search_results = knn_search("clip-images", openai_result, 5)jina_search_results = knn_search("jina-images", jina_result, 5)embed_search_results = knn_search("embed-images", cohere_result, 5)clip_search_results = clip_search_results["hits"]["hits"]jina_search_results = jina_search_results["hits"]["hits"]embed_search_results = embed_search_results["hits"]["hits"]st.subheader("Search Results")col1, spacer1, col2, spacer2, col3 = st.columns([3, 0.2, 3, 0.2, 3])def print_results(results):for hit in results:image_data = base64.b64decode(hit["_source"]["image_data"])image = Image.open(BytesIO(image_data))st.image(image, use_container_width=True)st.write("score: ", hit["_score"])# printing resultswith col1:st.write("CLIP")print_results(clip_search_results)with col2:st.write("JinaCLIP")print_results(jina_search_results)with col3:st.write("Cohere")print_results(embed_search_results)else:st.warning("Please upload an image or type text to search.")

现在,图像视图的代码:

[ ]
elif st.session_state.selected_view == "Images":# images pagest.header("All images")# getting all imagesimages = get_all_query("jina-images")hits = images["hits"]["hits"]columns = st.columns(5)for idx, hit in enumerate(hits):image_data = base64.b64decode(hit["_source"]["image_data"])image = Image.open(BytesIO(image_data))with columns[idx % 5]:st.image(image, use_container_width=True)

我们将使用以下命令运行该应用程序:

streamlit run app.py

使用 Elasticsearch 来进行图形搜索 - CLIP 替代品

由于多模态性,我们可以在图像数据库中根据文本(文本到图像的相似性)或图像(图像到图像的相似性)运行搜索。

使用 UI 搜索

为了比较这三种模型,我们将使用一个场景,即房地产网页希望通过允许用户使用图像或文本进行搜索来改善其搜索体验。我们将讨论每种模型提供的结果。

我们将上传 “rustic home” 的图片:

以下是搜索结果。如你所见,根据我们上传的图像,每个模型都生成了不同的结果:

此外,你还可以看到根据文本查找房屋特征的结果:

如果搜索 “modern”,这三个模型都会显示良好的结果。但是,JinaCLIP 和 Cohere 会在第一个位置显示相同的房屋。

功能比较

下面是本文中介绍的三个选项的主要功能和价格的摘要:

ModelCreated byEstimated PriceFeatures
CLIPOpenAI每次重复运行 0.00058 美元 (https://replicate.com/krthr/clip-embeddings)针对文本和图像的通用多模态模型;适用于无需特定训练的各种应用。
JinaCLIPJina AI每 100 万枚 Jina tokens 需 0.018 美元 (https://jina.ai/embeddings/)针对多模式应用优化的 CLIP 变体。提高了检索文本和图像的精度。
Embed-3CohereCohere 上每 100 万个 tokens 收费 0.10 美元,每份数据和图像收费 0.0001 美元(https://cohere.com/pricing)专注于企业数据。改进了图形和图表等复杂视觉数据的检索。

如果你要搜索长图像描述,或者想要进行文本转文本和图像转文本,则应放弃 CLIP,因为 JinaCLIP 和 Embed-3 都针对此用例进行了优化。

JinaCLIP 是一种通用模型,而 Cohere 的模型更侧重于企业数据,如产品或图表。

在数据上测试模型时,请确保涵盖:

  • 你感兴趣的所有模式:文本转图像、图像转文本、文本转文本
  • 长图像描述和短图像描述
  • 相似概念匹配(同一类型对象的不同图像)
  • 负面
    • 硬负面:与预期输出相似但仍然错误
    • 简单负面:与预期输出不相似且错误
  • 具有挑战性的场景
    • 不同的角度/视角
    • 各种照明条件
    • 抽象概念(“modern”、“cozy”、“luxurious”)
  • 特定领域案例
    • 技术图表或图表(尤其是 Embed-3)
    • 产品变化(颜色、尺寸、样式)

结论

虽然 CLIP 是进行图像相似性搜索时的首选模型,但在某些情况下,商业和非商业替代方案都可以表现得更好。

JinaCLIP 是一款强大的一体化工具,据称在文本到文本嵌入方面比 CLIP 更精确。

Embed-3 遵循 Cohere 的路线,通过使用典型的业务文档使用真实数据训练模型来满足业务客户的需求。

在我们的小实验中,我们可以看到 JinaClip 和 Cohere 都显示了有趣的图像到图像和文本到图像结果,并且在这些类型的任务中表现与 CLIP 非常相似。

Elasticsearch 允许你搜索嵌入,将向量搜索与全文搜索相结合,使你能够搜索图像和其中的文本。

想要获得 Elastic 认证?了解下一次 Elasticsearch 工程师培训的时间!

Elasticsearch 包含新功能,可帮助你为你的用例构建最佳搜索解决方案。深入了解我们的示例笔记本以了解更多信息,开始免费云试用,或立即在本地机器上试用 Elastic。

原文:Exploring CLIP alternatives - Elasticsearch Labs

相关文章:

Elasticsearch:探索 CLIP 替代方案

作者&#xff1a;来自 Elastic Jeffrey Rengifo 及 Toms Mura 分析图像到图像和文本到图像搜索的 CLIP 模型的替代方案。 在本文中&#xff0c;我们将通过一个模拟房地产网站的实际示例介绍 CLIP 多模态模型&#xff0c;探索替代方案&#xff0c;并分析它们的优缺点&#xff0c…...

天翼云910B部署DeepSeek蒸馏70B LLaMA模型实践总结

一、项目背景与目标 本文记录在天翼云昇腾910B服务器上部署DeepSeek 70B模型的全过程。该模型是基于LLaMA架构的知识蒸馏版本&#xff0c;模型大小约132GB。 1.1 硬件环境 - 服务器配置&#xff1a;天翼云910B服务器 - NPU&#xff1a;8昇腾910B (每卡64GB显存) - 系统内存&…...

Mac 清理缓存,提高内存空间

步骤 1.打开【访达】 2.菜单栏第五个功能【前往】&#xff0c;点击【个人】 3.【command shift J】显示所有文件&#xff0c;打开【资源库】 4.删除【Containers】和【Caches】文件 Containers 文件夹&#xff1a;用于存储每个应用程序的沙盒数据&#xff0c;确保应用程序…...

bash+crontab充当半个守护进程的歪招

两个cpolar下的不同程序&#xff0c;都需要定时监测&#xff0c;以免程序没有再运行。有点类似半个守护进程吧。但是守护进程不会写&#xff0c;咋搞&#xff1f;就用这个办法临时当下守门员。这里主要为了备忘xpgrep -各类参数的用法。 #!/bin/bashif pgrep -fl "check_…...

Android JNI的理解与使用。

写在前面&#xff1a;Java相对于C/C来说是更高级的语言&#xff0c;隐藏了指针&#xff0c;可读性更高&#xff0c;更容易学习&#xff0c;但是无法直接操作硬件、运行速度较慢也是不可回避的硬伤。JNI就是Java官方定义的一套标准“接口”&#xff0c;用于Java和C/C之间互相调用…...

解决DeepSeek服务器繁忙的有效方法

全球42%的企业遭遇过AI工具服务器过载导致内容生产中断&#xff08;数据来源&#xff1a;Gartner 2025&#xff09;。当竞品在凌晨3点自动发布「智能家居安装指南」时&#xff0c;你的团队可能正因DeepSeek服务器繁忙错失「净水器保养教程」的流量黄金期⏳。147SEO智能调度系统…...

PyInstaller全平台打包深度解析:资源打包与路径兼容终极方案

一、典型问题场景分析 案例现象&#xff1a;PyQt5开发的GUI程序本地运行正常&#xff0c;但打包后出现以下问题&#xff1a; 程序图标丢失CSS样式表失效图片资源无法加载配置文件读取失败 问题本质&#xff1a;PyInstaller默认不会打包非代码资源文件&#xff0c;且打包后程…...

FreeSwitch的mod_spandsp模块

FreeSWITCH 的 mod_spandsp 模块是一个基于 Spandsp 库 的核心模块&#xff0c;主要用于实现 传真&#xff08;Fax&#xff09;、DTMF 信号处理 以及 语音编解码转换 等功能。它通过集成 SpandSP 的数字信号处理能力&#xff0c;使 FreeSWITCH 能够与传统通信系统&#xff08;如…...

【c++】【Linux】【进程】线程终止/崩溃 会导致进程终止/崩溃 吗?

【c】【Linux】【进程】线程终止/崩溃 会导致进程终止/崩溃 吗&#xff1f; 1.线程终止会导致进程终止吗&#xff1f; 在操作系统中&#xff0c;线程是进程的基本执行单元&#xff0c;一个进程可以包含一个或多个线程。 当一个子线程终止时&#xff0c;进程并不会因此自动终…...

Deepseek 怼CHATGPT实况

提示词&#xff1a; 用犀利的语言批评ChatGPT 深度思考&#xff08;R1) 嗯&#xff0c;用户让我用犀利的语言批评ChatGPT。首先&#xff0c;我需要理解他们的动机。可能他们遇到了ChatGPT的某些问题&#xff0c;比如回答不准确或者缺乏深度&#xff0c;所以想表达不满。也有…...

内核数据结构用法(2)list

list 在 Linux 内核中&#xff0c;链表操作是通过一组宏和函数来实现的&#xff0c;这些操作通常用来管理和遍历链表。以下是一些常用的链表函数和宏的具体用法。 1. 定义链表节点 首先&#xff0c;你需要定义一个包含 struct list_head 的结构体&#xff1a; #include <…...

量化自学 - 金融理论与python - Net Present Value 净现值

净现值&#xff08;Net Present Value&#xff0c;NPV&#xff09;是金融理论中用于评估投资项目价值的指标。其核心思想是将未来现金流按一定贴现率折算为当前价值&#xff0c;并减去初始投资成本。若NPV为正&#xff0c;表明项目预期收益高于成本&#xff0c;具有投资价值&am…...

Java Web开发实战与项目——用户认证与授权模块开发

Web应用中&#xff0c;用户认证与授权是至关重要的功能&#xff0c;确保只有合法用户才能访问受保护的资源。Spring Security作为一个强大的安全框架&#xff0c;支持多种认证与授权方式。在本章节中&#xff0c;我们将深入探讨三种常见的用户认证与授权方案&#xff1a;基于To…...

蓝桥杯篇---IAP15F2K61S2中断

文章目录 前言简介中断源1.外部中断2.定时器中断3.串口中断4.ADC中断5.PCA中断6.SPI中断7.PWM中断 中断优先级中断相关寄存器1.IE2.IP3.TCON4.SCON 中断使用步骤1.配置中断源2.使能中断3.设置优先级4.编写中断服务程序5.清除中断标志 示例代码&#xff1a;外部中断使用示例代码…...

django连接mysql数据库

1.下载mysqlclient第三方库 2.在settings.py里连接数据库&#xff08;提前建好&#xff09; DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: 学生信息,USER: root,PASSWORD: 999123457,HOST: localhost,POST: 3306,} } 3.在models.py里创建一个类&#xff0…...

Python爬虫TLS

TLS指纹校验原理和绕过 浏览器可以正常访问&#xff0c;但是用requests发送请求失败。 后端是如何监测得呢&#xff1f;为什么浏览器可以返回结果&#xff0c;而requests模块不行呢&#xff1f; https://cn.investing.com/equities/amazon-com-inc-historical-data 1.指纹校…...

Docker 部署 MySQL 8 详细图文教程

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …...

基于Python的Diango旅游数据分析推荐系统设计与实现+毕业论文(15000字)

基于Python的Diango旅游数据分析推荐系系统设计与实现毕业论文指导搭建视频&#xff0c;带爬虫 配套论文1w5字 可定制到某个省份&#xff0c;加40 基于用户的协同过滤算法 有后台管理 2w多数据集 可配套指导搭建视频&#xff0c;加20 旅游数据分析推荐系统采用了Python语…...

网络安全java练习平台 js网络安全

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 网上学习资料一大堆&#xff0c;但如果学到的知识不成体系&#xff0c;遇到问题时只是浅尝辄止&#xff0c;不再深入研究&#xff0c;那么很难做到真正的技术提升…...

在做题中学习(90):螺旋矩阵II

解法&#xff1a;模拟 思路&#xff1a;创建相同大小的一个二维数组&#xff08;矩阵&#xff09;&#xff0c;用变量标记原矩阵的行数和列数&#xff0c;每次遍历完一行或一列&#xff0c;相应行/列数--&#xff0c;进行对应位置的赋值即可。此题是正方形矩阵&#xff0c;因此…...

Educational Codeforces Round 174 (Rated for Div. 2)(ABCD)

A. Was there an Array? 翻译&#xff1a; 对于整数数组 ​&#xff0c;我们将其相等特征定义为数组 &#xff0c;其中&#xff0c;如果数组 a 的第 i 个元素等于其两个相邻元素&#xff0c;则 &#xff1b;如果数组 a 的第 i 个元素不等于其至少一个相邻元素&#xff0c;则 …...

qemu启动aarch64 linux+ buildroot + 应用程序

1、Linux内核网址 https://www.kernel.org/ 2、安装依赖 sudo apt update sudo apt install -y build-essential qemu qemu-system gcc make bc flex bison libssl-dev libncurses5-dev libelf-dev 3、拉取kernel代码和编译kernel git clone --depth 1 https://git.ker…...

Sponge VS Spring:新兴力量与行业标准的碰撞

框架特性对比 特性SpongeSpring编程语言Go (Golang)Java设计范式低代码, 代码生成, 模块化IoC (控制反转), DI (依赖注入), AOP (面向切面编程)性能高性能, 执行速度快, 并发性好成熟的性能, 需要 JVM 调优, 启动时间可能较长成熟度与稳定性较新, 快速发展中非常成熟, 行业标准…...

推荐几款较好的开源成熟框架

一. 若依&#xff1a; 1. 官方网站&#xff1a;https://doc.ruoyi.vip/ruoyi/ 2. 若依SpringBootVueElement 的后台管理系统&#xff1a;https://gitee.com/y_project/RuoYi-Vue 3. 若依SpringBootVueElement 的后台管理系统&#xff1a;https://gitee.com/y_project/RuoYi-Cl…...

【分布式】Hadoop完全分布式的搭建(零基础)

Hadoop完全分布式的搭建 环境准备&#xff1a; &#xff08;1&#xff09;VMware Workstation Pro17&#xff08;其他也可&#xff09; &#xff08;2&#xff09;Centos7 &#xff08;3&#xff09;FinalShell &#xff08;一&#xff09;模型机配置 0****&#xff09;安…...

JavaScript 异步编程:Promise 与 await 的关联与使用

在 JavaScript 中&#xff0c;异步编程是处理耗时操作&#xff08;如网络请求、文件读写等&#xff09;的核心机制。Promise 和 await 是两种常用的异步编程工具&#xff0c;它们密切相关&#xff0c;但又有各自的特点和适用场景。本文将深入探讨它们的关联、区别以及如何在实际…...

体验用ai做了个python小游戏

体验用ai做了个python小游戏 写在前面使用的工具2.增加功能1.要求增加视频作为背景。2.我让增加了一个欢迎页面。3.我发现中文显示有问题。4.我提出了背景修改意见&#xff0c;欢迎页面和结束页面背景是视频&#xff0c;游戏页面背景是静态图片。5.提出增加更多游戏元素。 总结…...

golang常用库之-swaggo/swag根据注释生成接口文档

文章目录 golang常用库之-swaggo/swag库根据注释生成接口文档什么是swaggo/swag golang常用库之-swaggo/swag库根据注释生成接口文档 什么是swaggo/swag github&#xff1a;https://github.com/swaggo/swag 参考文档&#xff1a;https://golang.halfiisland.com/community/pk…...

【可实战】Linux 常用统计命令:排序sort、去重uniq、统计wc

在 Linux 系统中&#xff0c;有一些常用的命令可以用来收集和统计数据。 一、常用统计命令的使用场景 日志分析和监控&#xff1a;通过使用 Linux 统计命令&#xff0c;可以实时监控和分析系统日志文件&#xff0c;了解系统的运行状况和性能指标。例如&#xff0c;使用 tail 命…...

【设计模式】【创建型模式】建造者模式(Builder)

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f44d; 欢迎点赞、收藏、关注&#xff0c;跟上我的更新节奏 &#x1f3b5; 当你的天空突…...

UE5.3 C++ 通过Spline样条实现三维连线,自己UV贴图。

一.制作了基于USplineComponent的画线插件&#xff0c;就是我们常说的样条线。 直接看怎么用&#xff0c;关于插件实现细节&#xff0c;后续会更新&#xff0c;看思路就行。通过ID,管理每一条线。移除删掉上一帧的线条Mesh。第一个点&#xff0c;是本身直接放过去。第二个点是…...

每日学习Java之一万个为什么

9.Class <?> class1 Myclass.class 为什么要有通配符&#xff1f;传给谁用的&#xff1f; 首先&#xff0c;这里的class特指某个对象在JVM中的元数据集合。 有普通、接口、数组、基本类型、 void 类型、局部类、匿名类、枚举、注解 1.类型安全&#xff1a;通配符允许…...

4、IP查找工具-Angry IP Scanner

在前序文章中&#xff0c;提到了多种IP查找方法&#xff0c;可能回存在不同场景需要使用不同的查找命令&#xff0c;有些不容易记忆&#xff0c;本文将介绍一个比较优秀的IP查找工具&#xff0c;可以应用在连接树莓派或查找IP的其他场景中。供大家参考。 Angry IP Scanner下载…...

华为昇腾920b服务器部署DeepSeek翻车现场

最近到祸一台HUAWEI Kunpeng 920 5250&#xff0c;先看看配置。之前是部署的讯飞大模型&#xff0c;发现资源利用率太低了。把5台减少到3台&#xff0c;就出了他 硬件配置信息 基本硬件信息 按照惯例先来看看配置。一共3块盘&#xff0c;500G的系统盘&#xff0c; 2块3T固态…...

一周学会Flask3 Python Web开发-http响应状态码

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 在Flask程序中&#xff0c;客户端发出的请求触发相应的视图函数&#xff0c;获取返回值会作为响应的主体&#xff0c;最后生成…...

Javascript网页设计实例:通过JS实现上传Markdown转化为脑图并下载脑图

功能预览 深度与密度测试 对于测试部分&#xff0c;分别对深度和密度进行了测试&#xff1a; 注意&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;只实现了识别Markdown中的#代表的层级&#xff0c;所以不能使用其余标识符&#xff0…...

【Spring生命周期】Bean元信息配置阶段

引言 本系列将详细讲解Spring生命周期的13个阶段&#xff0c;从源码角度帮助我们更好的理解Spring框架和bean生命周期全流程 Bean信息定义4种方式 API的方式Xml文件方式properties文件的方式注解的方式 在 Spring 框架中&#xff0c;Bean 元信息配置阶段是整个 Bean 生命周…...

【iOS】SwiftUI状态管理

State ObservedObject StateObject 的使用 import SwiftUIclass CountModel: ObservableObject {Published var count: Int 0 // 通过 Published 标记的变量会触发视图更新init() {print("TimerModel initialized at \(count)")} }struct ContentView: View {State…...

ubuntu上如何查看coredump文件默认保存在哪个路径?

在 Ubuntu 系统中&#xff0c;可以通过以下几种方式来查看 coredump 文件默认保存的路径&#xff1a; 1. 查看core_pattern配置 core_pattern是一个内核参数&#xff0c;它决定了 coredump 文件的保存位置和命名规则。可以通过以下命令查看其当前值&#xff1a; cat /proc/s…...

技术总结汇总

目录 数据库 数据库系统原理 MySQL Redis Java Java 基础 Java 容器 Java 并发 Java 虚拟机 Java I/O 系统设计 系统设计基础 微服务 分布式 集群和负载均衡 灾备和故障转移 限流 降级和熔断 缓存 消息队列 设计模式 DDD领域驱动设计 开发框架和中间件…...

Java-如何将其他地方拉取的jar包导入本地maven环境

背景 公司的一个老旧二开项目&#xff0c;原项目维护方不合作了&#xff0c;提供的项目源码提供给到公司。项目中用到了一些原维护方内部的jar包&#xff0c;导致二开时依赖的这些部分全部报错。虽然在项目中直接导入此jar包可以解决报红报错问题&#xff0c;但是在使用maven打…...

Unity 聊天气泡根据文本内容适配

第一步 拼接UI 1、对气泡图进行九宫图切割 2、设置底图pivot位置和对齐方式 pivot位置&#xff1a;&#xff08;0&#xff0c;1&#xff09; 对齐方式&#xff1a;左上对齐 3、设置文本pivot位置和对齐方式&#xff0c;并挂上布局组件 pivot设置和对齐方式和底图一样&#…...

【组态PLC】基于博图V16和组态王六层双部电梯组态设计【含PLC组态源码 M008期】

控制要求 1&#xff09;两台电梯同时运行时&#xff0c;共同享用一套外呼按钮。 2&#xff09;当两台电梯同时去响应外呼信号时&#xff0c;两台电梯自动定向启动前往相应的楼层&#xff0c;当某一台电梯先行到达指定层楼时&#xff0c;另外一台电梯必须就近停靠平层&#xf…...

Python--数据类型(中)

1. 列表&#xff08;list&#xff09; 1.1 定义与特性 定义&#xff1a;有序、可变的容器&#xff0c;支持多种数据类型混合存储。 user_list ["奥力给", 98, True] empty_list [] # 空列表可变性&#xff1a;列表内部元素可修改&#xff0c;区别于字符串和元组。…...

学习总结2.19

首先就是对dfs和bfs的熟悉&#xff0c;dfs是一种递归函数&#xff0c;通过不断深搜来达到目的&#xff0c;通常用于寻找多少未知量&#xff0c;相较于bfs&#xff0c;编译难度更低一点&#xff1b;bfs多用于寻找最短路径之类&#xff0c;相较于dfs代码多了一部分队列的代码&…...

[Vivado报错] [Runs 36-527] DCP does not exist

一、错误原因解析 此错误表明Vivado在指定路径未找到.dcp&#xff08;Design Checkpoint&#xff09;文件&#xff0c;通常由以下原因导致&#xff1a; 路径过长或特殊字符&#xff1a;Windows系统路径长度限制&#xff08;260字符&#xff09;可能导致文件生成失败&#xff…...

深度学习的集装箱箱号OCR识别技术,识别率99.9%

集装箱箱号OCR识别技术是一项结合计算机视觉和规则校验的复杂任务&#xff0c;以下是其关键要点及实现思路的总结&#xff1a; 1、集装箱号结构&#xff1a;11位字符&#xff0c;格式为公司代码(3字母)和序列号(6数字)以及校验码(1数字)和尺寸/类型代码(可选)&#xff0c;例如…...

基于java新闻管理系统,推荐一款开源cms内容管理系统ruoyi-fast-cms

一、项目概述 1.1 项目背景 在信息高速流通的当下&#xff0c;新闻媒体行业每天都要处理和传播海量信息。传统的新闻管理模式依赖人工操作&#xff0c;在新闻采集、编辑、发布以及后续管理等环节中&#xff0c;不仅效率低下&#xff0c;而且容易出现人为失误。同时&#xff0…...

网络安全要学python 、爬虫吗

网络安全其实并不复杂&#xff0c;只是比普通开发岗位要学习的内容多一点。无论是有过编程基础还是零基础的都可以学习的。网络安全目前可就业的岗位从技术上可分为两部分&#xff1a;web安全和二进制逆向安全。web安全是网络安全的入门方向&#xff0c;内容简单&#xff0c;就…...

ChatGPT行业热门应用提示词案例-AI绘画类

AI 绘画指令是一段用于指导 AI 绘画工具&#xff08;如 DALLE、Midjourney 等&#xff09;生成特定图像的文本描述。它通常包含场景、主体、风格、色彩、氛围等关键信息&#xff0c;帮助 AI 理解创作者的意图&#xff0c;从而生成符合要求的绘画作品。 ChatGPT 拥有海量的知识…...