用OpenAI接口给女朋友手搓AI小助理,她说要奖励我,结果……

前言

最近,我那财经系的小女友迎来了考试周,她的复习资料已经堆得像珠穆朗玛峰一样高。压力山大的她不断让我帮她整理这些资料,还频频向我倾诉她的苦水。虽然我自己也挺忙的,但为了爱,我只能忍痛扛起这重担。。。为了减轻我的负担,我向小女友推荐了几个国内的AI网站,让她去找那些冰冷无情但聪明绝顶的机器人求助。虽然整理资料的任务是轻了不少,但她的吐槽却是有增无减,搞得我快成了她的专属垃圾桶。

于是乎,我灵机一动,决定利用OpenAI接口,亲手给她打造一个专属AI小助理。接下来,我将详细介绍如何建立一个小型的网页AI小助理,包括前后端的交互。希望这篇文章不仅能帮你减轻工作量,还能为你的女朋友赚取一些甜蜜的奖励哦!

天才第一步:雀氏。。。一个优雅简洁且可爱的前端界面

首先,我们需要一个前端界面来让亲爱的小女友与AI助手进行互动。下面是一个HTML和CSS的例子,它提供了一个可爱的聊天框和一个还算可爱的输入框,小女友可以在这里键入她的问题并发送给AI助手。话不多说,先上示例图。为了不影响大伙的阅读体验,前端界面的全部代码我就放在文章末尾了。

image.png

第二步:后端-AI助手的大脑

后端部分,我们在当前文件夹下建立一个ai.js文件,使用Node.js和Express来处理与OpenAI的交互。首先,确保你已经安装了必要的依赖包。打开你的终端,输入以下命令:

npm init -y
npm install express body-parser openai dotenv cors

1. 导入必要的模块

const express = require("express");
const bodyParser = require("body-parser");
const OpenAI = require("openai");
const dotenv = require("dotenv");
dotenv.config();

这段代码就像是在召唤超级英雄一样,依次叫来了Express、body-parser和OpenAI模块,还顺便引入了dotenv来加载环境变量。这样我们就能通过process.env来访问我们的OpenAI API密钥了。 随后在当前文件夹下建立一个.env文件,用来存放我们一些不可见人的小秘密数据,比如PORT端口和OPENAI_KEY。

image.png


2. 配置OpenAI客户端

const openai = new OpenAI({apiKey: process.env.OPENAI_KEY,baseURL: "https://api.302.ai/v1",
});

这里,我们配置了OpenAI客户端。apiKey是你的OpenAI密钥,baseURL则是API的地址。这里使用的是302AI的API代理,完全对齐OpenAI的API。至于为什么,因为原生的OpenAI需要绑一张海外信用卡,且充值进去才能用。。。


3. 设置Express应用

const app = express();
const port = process.env.PORT || 3000;

我们创建了一个Express应用实例,并设置了端口。这里使用了环境变量中的端口号,如果没有设置环境变量,则默认使用3000端口。


4. 中间件配置

app.use(bodyParser.json());
app.use(cors());

这里,我们配置了两个中间件。bodyParser.json()用于解析JSON请求体,而cors()则是用来启用跨域资源共享,这样我们就可以从不同的域名访问我们的API了。

5. 初始化聊天历史

let chatHistory = [{ role: "system", content: "You are a helpful assistant." }];

为了让我们的AI助手能有一些上下文,我们初始化了一个聊天历史数组。第一条消息是由“系统”发送的,告诉AI它是一个乐于助人的助手。就像是给AI设定了一个友好的开场白。


6. 处理用户消息

app.post("/chat", async (req, res) => {const userMessage = req.body.message;chatHistory.push({ role: "user", content: userMessage });try {const completion = await openai.chat.completions.create({messages: chatHistory,model: "gpt-3.5-turbo",});const aiMessage = completion.choices[0].message.content;chatHistory.push({ role: "assistant", content: aiMessage });res.json({ aiMessage, chatHistory });} catch (error) {res.status(500).send("处理请求时发生错误。");}
});

