C++编写Redis客户端
目录
安装redis-plus-plus库
编辑
编译C++redis客户端
redis的通用命令使用
get/set
exists
del
keys
expire /ttl
type
string类型核心操作
set和get
set带有超时时间
set带有NX
string带有XX
mset
mget
getrange和setrange
incr和decr
list类型核心操作
lpush和lrange
lpop和rpop
brpop
llen
set类型核心操作
sadd和smembers
sismember
scard
spop
sinter
sinterstore
hash类型核心操作
hset和hget
hexists和hdel和hlen
hmset和hmget
hkeys hvals
zset类型核心操作
zadd和zrange
zscore
zrank
安装redis-plus-plus库
C++操作redis的库有很多,这里使用redis-plus-plus,我们需要在githb上下载。
github地址:GitHub - sewenew/redis-plus-plus: Redis client written in C++
github在国内的时候有时候会抽风,网不好,怎么呢?fq当然可以打开github,但fq是违法行为。

那有没有合法的方式打开呢?我们可以下载Watt Toolkit软件,这玩意其实就是一个游戏加速器。

打开之后点击网络加速,这里面可以对github进行加速。

打开github后往下面翻,可以看到下载,要下载redis-plus-plus要先安装hiredis。
安装hiredis
ubuntu
apt install libhiredis-dev