这里,我们定义了一个处理POST请求的路由/chat。当用户发送消息时:

  1. 从请求体中获取用户的消息userMessage,并将其添加到聊天历史中。
  2. 调用OpenAI的API生成回复。具体来说,调用了chat.completions.create方法,并传递了当前的聊天历史和所使用的模型。
  3. 将AI的回复添加到聊天历史中,然后将AI的回复和更新后的聊天历史返回给前端。

如果在处理过程中遇到错误,我们会返回一个500状态码,并在响应中发送错误信息。


7. 启动服务器

app.listen(port, () => {console.log(`Server is running on http://localhost:${port}`);
});

最后,我们启动了服务器,让它在指定端口上监听。这样,我们的AI助手就正式上线了!你可以访问这个ip地址,与这个小猫老弟智能助手进行愉快的对话。

第三步:前端与后端之间的小小润滑

1. 准备工作

document.addEventListener("DOMContentLoaded", function () {// ...
}

首先,我们需要确保页面加载完成后再执行代码。这就是DOMContentLoaded事件的作用,确保页面所有元素都已经加载完毕。


2. 获取元素和初始化

const sendButton = document.querySelector(".button--submit");
const closeButton = document.querySelector(".button--close-window");
const chatBox = document.getElementById("ai-window-chatbox");
const placeholder = document.querySelector(".ai-placeholder");
const overlay = document.querySelector(".overlay");
const openAiButton = document.querySelector(".button--openai");
const aiWindow = document.querySelector(".ai-window");
const textarea = document.getElementById("ai-window-userInput");

这些变量就像是我们要控制的道具箱,每个按钮和输入框都有它独特的功能,为用户提供最佳的体验。


3. 调整文本框的高度

function adjustHeight() {const minHeight = 35;textarea.style.height = minHeight + "px";textarea.style.height = Math.max(minHeight, Math.min(textarea.scrollHeight, 180)) + "px";
}textarea.addEventListener("input", adjustHeight);
adjustHeight();

这里的作用是不断地调整输入框的高度,确保它既不会太矮,也不会太高。我们希望它看起来刚刚好,保持优雅。


4. 发送消息的函数

async function sendMessage() {// 获取用户输入,空则退出函数const message = textarea.value.trim();if (!message) return;// 清空输入框内容,调正输入框高度,隐藏小猫老弟,展示聊天内容textarea.value = "";adjustHeight();if (placeholder) {placeholder.style.display = "none";}// 将用户发送内容添加进聊天记录,并将内容md语法化const userMessageHTML = `<div class="message user"><strong>你:</strong> ${marked.parse(message)}</div>`;chatBox.innerHTML += userMessageHTML;// 禁用发送按钮sendButton.disabled = true;try {// 获取AI回复,这里向app监听的端口发送请求const response = await fetch("http://localhost:3000/chat", {method: "POST",headers: { "Content-Type": "application/json" },body: JSON.stringify({ message }),});if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}// 拿到回复数据,将其md语法化之后添加进聊天记录const data = await response.json();const aiMessage = data.aiMessage;const aiMessageHTML = `<div class="message assistant"><strong>小猫:</strong> ${marked.parse(aiMessage)}</div>`;chatBox.innerHTML += aiMessageHTML;} catch (error) {// 打印错误到控制台,并且在页面上显示系统出错console.error("Fetch Error:", error);const errorMessageHTML = `<div class="message system"><strong>系统:</strong> 出错了,请稍后再试。</div>`;chatBox.innerHTML += errorMessageHTML;} finally {// 启用发送按钮sendButton.disabled = false;}// 滚动到底部显示最新消息chatBox.scrollTop = chatBox.scrollHeight;
}

发送消息的过程就像一场激动人心的告白,你输入内容,点击发送,心跳加速等待对方的回复。代码中,我们首先获取用户输入,清空输入框,并调整高度。如果有内容,则发送给服务器,等待 AI 的回应。如果出错了,也会优雅地告诉你“系统出错了,请稍后再试”。


5. 添加事件监听器

sendButton.addEventListener("click", sendMessage);
textarea.addEventListener("keydown", (e) => {if (e.key === "Enter" && !e.shiftKey) {e.preventDefault();sendMessage();}
});

我们绑定了点击发送按钮和按下回车键的事件。除此之外我们可以用shift + enter来进行换行


6. 关闭按钮和模糊背景点击事件

// 关闭窗口事件
closeButton.addEventListener("click", () => {aiWindow.classList.add("hidden");overlay.classList.add("hidden");
});overlay.addEventListener("click", () => {aiWindow.classList.add("hidden");overlay.classList.add("hidden");
});// 打开窗口事件
openAiButton.addEventListener("click", () => {aiWindow.classList.remove("hidden");overlay.classList.remove("hidden");
});

点击关闭按钮或遮罩层,AI 窗口和背景同时消失。点击打开按钮,AI 窗口和背景同时出现。

结尾

以上就是手搓一个AI小助理的全过程!完成后我将这个小程序应用到了写给女朋友的网站上,女朋友访问后开心的像个傻子,说要好好的疼爱疼爱我。。。不说了,逛商城了。

最后,希望大伙能从中获得灵感,让生活变得更加智能和有趣。如果你也有类似的需求,不妨试试这个小项目,享受AI带来的便利和乐趣吧!

最后的最后,祝大家都能顺利完成任务,收获意外的惊喜和奖励!

image.png (也是被AI正义执行了。。。)


HTML主要代码

    <div class="ai-window flex-col al-center jtf-space-B hidden"><button class="button--close-window">&times;</button><div id="ai-window-chatbox" class="ai-chatbox flex-col al-center"><div class="ai-placeholder flex-col al-center jtf-center"><imgwidth="64"src="https://img.icons8.com/pastel-glyph/64/000000/cat--v2.png"alt="cat--v2"/><p>需要帮助吗?请向我提问!</p></div></div><div class="ai-userInput-box flex al-center jtf-space-B"><textarearows="1"id="ai-window-userInput"placeholder="给小猫老弟发送消息"class="ai-userInput"></textarea><button class="button--submit"><svgxmlns="http://www.w3.org/2000/svg"fill="none"viewBox="0 0 24 24"stroke-width="1.5"stroke="currentColor"class="send-icon"><pathstroke-linecap="round"stroke-linejoin="round"d="M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18"/></svg></button></div></div><div class="overlay hidden"></div><button class="button--openai"><imgwidth="48"src="https://img.icons8.com/pastel-glyph/64/000000/cat--v2.png"alt="cat--v2"/></button>

CSS代码

/*******************************/
/******* 全局设置 *******/
/*******************************/
* {margin: 0;padding: 0;box-sizing: border-box;
}html {font-size: 62.5%;
}body {font-family: "Poppins", "ZCOOL XiaoWei", sans-serif;color: rgb(255, 255, 255, 0.8);
}/*******************************/
/******* AI助理部分 *******/
/*******************************/
.button--openai {border: none;background-color: #f7f6f6;width: 6.4rem;height: 6.4rem;padding: 8px;cursor: pointer;position: absolute;border-radius: 50%;box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.2);bottom: 7%;right: 5%;transition: all 0.2s;
}.button--openai:hover {background-color: rgba(247, 246, 246, 0.6);
}.button--openai img {position: absolute;top: 0;left: 8%;
}.ai-window {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 70%;height: 80%;background-color: #fff;padding: 6rem;border-radius: 5px;box-shadow: 0 3rem 5rem rgba(0, 0, 0, 0.3);z-index: 10;
}.button--close-window {position: absolute;top: 2rem;right: 3.2rem;font-size: 5rem;color: #333;cursor: pointer;border: none;background: none;
}.ai-chatbox {width: 90%;height: 80%;color: #333;overflow-y: auto;
}.ai-placeholder {height: 100%;text-align: center;font-size: 1.6rem;
}.ai-userInput-box {width: 90%;color: #000;padding: 8px 10px;font-family: sans-serif;background-color: #efefef;border-radius: 26px;
}.ai-userInput {border: none;background-color: transparent;width: 90%;padding: 8px 12px;font-size: 1.6rem;overflow-y: auto;resize: none;
}.ai-userInput:focus {outline: none;
}.button--submit {width: 3.2rem;height: 3.2rem;border: none;background-color: #000;border-radius: 50%;padding: 5px;color: white;cursor: pointer;transition: all 0.1s;
}.button--submit:hover {background-color: rgba(0, 0, 0, 0.6);
}.message {font-size: 1.6rem;width: initial;margin: 10px;padding: 10px;border-radius: 10px;
}.message.user {background-color: #d1e7dd;align-self: flex-end;
}.message.assistant {background-color: #f8d7da;align-self: flex-start;
}.message.system {background-color: #fff3cd;align-self: center;text-align: center;
}/*******************************/
/******* 工具类部分 *******/
/*******************************/.overlay {position: absolute;top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.6);backdrop-filter: blur(3px);z-index: 5;
}.hidden {display: none !important;
}.flex {display: flex;
}.flex-col {display: flex;flex-direction: column;
}.al-center {align-items: center;
}.jtf-center {justify-content: center;
}.jtf-space-A {justify-content: space-around;
}.jtf-space-B {justify-content: space-between;
}

ai.js代码

const express = require("express");
const bodyParser = require("body-parser");
const OpenAI = require("openai");
const cors = require("cors");
const dotenv = require("dotenv");
dotenv.config();const openai = new OpenAI({apiKey: process.env.OPENAI_KEY,baseURL: "https://api.302.ai/v1",
});const app = express();
const port = process.env.PORT || 3000;app.use(bodyParser.json());app.use(cors());let chatHistory = [{ role: "system", content: "You are a helpful assistant." }];app.post("/chat", async (req, res) => {const userMessage = req.body.message;chatHistory.push({ role: "user", content: userMessage });try {const completion = await openai.chat.completions.create({messages: chatHistory,model: "gpt-3.5-turbo",});const aiMessage = completion.choices[0].message.content;chatHistory.push({ role: "assistant", content: aiMessage });res.json({ aiMessage, chatHistory });} catch (error) {res.status(500).send("处理请求时发生错误。");}
});app.listen(port, () => {console.log(`Server is running on http://localhost:${port}`);
});

script.js(前端引用)代码

"use strict";document.addEventListener("DOMContentLoaded", function () {const sendButton = document.querySelector(".button--submit");const closeButton = document.querySelector(".button--close-window");const chatBox = document.getElementById("ai-window-chatbox");const placeholder = document.querySelector(".ai-placeholder");const overlay = document.querySelector(".overlay");const openAiButton = document.querySelector(".button--openai");const aiWindow = document.querySelector(".ai-window");const textarea = document.getElementById("ai-window-userInput");function adjustHeight() {const minHeight = 35;textarea.style.height = minHeight + "px";textarea.style.height =Math.max(minHeight, Math.min(textarea.scrollHeight, 180)) + "px";}textarea.addEventListener("input", adjustHeight);adjustHeight(); // 初始化调整高度async function sendMessage() {const message = textarea.value.trim();if (!message) return;textarea.value = "";adjustHeight();if (placeholder) {placeholder.style.display = "none";}const userMessageHTML = `<div class="message user"><strong>你:</strong> ${marked.parse(message)}</div>`;chatBox.innerHTML += userMessageHTML;sendButton.disabled = true;try {const response = await fetch("http://localhost:3000/chat", {method: "POST",headers: { "Content-Type": "application/json" },body: JSON.stringify({ message }),});if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}const data = await response.json();const aiMessage = data.aiMessage;const aiMessageHTML = `<div class="message assistant"><strong>小猫:</strong> ${marked.parse(aiMessage)}</div>`;chatBox.innerHTML += aiMessageHTML;} catch (error) {console.error("Fetch Error:", error);const errorMessageHTML = `<div class="message system"><strong>系统:</strong> 出错了,请稍后再试。</div>`;chatBox.innerHTML += errorMessageHTML;} finally {sendButton.disabled = false;}chatBox.scrollTop = chatBox.scrollHeight;}sendButton.addEventListener("click", sendMessage);textarea.addEventListener("keydown", (e) => {if (e.key === "Enter" && !e.shiftKey) {e.preventDefault();sendMessage();}});closeButton.addEventListener("click", () => {aiWindow.classList.add("hidden");overlay.classList.add("hidden");});overlay.addEventListener("click", () => {aiWindow.classList.add("hidden");overlay.classList.add("hidden");});openAiButton.addEventListener("click", () => {aiWindow.classList.remove("hidden");overlay.classList.remove("hidden");});
});