安装redis-plus-plus
下载redis-plus-plus源
git clone https://github.com/sewenew/redis-plus-plus.git
安装好源之后,按照下面的命令执行即可
cd redis-plus-plus
mkdir build // 创建一个 build、 目录是习惯用法,让编译临时生成的文件放在改目录下
cd build
cmake .. // 生成makefile
make // 进行编译
make install // 把库考到系统目录
cd ..
安装完毕后,头文件会装到 /usr/local/include/sw/的redis++。
编译C++redis客户端
要写redis代码需要包含一下头文件<sw/redis++/redis++.h>。
当我们创建好Redis对象之后,执行的各种命令,其实就是该类中调用各种方法即可。
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <sw/redis++/redis++.h>using namespace std;int main()
{// 创建redis对象的时候需要再构造函数中指定 redis 服务器的地址和端口 由于我们redis客户端和服务器在同一个主机,写本地回环即可sw::redis::Redis redis("tcp://127.0.0.1:6379"); // 如果是不同主机,就写对应主机的ip即可,6379是端口号// 测试是否连接成功 让客户端给服务器发送一个 ping 服务器会返回一个 PONG,通过返回值获取到string result = redis.ping();cout << result << endl;return 0;}
使用makefile编译文件
编译程序的时候,需要引入库文件。
1. redis++自己的静态库
我们可以使用find命令查找。

/usr/local/lib/libredis++.a
2.hiredis的静态库

/usr/lib/x86_64-linux-gnu/libhiredis.a
3.线程库
-pthread直接写就可以
hello:01.hello.ccg++ -o $@ $^ -std=c++17 /usr/local/lib/libredis++.a /usr/lib/x86_64-linux-gnu/libhiredis.a -pthread.PHONY:clean
clean:rm -f hello

redis的通用命令使用
如果会使用redis的命令,那么使用C++编写redis客户端是非常简单的,很多都是接口都是一样的设计,命令的参数怎么写的的函数的参数就怎么传递就行。下面我并不会介绍每个函数的作用是啥,因为默认各位都是对命令了然于胸的,如果看到哪一个命令想不起来它的作用,随便上网查一下即可,或者是看下代码应该就能想起来,并且我不会把所有的命令都写出来,因为有些命令是非常简单的。
get/set

void test1(sw::redis::Redis &redis)
{cout << "get 和 set 的使用" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();// 使用 set 设置 keyredis.set("key1", "111");redis.set("key2", "222");redis.set("key3", "333");// 使用 get 获取 key// get的返回值是sw::redis::OptionalString类型auto value1 = redis.get("key1");// optional 可以隐式转换成 bool 类型,可以直接在 if中判断,如果是无效元素,就返回false// 使用之前判断是否存在if (value1){// get的返回值是sw::redis::OptionalString类型,cout不支持该类型的运算符重载// 此处把sw::redis::OptionalString里面包含的值取出来就行,OptionalString只包含一个元素的容器// 可以使用value()方法取出来cout << "key1: " << value1.value() << endl;}auto value2 = redis.get("key2");if (value2){cout << "key2: " << value2.value() << endl;}auto value3 = redis.get("key3");if (value3){cout << "key3: " << value3.value() << endl;}// redis中并不存在key4auto value4 = redis.get("key4");if (value4){cout << "key4: " << value4.value() << endl;}
}

exists
// exists
void test2(sw::redis::Redis &redis)
{cout << "exists" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();// 使用 set 设置 keyredis.set("key1", "111");// 存在的key// 返回值是一个long long类型,表示有几个key存在auto ret = redis.exists("key1");cout << ret << endl;// 不存在的keyret = redis.exists("key2");cout << ret << endl;// 判定多个 keyredis.set("key3", "333");ret = redis.exists({"key1", "key2", "key3"});cout << ret << endl;
}

del
void test3(sw::redis::Redis &redis)
{cout << "del" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();// 使用 set 设置 keyredis.set("key1", "111");redis.set("key2", "222");// 删除一个key// 返回值是成功删除的个数auto ret = redis.del("key1");cout << ret << endl; // key1 存在返回值为1 表示删除1个// 删除多个keyret = redis.del({"key2", "key3"});cout << ret << endl; // key2 存在 key3 不存在 返回值2 表示删除2个// 判定被删除的key是否存在ret = redis.exists({"key1", "key2"}); // key1 key2都被删除了,因此存在个数0cout << ret << endl;
}

keys
void test4(sw::redis::Redis &redis)
{cout << "keys" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();// 使用 set 设置 keyredis.set("key1", "111");redis.set("key2", "222");redis.set("key3", "333");redis.set("key4", "444");redis.set("key5", "555");redis.set("key6", "666");// keys第一个参数匹配规则// keys第二个参数是一个"插入迭代器",需要先准备好一个保存结果的容器// 接下来在创建一个插入迭代器指向容器的位置,就可以吧keys获取到的结果依次通过刚才的插入迭代器插入到容器指定位置中vector<string> v;// 这个auto的类型是 back_inserter<std::vector<std::string>>// 此处的it就指向v的起始地址auto it = back_inserter(v);// 这个地方是把keys查询的所有结果插入到v这个容器中redis.keys("*", it);// keys查询的key都放到v这个容器中// 遍历vector,查看结果for (auto &elem : v){cout << elem << endl;}
}

expire /ttl
void test5(sw::redis::Redis &redis)
{cout << "expire and ttl" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();// 使用 set 设置 keyredis.set("key1", "111");// 设置key的过期时间redis.expire("key1", 10); // 这里可以直接跟字面值表示10sredis.expire("key1", chrono::seconds(10)); // 建议使用chrono的库函数,更加直观// 先休眠一会再查看过期时间this_thread::sleep_for(chrono::seconds(5)); // 休眠5s// 获取key的过期时间long long time = redis.ttl("key1");cout << time << endl; // 5s后,key1的过期时间还剩5s
}

type
void test6(sw::redis::Redis &redis)
{cout << "type" << endl;// 1.清空一下数据库redis.flushall();// 2. string 类型redis.set("key1", "111");string type = redis.type("key1");cout << "key1: " << type << endl;// 3. list 类型redis.lpush("key2", "111");type = redis.type("key2");cout << "key2: " << type << endl;// 4. hash 类型redis.hset("key3", "field1", "111");type = redis.type("key3");cout << "key3: " << type << endl;// 5. set 类型redis.sadd("key4", "111");type = redis.type("key4");cout << "key4: " << type << endl;// 6. zset 类型redis.zadd("key5", "吕布", 99);type = redis.type("key5");cout << "key5: " << type << endl;
}

string类型核心操作
set和get
void test1(sw::redis::Redis &redis)
{cout << "get 和 set 的使用" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();redis.set("key", "111");// value是optionalString类型,需要使用value()方法取出来auto value = redis.get("key");if (value){std::cout << "value: " << value.value() << std::endl;}// 修改key的valueredis.set("key", "222");value = redis.get("key");if (value){std::cout << "value: " << value.value() << std::endl;}}

set带有超时时间
void test2(sw::redis::Redis &redis)
{cout << "set 带有超时时间" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();// 给key设置超时时间为9sredis.set("key", "111", chrono::seconds(9));// 休息6sthis_thread::sleep_for(chrono::seconds(6));// 获取超时时间auto time = redis.ttl("key");cout << "time: " << time << endl;
}

set带有NX
void test3(sw::redis::Redis &redis)
{cout << "set NX 和 XX" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();// 包含该命名空间可以直接使用 0s 这样的字面值常量using namespace std::chrono_literals;// set的重载版本中,没有单独提供 NX 和 XX版本,必须搭配过期时间使用,不需要过期时间就设置为0s// 不存在就设定redis.set("key", "111", 0s, sw::redis::UpdateType::NOT_EXIST);auto value = redis.get("key");if (value){cout << "value: " << value.value() << endl;}else{cout << "key 不存在!" << endl;}
}

void test3(sw::redis::Redis &redis)
{cout << "set NX 和 XX" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();// 包含该命名空间可以直接使用 0s 这样的字面值常量using namespace std::chrono_literals;redis.set("key", "111");// set的重载版本中,没有单独提供 NX 和 XX版本,必须搭配过期时间使用,不需要过期时间就设置为0s// 上面已经设置了key,所有下面set不会设置成功redis.set("key", "222", 0s, sw::redis::UpdateType::NOT_EXIST);auto value = redis.get("key");if (value){// 打印的结果是111cout << "value: " << value.value() << endl;}else{cout << "key 不存在!" << endl;}
}

string带有XX
void test3(sw::redis::Redis &redis)
{cout << "set NX 和 XX" << endl;// 1.清空一下数据库,以免影响我们使用redis.flushall();// 包含该命名空间可以直接使用 0s 这样的字面值常量using namespace std::chrono_literals;redis.set("key", "111");// set的重载版本中,没有单独提供 NX 和 XX版本,必须搭配过期时间使用,不需要过期时间就设置为0s// 已经存在才能设置成功,上面存在,因此可以设置成功redis.set("key", "222", 0s, sw::redis::UpdateType::EXIST);auto value = redis.get("key");if (value){// 打印的结果是222cout << "value: " << value.value() << endl;}else{cout << "key 不存在!" << endl;}
}

mset
void test4(sw::redis::Redis &redis)
{cout << "mset" << endl;redis.flushall();// 第一种写法,使用初始化列表描述多个键值对redis.mset({make_pair("key1", "111"),make_pair("key2", "222")});// 第二种写法,把多个键值对提前放到容器中,以迭代器的形式告诉msetvector<pair<string, string>> keys;keys.push_back(make_pair("key3", "333"));keys.push_back(make_pair("key4", "444"));redis.mset(keys.begin(), keys.end());auto value = redis.get("key1");if (value){cout << "value: " << value.value() << endl;}value = redis.get("key2");if (value){cout << "value: " << value.value() << endl;}value = redis.get("key3");if (value){cout << "value: " << value.value() << endl;}value = redis.get("key4");if (value){cout << "value: " << value.value() << endl;}
}

mget
void test5(sw::redis::Redis &redis)
{cout << "mget" << endl;redis.flushall();vector<pair<string, string>> keys;keys.push_back(make_pair("key1", "111"));keys.push_back(make_pair("key2", "222"));keys.push_back(make_pair("key3", "333"));redis.mset(keys.begin(), keys.end());vector<sw::redis::OptionalString> values;auto it = std::back_inserter(values);redis.mget({"key1", "key2", "key3", "key4"}, it);for (auto &elem : values){if (elem)cout << elem.value() << endl;elsecout << "元素无效" << endl;}
}

getrange和setrange
void test6(sw::redis::Redis &redis)
{cout << "getrange and setrange " << endl;redis.flushall();redis.set("key", "hello world");// 获取到下标2-5的字符string ret = redis.getrange("key", 2, 5);cout << "ret: " << ret << endl;// 将下标2后面的字符修改为musicredis.setrange("key", 2, "music");auto value = redis.get("key");if (value)cout << "value: " << value.value() << endl;
}

incr和decr
void test7(sw::redis::Redis &redis)
{cout << "incr end decr" << endl;redis.flushall();redis.set("key", "100");// 自增long long ret = redis.incr("key");auto value = redis.get("key");if (value)cout << "value: " << value.value() << endl;// 自减ret = redis.decr("key");value = redis.get("key");if (value)cout << "value: " << value.value() << endl;
}

list类型核心操作
lpush和lrange
void test1(Redis &redis)
{cout << "lpush 和 lrange" << endl;redis.flushall();// 插入单个元素redis.lpush("key", "111");// 插入一组元素,基于初始化列表redis.lpush("key", {"222", "333", "444"});// 插入一组元素,基于迭代器vector<string> values = {"555", "666", "777"};redis.lpush("key", values.begin(), values.end());// lrange 获取到列表中的元素vector<string> results;auto it = std::back_inserter(results);redis.lrange("key", 0, -1, it);for (auto &elem : results){cout << elem << endl;}
}
lpush是头插,因此越后面的元素在前面。 rpush和lpush的用法是一模一样的,这里就不介绍了。

lpop和rpop
void test3(Redis &redis)
{cout << "lpop 和 rpop" << endl;redis.flushall();// 构造一个 listredis.rpush("key", {"111", "222", "333", "444", "555"});// lpop 从左边弹出一个元素auto value = redis.lpop("key");if (value)cout << value.value() << endl;// rpop 从右边弹出一个元素value = redis.rpop("key");if (value)cout << value.value() << endl;
}

brpop
阻塞删除一个key
void test4(Redis &redis)
{cout << "blpop" << endl;redis.flushall();// key不存在一定会阻塞// 返回值是 OptionalStringPair 是一个pair// pair的first是来自哪一个key// pair的second是哪个元素被删了auto result = redis.blpop("key");if (result){cout << "key:" << result.value().first << endl;cout << "elem:" << result.value().second << endl;}else{cout << "result 无效!" << endl;}
}


阻塞删除多个key 并设置超时时间
void test4(Redis &redis)
{using namespace std::chrono_literals;cout << "blpop" << endl;redis.flushall();// key不存在一定会阻塞// 返回值是 OptionalStringPair 是一个pair// pair的first是来自哪一个key// pair的second是哪个元素被删了auto result = redis.blpop({"key", "key1", "key2"}, 10s);if (result){cout << "key:" << result.value().first << endl;cout << "elem:" << result.value().second << endl;}else{cout << "result 无效!" << endl;}
}
llen
void test5(Redis &redis)
{cout << "llen" << endl;redis.flushall();redis.lpush("key", {"111", "222", "333", "444", "555"});long long len = redis.llen("key");cout << "len: " << len << endl;
}

redis-plus-plus这个库,接口风格设计是非常统一的。
当一个函数,参数需要传递多个值的时候,往往都是支持初始化列表或者是一对迭代器的方式来进行实现。
当一个函数,返回值需要表示多个数据的时候,往往也会借助插入迭代器,来实现往一个容器中添加元素的效果。
当某些场景涉及到无效值的时候,往往会搭配std::optional来进行使用。
set类型核心操作
sadd和smembers
void test1(Redis &redis)
{cout << "sadd 和 smembers" << endl;redis.flushall();// 一次添加一个元素redis.sadd("key", "111");// 一次添加多个元素 使用初始化列表redis.sadd("key", {"222", "333", "444"});// 一次添加多个元素 使用迭代器// 使用什么容器都可以,set、vector、list...set<string> elems = {"555", "666", "777"};redis.sadd("key", elems.begin(), elems.end());// 获取集合中的所有元素vector<string> result;auto it = std::back_inserter(result);redis.smembers("key", it);for (auto &e : result){cout << e << endl;}
}

sismember
void test2(Redis &redis)
{cout << "sismember" << endl;redis.flushall();redis.sadd("key", {"111", "222", "333"});// 判断元素是否存在bool ret1 = redis.sismember("key", "111");bool ret2 = redis.sismember("key", "444");cout << "ret1: " << ret1 << endl;cout << "ret2: " << ret2 << endl;
}
scard
void test3(Redis &redis)
{cout << "scard" << endl;redis.flushall();redis.sadd("key", {"111", "222", "333"});// 获取集合中元素的个数int ret = redis.scard("key");cout << "ret: " << ret << endl;
}

spop
void test4(Redis &redis)
{cout << "spop" << endl;redis.flushall();redis.sadd("key", {"111", "222", "333"});// 随机删除元素auto result = redis.spop("key");if (result){cout << "result: " << result.value() << endl;}else{cout << "result 无效 !" << endl;}
}

sinter
void test5(Redis &redis)
{cout << "sinter" << endl;redis.flushall();redis.sadd("key1", {"111", "222", "333"});redis.sadd("key2", {"111", "222", "444"});set<string> result;auto it = std::inserter(result, result.end());redis.sinter({"key1", "key2"}, it);for (auto &e : result){cout << e << endl;}
}

sinterstore
void test6(Redis &redis)
{cout << "sinterstore" << endl;redis.flushall();redis.sadd("key1", {"111", "222", "333"});redis.sadd("key2", {"111", "222", "444"});long long len = redis.sinterstore("key3", {"key1", "key2"});cout << "len: " << len << endl;set<string> result;auto it = std::inserter(result, result.end());redis.smembers("key3", it);for (auto &e : result){cout << e << endl;}
}

求并集和求交集基本一致,不多赘述。
hash类型核心操作
hset和hget
void test1(Redis &redis)
{cout << "hset 和 hget" << endl;redis.flushall();// 一次添加一个元素redis.hset("key", "f1", "111");redis.hset("key", make_pair("f2", "222"));// 一次添加多个元素(初始化列表)redis.hset("key", {make_pair("f3", "333"), make_pair("f4", "444")});// 一次添加多个元素(迭代器)vector<pair<string, string>> fileds = {make_pair("f5", "555"), make_pair("f6", "666")};redis.hset("key", fileds.begin(), fileds.end());auto value = redis.hget("key", "f1");if (value){cout << value.value() << endl;}
}

hexists和hdel和hlen
void test2(Redis &redis)
{cout << "hexists hdel hlen" << endl;redis.flushall();redis.hset("key", "f1", "111");redis.hset("key", "f2", "222");redis.hset("key", "f3", "333");bool ret1 = redis.hexists("key", "f1");bool ret2 = redis.hexists("key", "f3");cout << "ret1: " << ret1 << endl;cout << "ret2: " << ret2 << endl;// 一次删除一个filedlong long r = redis.hdel("key", "f1");cout << "删除了" << r << "个" << endl;// 一次删除多个filedr = redis.hdel("key", {"f2", "f3"});cout << "删除了" << r << "个" << endl;long long len = redis.hlen("key");cout << "len: " << len << endl;
}

hmset和hmget
void test4(Redis &redis)
{cout << "hmset hmget" << endl;redis.flushall();// 初始化列表redis.hmset("key", {make_pair("f1", "111"), make_pair("f2", "222")});// 迭代器vector<pair<string, string>> filed = {make_pair("f3", "333"), make_pair("f4", "444")};redis.hmset("key", filed.begin(), filed.end());vector<string> result;auto it = std::back_inserter(result);redis.hmget("key", {"f1", "f2", "f3"}, it);for (auto &e : result)cout << e << endl;
}

hkeys hvals
void test3(Redis &redis)
{cout << "heys 和 hvals" << endl;redis.flushall();redis.hset("key", "f1", "111");redis.hset("key", "f2", "222");redis.hset("key", "f3", "333");vector<string> fileds;auto itfileds = std::back_inserter(fileds);redis.hkeys("key", itfileds);for (auto &e : fileds)cout << e << endl;vector<string> values;auto itvalues = std::back_inserter(values);redis.hvals("key", itvalues);for (auto &e : values)cout << e << endl;
}

zset类型核心操作
zadd和zrange
oid test1(Redis &redis)
{cout << "zadd 和 zrange" << endl;redis.flushall();redis.zadd("key", "吕布", 99);redis.zadd("key", {make_pair("赵云", 98),make_pair("关羽", 97)});vector<pair<string, double>> members;members.push_back(make_pair("张飞", 96));members.push_back(make_pair("马超", 95));redis.zadd("key", members.begin(), members.end());// zrange支持两种风格的查询:// 1.只查询member,不带score// 2.查询member 带 score// 关键在于迭代器指向的是只包含一个string,就只包含memeber// 迭代器指向的是一个 pair,里面包含了 string double 就查询member和scorevector<string> memberResults;auto it = std::back_inserter(memberResults);redis.zrange("key", 0, -1, it);for (auto &m : memberResults)cout << m << endl;vector<pair<string, double>> membersWithScore;auto it2 = std::back_inserter(membersWithScore);redis.zrange("key", 0, -1, it2);for (auto &m : membersWithScore)cout << m.first << " " << m.second << endl;
}

zcar和zrem
void test2(Redis &redis)
{cout << "zcard 和 zrem" << endl;redis.flushall();redis.zadd("key", "music", 99);redis.zadd("key", "english", 69);redis.zadd("key", "math", 98);redis.zrem("key", "english");long long len = redis.zcard("key");cout << "len: " << len << endl;
}

zscore
void test3(Redis &redis)
{cout << "zscore" << endl;redis.flushall();redis.zadd("key", "music", 99);redis.zadd("key", "english", 69);redis.zadd("key", "math", 98);auto score = redis.zscore("key", "music");if (score){cout << "score: " << score.value() << endl;}else{cout << "score 无效!" << endl;}
}

zrank
void test4(Redis &redis)
{cout << "zrank" << endl;redis.flushall();redis.zadd("key", "music", 99);redis.zadd("key", "english", 69);redis.zadd("key", "math", 98);auto rank = redis.zrank("key", "music");if (rank){cout << "rank: " << rank.value() << endl;}else{cout << "rank 无效!" << endl;}
}

相关文章:
C++编写Redis客户端
目录 安装redis-plus-plus库 编辑 编译Credis客户端 redis的通用命令使用 get/set exists del keys expire /ttl type string类型核心操作 set和get set带有超时时间 set带有NX string带有XX mset mget getrange和setrange incr和decr list类型核心操作…...
基于大模型预测的急性横贯性脊髓炎诊疗方案研究报告
目录 一、引言 1.1 研究背景与意义 1.2 研究目的与方法 1.3 国内外研究现状 二、急性横贯性脊髓炎概述 2.1 疾病定义与分类 2.2 病因与发病机制 2.3 临床表现与诊断标准 三、大模型在急性横贯性脊髓炎预测中的应用 3.1 大模型介绍与原理 3.2 数据收集与预处理 3.3 …...
nature genetics | SCENT:单细胞多模态数据揭示组织特异性增强子基因图谱,并可识别致病等位基因
–https://doi.org/10.1038/s41588-024-01682-1 Tissue-specific enhancer–gene maps from multimodal single-cell data identify causal disease alleles 研究团队和单位 Alkes L. Price–Broad Institute of MIT and Harvard Soumya Raychaudhuri–Harvard Medical S…...
【C语言】指针篇
目录 C 语言指针概述指针的声明和初始化声明指针初始化指针指针的操作解引用操作指针算术运算指针的用途动态内存分配作为函数参数指针与数组数组名作为指针通过指针访问数组元素指针算术和数组数组作为函数参数指针数组和数组指针指针数组数组指针函数指针函数指针的定义和声明…...
DeepSeek:如何通过自然语言生成HTML文件与原型图?
在当今快节奏的开发与设计环境中,快速生成HTML文件或原型图是每个开发者与设计师的迫切需求。虽然DeepSeek无法直接生成图片,但它却能够通过自然语言生成流程图、原型图以及交互式页面,甚至可以直接输出HTML代码。本文将详细介绍如何与DeepSe…...
数据结构与算法(两两交换链表中的结点)
原题 24. 两两交换链表中的节点 - 力扣(LeetCode) 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示…...
语言模型作为零样本规划者:提取可执行知识以供具身代理使用
【摘要】 本文研究了预训练的语言模型(LLMs)能否被用来执行在交互式环境中的任务。作者发现,尽管LLMs在生成高阶任务的行动计划时可能无法做到完全精确定义,但通过适当提示,大型预训练语言模型可以分解高阶任务到中阶…...
Baklib智能推荐引擎驱动内容中台升级
智能推荐引擎技术架构 现代智能推荐系统的技术架构以语义分析算法为核心,通过自然语言处理技术解构内容特征,结合动态知识图谱实现信息实体关系的智能映射。该系统采用分层设计架构,基础层依托深度学习模型处理海量非结构化数据,…...
显示器长时间黑屏
现象 电脑启动后,进入登录界面前会随机黑屏,有时候十几秒,有时候几分钟 进入桌面后,长时间不操作电脑黑屏,移动鼠标,点击键盘后尝试点亮屏幕,也会消耗较长时间 尝试 重装系统,或者重新安装显卡,都能够恢复,但过段时间以后又出现黑屏情况 集成显卡,独立显卡都出现过 操作系统…...
顺序表与链表·续
引言 本文承接上文(顺序表与链表-CSDN博客),开始对链表的要点提炼。前文提到顺序表适合需要频繁随机访问且数据量固定的场景,而链表适合需要频繁插入和删除且数据量动态变化的场景。链表的引入弥补了顺序表在动态性和操作效率上的…...
nvidia驱动升级-ubuntu 1804
升级 1.从官网下载*.run驱动文件 2.卸载原始驱动 sudo /usr/bin/nvidia-uninstall sudo apt-get --purge remove nvidia-\* # 可能不需要加-\ sudo apt-get purge nvidia-\* # 可能不需要加-\ sudo apt-get purge libnvidia-\* # 可能不需要…...
【Linux】——初识操作系统
文章目录 冯-诺依曼体系结构操作系统shell 冯-诺依曼体系结构 我们现在所使用的计算机就是冯-诺依曼体系结构。 存储器就是内存。 由下图可知,寄存器最快,为啥不用寄存器呢? 因为越快价格就最贵,冯诺依曼体系结构的诞生…...
本地化deepseek
小白都能拥有自己的人工智能 1、我本地环境 系统:win10 cpu:i7(i7-12700),差不多就行 硬盘:500G+2T,可以不用这么大 显卡:七彩虹2060 12G ,够用了 我的配置最高也只能配上8B了, R1模型版本CPUGPU内存存储8B Intel Core i7/AMD Ryzen 7 及以上 无强制要求,有 4…...
利用可变参数模板,可打印任意参数和参数值。(C++很好的调式函数)
很酷的应用: (1) 如何获取可变参数名 代码例子: #define _test(...) (test_t(#__VA_ARGS__, __VA_ARGS__))template<typename... Args> void test_t(const char* names, Args... args) {std::cout << names <<…...
Yashan DB 体系结构
一、体系结构概况 1.1 线程管理 YashanDB采用多线程架构,线程分为两类: • 工作线程(Worker Threads):每个客户端连接到数据库实例时,会创建一个工作线程。工作线程负责处理客户端的SQL请求,执…...
测试工程师Deepseek实战之如何反向PUA它
问: 你是一名资深测试开发工程师 帮我设计一个提效工具,具有以下功能: 1.页面使用PYQT5设计,用两个输入控件,最好是日期类型的控件,第一个日期控件作为开始日期,第二个日期控件作为结束日期;前后…...
Windows系统中在VSCode上配置CUDA环境
前置步骤 安装符合GPU型号的CUDA Toolkit 配置好 nvcc 环境变量 安装 Visual Studio 参考https://blog.csdn.net/Cony_14/article/details/137510909 VSCode 安装插件 Nsight Visual Studio Code Editionvscode-cudacpp 安装 cmake 并配置好环境变量 注:Windows 端…...
React Native 0.76 升级后 APK 体积增大的原因及优化方案
在将 React Native 从 0.71 升级到 0.76 后,打包体积从 40 多 MB 增加到了 80 MB。经过一系列排查和优化,最终找到了解决方案,并将优化过程整理如下。 1. React Native 0.76 体积增大的可能原因 (1) 新架构默认启用 React Native 0.76 默认启用了 New Architecture(新架…...
pycharm找不到conda可执行文件
conda 24.9.2 在pycharm的右下角就可以切换python解释器了...
定时任务框架
常用定时任务框架 JDK 自带的 ScheduledExecutorService 适用于轻量级定时任务,基于线程池实现。API 简单,适用于小规模任务调度。 Quartz 强大的 Java 任务调度框架,支持 Cron 表达式、分布式集群、持久化等。适用于复杂调度场景࿰…...
FPGA信号调试必备:Quartus中keep、preserve、noprune的正确用法与避坑指南
FPGA信号调试必备:Quartus中keep、preserve、noprune的正确用法与避坑指南 在FPGA开发过程中,信号调试是最令人头疼的环节之一。特别是当你发现仿真时明明存在的关键信号,在综合后却神秘消失时,那种挫败感简直难以言表。作为一名长…...
Python实战:从零构建基于腾讯混元大模型的智能客服系统
1. 为什么选择腾讯混元大模型做智能客服 最近两年大模型技术突飞猛进,但真正要把大模型落地到实际业务中,很多开发者都会遇到三个头疼的问题:第一是模型效果不稳定,第二是API调用复杂,第三是业务逻辑难集成。我在帮几…...
PyTorch张量拼接实战:torch.stack()与torch.cat()的5个典型场景对比
PyTorch张量拼接实战:torch.stack()与torch.cat()的5个典型场景对比 在深度学习项目中,数据维度的操作就像乐高积木的拼装——选错连接方式可能导致模型结构崩塌。作为PyTorch中高频使用的两种拼接操作,torch.stack()和torch.cat()常被混淆使…...
流注放电,COMSOL放电仿真,等离子体仿真,棒板电极,空气流注,流注放电,需要拿去参考
流注放电,COMSOL放电仿真,等离子体仿真,棒板电极,空气流注,流注放电,需要拿去参考。流注放电这玩意儿在高压设备里常见得跟小区门口的便利店似的。实验室里整了个棒板电极结构,空气里突然窜出条…...
ImageGlass架构深度解析:高性能Windows图像查看器的技术实现与优化策略
ImageGlass架构深度解析:高性能Windows图像查看器的技术实现与优化策略 【免费下载链接】ImageGlass 🏞 A lightweight, versatile image viewer 项目地址: https://gitcode.com/gh_mirrors/im/ImageGlass ImageGlass作为一款轻量级、高性能的Win…...
别再瞎找了!AI论文软件2026最新测评与推荐
2026年真正好用的AI论文软件,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…...
BepInEx游戏插件加载器完全指南:从入门到精通Unity游戏扩展工具
BepInEx游戏插件加载器完全指南:从入门到精通Unity游戏扩展工具 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx 如何用BepInEx解锁游戏自定义功能?解决玩家…...
基于智能体(Agent)的自动化图像工作流:Wan2.2-I2V-A14B与任务编排
基于智能体(Agent)的自动化图像工作流:Wan2.2-I2V-A14B与任务编排 1. 引言:当图像生成遇上智能体 想象一下这样的场景:你需要为电商平台制作一组节日主题的广告图,包含特定风格的背景、商品展示和人物互动…...
OneAgent智能体全球发布会圆满落幕:引领金融AI交易新时代
2026年3月25日,聚焦金融AI领域的盛会《OneAgent智能体全球产品发布会》在中国杭州成功落幕。本次发布会吸引了全球金融科技领域的行业专家、投资机构以及技术爱好者的关注,标志着OneAgent在全球AI金融市场的战略布局正式启动。AI原生对冲交易新物种&…...
Outfit字体全攻略:5大核心优势与零基础实战指南
Outfit字体全攻略:5大核心优势与零基础实战指南 【免费下载链接】Outfit-Fonts The most on-brand typeface 项目地址: https://gitcode.com/gh_mirrors/ou/Outfit-Fonts Outfit字体作为一款专业的开源无衬线字体,凭借其完整的9种字重体系和现代设…...