如何学习AI大模型?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

在这里插入图片描述

👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

在这里插入图片描述

1.AI大模型学习路线图
2.100套AI大模型商业化落地方案
3.100集大模型视频教程
4.200本大模型PDF书籍
5.LLM面试题合集
6.AI产品经理资源合集

👉获取方式:
😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39169.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】STL-priority_queue

目录 1、priority_queue的使用 2、实现没有仿函数的优先级队列 3、实现有仿函数的优先级队列 3.1 仿函数 3.2 真正的优先级队列 3.3 优先级队列放自定义类型 1、priority_queue的使用 priority_queue是优先级队列&#xff0c;是一个容器适配器&#xff0c;不满足先进先出…

Spring Boot配置文件properties/yml/yaml

一、Spring Boot配置文件简介 &#xff08;1&#xff09;名字必须为application,否则无法识别。后缀有三种文件类型&#xff1a; properties/yml/yaml&#xff0c;但是yml和yaml使用方法相同 &#xff08;2&#xff09; Spring Boot 项⽬默认的配置文件为 properties &#xff…

【单片机毕业设计选题24041】-基于STM32的水质检测系统

系统功能: 系统上电后显示“欢迎使用水质检测系统请稍后”两秒后进入正常显示页面。 第一页面第一行显示“系统状态信息”&#xff0c;第二行显示温度和PH值信息&#xff0c;第三行显示 浑浊度信息&#xff0c;第四行显示TDS值信息。 第一页面下的按键操作&#xff1a; 短…

SSE代替轮询?

什么是 SSE SSE&#xff08;Server-Sent Events&#xff0c;服务器发送事件&#xff09;&#xff0c;为特定目的而扩展的 HTTP 协议&#xff0c;用于实现服务器向客户端推送实时数据的单向通信。如果连接断开&#xff0c;浏览器会自动重连&#xff0c;传输的数据基于文本格式。…

[python][Anaconda]使用jupyter打开F盘或其他盘文件

jupyter有一个非常不好的体验&#xff0c;就是不能在界面切换到其他盘来打开文件。 使用它&#xff0c;比较死板的操作是要先进入文件目录&#xff0c;再运行jupyter。 以Windows的Anaconda安装了jupyter lab或jupyter notebook为例。 1&#xff0c;先运行Anaconda Prompt 2&…

基于OpenCV与Keras的停车场车位自动识别系统

本项目旨在利用计算机视觉技术和深度学习算法&#xff0c;实现对停车场车位状态的实时自动识别。通过摄像头监控停车场内部&#xff0c;系统能够高效准确地辨认车位是否被占用&#xff0c;为车主提供实时的空闲车位信息&#xff0c;同时为停车场管理者提供智能化的车位管理工具…

网优小插件_基于chrome浏览器Automa插件编写抓取物业点信息小工具

日常在无线网络优化&#xff0c;经常需要提取某一地市&#xff0c;某个属性物业点信息&#xff08;物业点名称、地址、及经纬度信息&#xff09;&#xff0c;本文介绍基于chrome浏览器Automat插件开发自动化工具&#xff0c;利用百度地图经纬度拾取网资源开发一个抓取物业点基本…

为什么这几年参加PMP考试的人越来越多

参加PMP认证的人越来越多的原因我认为和社会发展、职场竞争、个人提升等等方面有着不小的关系。国际认证与国内认证的性质、发展途径会有一些区别&#xff0c;PMP引进到中国二十余年&#xff0c;报考人数持增长状态也是正常的。 具体可以从下面这几个点来展开论述。 市场竞争…

Rakis: 免费基于 P2P 的去中心化的大模型

是一个开源的&#xff0c;完全在浏览器中运行的去中心化 AI 推理网络&#xff0c;用户无需服务器&#xff0c;打开即可通过点对点网络使用 Llama-3、Mistral、Gemma-2b 等最新开源模型。 你可以通过右上角的 Scale Worker &#xff0c;下载好模型后挂机就能作为节点加入到这个…

JVM线上监控环境搭建Grafana+Prometheus+Micrometer

架构图 一: SpringBoot自带监控Actuator SpringBoot自带监控功能Actuator&#xff0c;可以帮助实现对程序内部运行情况监控&#xff0c;比如监控内存状况、CPU、Bean加载情况、配置属性、日志信息、线程情况等。 使用步骤&#xff1a; 1. 导入依赖坐标 <dependency><…

海外报纸媒体投放形式分为哪些?传播当中有什么优势-大舍传媒

国外报纸媒体投放新闻稿作为一种传统而有效的传播方式&#xff0c;依然在现代媒体环境中保持着其独特的价值和权威性。以下几点阐述了报纸媒体宣发的几个关键方面&#xff0c;特别是当通过专业机构如大舍传媒进行操作时&#xff1a; 权威性和公信力&#xff1a;报纸作为历史悠久…

基于Hadoop平台的电信客服数据的处理与分析③项目开发:搭建Kafka大数据运算环境---任务12:安装Kafka

任务描述 任务内容为安装和配置Kafka集群。 任务指导 Kafka是大数据生态圈中常用的消息队列框架 具体安装步骤如下&#xff1a; 1. 解压缩Kafka的压缩包 2. 配置Kafka的环境变量 3. 修改Kafka的配置文件&#xff0c;Kafka的配置文件存放在Kafka安装目录下的config中 4. 验证…

LangChain 一 hello LLM

本来想先写LangChain系列的&#xff0c;但是最近被AutoGen、LlamaIndex给吸引了。2023就要过去了&#xff0c;TIOBE数据编程语言排名Python都第一了&#xff0c;可见今年AI开发之热。好吧&#xff0c;一边学习业界通用的LangChain框架&#xff0c;一边准备跨年吧。 前言 先是O…

使用 PostGIS 生成矢量图块

您喜欢视听学习吗&#xff1f;观看视频指南&#xff01; 或者直接跳到代码 Overture Maps Foundation是由亚马逊、Meta、微软和 tomtom 发起的联合开发基金会项目&#xff0c;旨在创建可靠、易于使用、可互操作的开放地图数据。 Overture Maps 允许我们以GeoJSON格式下载开放…

【面试系列】产品经理高频面试题及详细解答

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&#xff1a;详细讲解AIGC的概念、核心技术、…

工业读码器与商用扫码器的区别

条码二维码在数字信息化应用越来越广泛&#xff0c;扫码器成为了数据收集和处理的重要工具&#xff0c;无论是工厂生产和物流包裹朔源追踪&#xff0c;还是商场超市扫码收银和餐饮娱乐等场景&#xff0c;均能看到扫码器的辅助&#xff0c;市场上的扫码器种类繁多&#xff0c;在…

【力扣】赎金信

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 ​ 给你两个字符串…

研发都认为DBA很Low?我反手一个嘴巴子

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…

antd(5.x) Popover 的content有个modal,关不掉了

问题描述&#xff1a; 如上图所示&#xff0c;我的提示modal 关不掉了&#xff0c;思考问题症结在handleVisibleChange const content (<div className{styles.box}>别的样式</div>{/* 链接 */}<div className{styles.linkBox}><Modaltitle{提示}open{…

武汉星起航:跨境电商流量红利爆发,2023年出海企业迎突破增长

在数字时代的浪潮中&#xff0c;中国跨境电商以惊人的爆发力崭露头角&#xff0c;成为全球贸易的璀璨新星。2023年数据显示&#xff0c;跨境电商出口额高达1.83万亿元&#xff0c;同比增长19.6%&#xff0c;这一显著增速不仅刷新纪录&#xff0c;更为众多出海企业带来了前所未有…