LLM4Rec介绍

1. 概念与缘起 LLM4Rec = Large Language Models for Recommendation 这是学术界和工业界对“将大语言模型(LLM)用于推荐系统”这一研究方向的统称,而不是某一个具体模型。 (A Survey on Large Language Models for Recommendation) 之所以受到关注:LLM 在文本理解、知识压缩、生成与推理方面表现突出,可为推荐系统带来「更好的语义表征 + 外部知识 + 类人生成能力」。 2. 两大技术范式 范式 思路 代表工作 典型应用场景 DLLM4Rec(Discriminative) 把 LLM 当作编码器/特征提取器;输出仍是打分/排序。 CLLM4Rec (WWW 2024) – 用软硬 Prompt 将用户/商品 ID 引入 GPT-2,融合 ID-Embedding 与文本表示。 (Collaborative Large Language Model for Recommender Systems) CTR 预估、序列推荐、冷启动 GLLM4Rec(Generative) 将推荐表述为自然语言生成任务,直接“写出”用户可能喜欢的物品或理由。 GPT-4Rec、RecMind、Chat-Rec 等 对话式推荐、长文本摘要推荐、理由生成 这一分类最早由 2023 年的系统综述明确提出。 (A Survey on Large Language Models for Recommendation)...

April 29, 2025 · 2 min · Egbert Ke

Linux TUN与TAP介绍

什么是Tun/Tap 在计算机网络中,TUN与TAP是操作系统内核中的虚拟网络设备。不同于普通靠硬件网路板卡实现的设备,这些虚拟的网络设备全部用软件实现,并向运行于操作系统上的软件提供与硬件的网络设备完全相同的功能。 TAP等同于一个以太网设备,它操作第二层数据包如以太网数据帧。TUN模拟了网络层设备,操作第三层数据包比如IP数据封包。 操作系统通过TUN/TAP设备向绑定该设备的用户空间的程序发送数据,反之,用户空间的程序也可以像操作硬件网络设备那样,通过TUN/TAP设备发送数据。在后种情况下,TUN/TAP设备向操作系统的网络栈投递(或“注入”)数据包,从而模拟从外部接受数据的过程。 应用程序如何操作Tun/Tap Linux Tun/Tap驱动程序为应用程序提供了两种交互方式:虚拟网络接口和字符设备/dev/net/tun。写入字符设备/dev/net/tun的数据会发送到虚拟网络接口中;发送到虚拟网络接口中的数据也会出现在该字符设备上。 应用程序可以通过标准的Socket API向Tun/Tap接口发送IP数据包,就好像对一个真实的网卡进行操作一样。除了应用程序以外,操作系统也会根据TCP/IP协议栈的处理向Tun/Tap接口发送IP数据包或者以太网数据包,例如ARP或者ICMP数据包。Tun/Tap驱动程序会将Tun/Tap接口收到的数据包原样写入到/dev/net/tun字符设备上,处理Tun/Tap数据的应用程序如VPN程序可以从该设备上读取到数据包,以进行相应处理。 应用程序也可以通过/dev/net/tun字符设备写入数据包,这种情况下该字符设备上写入的数据包会被发送到Tun/Tap虚拟接口上,进入操作系统的TCP/IP协议栈进行相应处理,就像从物理网卡进入操作系统的数据一样。 Tun虚拟设备和物理网卡的区别是Tun虚拟设备是IP层设备,从/dev/net/tun字符设备上读取的是IP数据包,写入的也只能是IP数据包,因此不能进行二层操作,如发送ARP请求和以太网广播。与之相对的是,Tap虚拟设备是以太网设备,处理的是二层以太网数据帧,从/dev/net/tun字符设备上读取的是以太网数据帧,写入的也只能是以太网数据帧。从这点来看,Tap虚拟设备和真实的物理网卡的能力更接近。 下图描述了Tap/Tun的工作原理: 使用Tun/Tap创建点对点隧道 通过应用程序从/dev/net/tun字符设备中读取或者写入数据看上去并没有太大用处,但通过将Tun/Tap结合物理网络设备使用,我们可以创建一个点对点的隧道。如下图所示,左边主机上应用程序发送到Tun虚拟设备上的IP数据包被VPN程序通过字符设备接收,然后再通过一个TCP或者UDP隧道发送到右端的VPN服务器上,VPN服务器将隧道负载中的原始IP数据包写入字符设备,这些IP包就会出现在右侧的Tun虚拟设备上,最后通过操作系统协议栈和socket接口发送到右侧的应用程序上。 上图中的隧道也可以采用Tap虚拟设备实现。使用Tap的话,隧道的负载将是以太数据帧而不是IP数据包,而且还会传递ARP等广播数据包。 使用Tun/Tap隧道绕过防火墙 结合路由规则和IPTables规则,可以将VPN服务器端的主机作为连接外部网络的网关,以绕过防火墙对客户端的一些外部网络访问限制。如下图所示,防火墙规则允许客户端访问主机IP2,而禁止访问其他Internet上的节点。通过采用Tun隧道,从防火墙角度只能看到被封装后的数据包,因此防火墙认为客户端只是在访问IP2,会对数据进行放行。而VPN服务端在解包得到真实的访问目的后,会通过路由规则和IPTables规则将请求转发到真正的访问目的地上,然后再将真实目的地的响应IP数据包封装进隧道后原路返回给客户端,从而达到绕过防火墙限制的目的。 使用Tap隧道桥接两个远程站点 如下图所示,可以使用tap建立二层隧道将两个远程站点桥接起来,组成一个局域网。对于两边站点中的主机来说,访问对方站点的主机和本地站点的主机的方式没有区别,都处于一个局域网192.168.0.0/24中。 VPN主机上有两个物理网卡,其中Eth0用于和对方站点的VPN主机进行通信,建立隧道。Eth1在通过网线连接到以太网交换机的同时也被则加入了Linux Bridge,这相当于用一条网线将Linux Bridge上的一个端口(Eth1)连接到了本地站点的以太网交换机上,Eth1上收到的所有数据包都会被发送到Linux Bridge上,Linux Bridge发给Eth1的数据包也会被发送到以太网交换机上。Linux Bridge上还有一个Tap虚拟网卡,用于VPN程序接收从Linux Bridge上收到的数据包。 假设192.168.0.5发出了一个对192.168.0.3的ARP请求,该ARP请求在网络中经过的路径如下: 192.168.0.5发出ARP请求,询问192.168.0.3的MAC地址。 该ARP请求将被发送到以太网交换机上。 以太网交换机对该请求进行泛洪,发送到其包括Eth1在内的所有端口上。 由于Eth1被加入了VPN主机上的Linux Bridge,因此Linux Bridge收到该ARP请求。 Linux Bridge对该ARP请求进行泛洪,发送到连到其上面的Tap虚拟网卡上。 VPN程序通过/dev/net/tun字符设备读取到该ARP请求,然后封装到TCP/UDP包中,发送到对端站点的VPN主机。 对端站点的VPN程序通过监听TCP/UDP端口接收到封装的ARP请求,将ARP请求通过/dev/net/tun字符设备写入到Tap设备中。 Linux Bridge泛洪,将ARP请求发送往Eth1,由于Eth1连接到了以太网交换机上,以太网交换机接收到了该ARP请求。 以太网交换机进行泛洪,将ARP请求发送给了包括192.168.0.3的所有主机。 192.168.0.3收到了APR请求,判断iP地址和自己相同,对此请求进行响应。 同理,ARP响应包也可以按照该路径返回到图左边包括192.168.0.5在内的站点中。 从站点主机的角度来看,上面图中两个VPN主机之间的远程连接可以看作一条虚拟的网线,这条网线将两个Linux Bridge连接起来。这两个Linux Bridge和两个以太网交换机一起将左右两个站点的主机连接在一起,形成了一个局域网。 参考资料 Universal TUN/TAP device driver Universal TUN/TAP device driver Frequently Asked Question Tun/Tap interface tutorial A simplistic, simple-minded, naive tunnelling program using tun/tap interfaces and TCP

November 27, 2024 · 1 min · Egbert Ke

Gost源码阅读笔记 Tunnel UDP Over TCP

Make Tunnel func makeTunnel() (c net.Conn, err error) { if UseWebsocket || !UseHttp { c, err = connect(Saddr) } else { addr := Saddr if proxyURL != nil { addr = proxyURL.Host } c, err = dial(addr) } if err != nil { return } if UseWebsocket { ws, resp, err := websocket.NewClient(c, &url.URL{Host: Saddr}, nil, 8192, 8192) if err != nil { c.Close() return nil, err } resp.Body.Close() c = NewWSConn(ws) } else if UseHttp { httpcli := NewHttpClientConn(c) if err = httpcli....

November 25, 2024 · 2 min · Egbert Ke

TLS加密过程及代码示例

TLS加密过程 客户端问候:客户端向服务器发送一个问候消息,包含支持的TLS版本、加密算法和其他信息。 服务器问候:服务器选择TLS版本和加密算法,并发送其数字证书给客户端。数字证书包含服务器的公钥。 验证证书:客户端验证服务器的数字证书是否由受信任的证书颁发机构签署。如果验证失败,连接将被终止。 生成会话密钥:客户端生成一个随机数,并使用服务器的公钥对其进行加密,然后发送给服务器。服务器使用其私钥解密,得到这个随机数。这个随机数将用于生成会话密钥。 会话密钥生成:客户端和服务器使用这个随机数生成对称加密的会话密钥。 加密通信:使用会话密钥加密和解密后续的通信数据。 这个过程确保了数据在传输过程中是加密的,并且只有通信的双方能够解密数据。 Golang tls库使用示例 TLS 服务器 package main import ( "crypto/tls" "fmt" "log" "net/http" ) func helloHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, TLS!") } func main() { http.HandleFunc("/", helloHandler) // 加载证书和密钥 cert, err := tls.LoadX509KeyPair("server.crt", "server.key") if err != nil { log.Fatalf("server: loadkeys: %s", err) } // 配置TLS tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}} // 创建TLS监听器 server := &http.Server{ Addr: ":8443", TLSConfig: tlsConfig, } log.Println("Starting server on https://localhost:8443") err = server....

November 25, 2024 · 1 min · Egbert Ke

使用C语言实现协程

本文译自 PuTTY 的作者 Simon Tatham 的文章 Coroutines in C,作者在文中介绍了一种基于 达夫设备 的思想实现的协程。注意,斜体部分为翻译过程中的补充。考虑到译者的英文水平有限,部分语句的翻译与原文略有出入,强烈建议读者结合原文观看。 介绍 编写大型程序总是一件困难的事。其中常见的一个问题就是:如果你有一段代码正在生产数据,同时有另一段代码正在消费这些数据,它俩之间谁应该是 caller(调用者)谁应该是 callee(被调用者)呢_(译者注,即如何维护它俩之间的调用关系)_? 这里有一段非常简单的 decompressor 代码,以及一段非常简单的 parser 代码: // decompressor while (1) { c = getchar(); if (c == EOF) break; if (c == 0xFF) { len = getchar(); c = getchar(); while (len--) { emit(c); } } else { emit(c); } } emit(EOF); // parser while (1) { c = getchar(); if (c == EOF) break; if (isalpha(c)) { do { add_to_token(c); c = getchar(); } while (isalpha(c)); got_token(WORD); } add_to_token(c); got_token(PUNCT); } 两段代码都非常简单易懂。前者通过调用 emit() 每次产生一个字符;后者通过调用 getchar() 每次消费一个字符。只需要调用 emit() 和 getchar() 就可以传送数据了,所以 decompressor 产生的数据可以很轻易地传送到 parser 中。...

November 21, 2024 · 5 min · Egbert Ke

Android学习路线

1、【主要】官网的体系化课程:https://developer.android.com/courses 2、书,如:《第一行代码》 参考: https://www.reddit.com/r/androiddev/comments/s8krkx/where_to_learn_android_app_development/ https://proandroiddev.com/if-i-were-to-start-my-android-career-in-2022-here-is-how-i-would-do-it-c7f149dc8cbf https://jinxuliang.com/course/AndroidKotlin/1_AndroidIntro/PPT.pdf

October 15, 2024 · 1 min · Egbert Ke

如何成就一番事业

https://mp.weixin.qq.com/s/G9re_-Cyx2-U4f35csS0Yw

June 3, 2024 · 1 min · Egbert Ke

Nginx Proxy Manager 单机多Docker Compose 反向代理配置

问题描述 单机下部署多个docker-compose, 并用nginx proxy manager 反代其他docker compose的流量,出现连不上其他docker compose 下的container的问题 尝试过的解决方式 1、地址用docker0的地址,端口用其他container暴露出来的端口,不行 2、换机器,不行 3、换docker、docker-compose 版本,不行 最终的解决方式 手动将多个docker compose加入到同一个docker network. 具体参考: 1、https://nginxproxymanager.com/advanced-config 2、https://stackoverflow.com/questions/38088279/communication-between-multiple-docker-compose-projects 3、https://github.com/NginxProxyManager/nginx-proxy-manager/issues/555 05.20 更新 最终还是要解决容器内无法访问宿主机IP的问题,非常诡异: 1、容器内可以ping通其他容器的hostname, 端口也是通的 2、容器内可以ping通宿主机ip (eth0) 3、但是容器无法连上宿主机的端口 4、公网可以正常访问宿主机的服务(端口是通的) 排查一圈发现是防火墙的原因,Ubuntu 22.04 TLS, 记得要把防火墙关了!(ufw disable) 艹! 参考过的几个有用文章: 1、https://juejin.cn/post/7180619106407120933 2、https://gist.github.com/bruno-brant/e119da3713a657036ff7e3446d98176a 一般软件打的镜像都比较轻量,用的alpine版的linux比较多,进容器后用apk update && apk add… 装一些常用软件,方便排查问题。

May 21, 2024 · 1 min · Egbert Ke

MySQL InnoDB 行记录格式(ROW_FORMAT)

MySQL InnoDB 行记录格式(ROW_FORMAT) 一、行记录格式的分类和介绍 在早期的InnoDB版本中,由于文件格式只有一种,因此不需要为此文件格式命名。随着InnoDB引擎的发展,开发出了不兼容早期版本的新文件格式,用于支持新的功能。为了在升级和降级情况下帮助管理系统的兼容性,以及运行不同的MySQL版本,InnoDB开始使用命名的文件格式。 1. Antelope: 先前未命名的,原始的InnoDB文件格式。它支持两种行格式:COMPACT 和 REDUNDANT。MySQL5.6的默认文件格式。可以与早期的版本保持最大的兼容性。不支持 Barracuda 文件格式。 2. Barracuda: 新的文件格式。它支持InnoDB的所有行格式,包括新的行格式:COMPRESSED 和 DYNAMIC。与这两个新的行格式相关的功能包括:InnoDB表的压缩,长列数据的页外存储和索引建前缀最大长度为3072字节。 在 msyql 5.7.9 及以后版本,默认行格式由innodb_default_row_format变量决定,它的默认值是DYNAMIC,也可以在 create table 的时候指定ROW_FORMAT=DYNAMIC。用户可以通过命令 SHOW TABLE STATUS LIKE'table_name' 来查看当前表使用的行格式,其中 row_format 列表示当前所使用的行记录结构类型。 PS:如果要修改现有表的行模式为compressed或dynamic,必须先将文件格式设置成Barracuda:set global innodb_file_format=Barracuda;,再用ALTER TABLE tablename ROW_FORMAT=COMPRESSED;去修改才能生效。 mysql> show variables like "innodb_file_format"; +--------------------+-----------+ | Variable_name | Value | +--------------------+-----------+ | innodb_file_format | Barracuda | +--------------------+-----------+ 1 row in set (0.00 sec) mysql> show table status like "test%"\G *************************** 1. row *************************** Name: test Engine: MyISAM Version: 10 Row_format: Dynamic Rows: 4 Avg_row_length: 20 Data_length: 80 Max_data_length: 281474976710655 Index_length: 1024 Data_free: 0 Auto_increment: NULL Create_time: 2018-08-07 13:07:59 Update_time: 2018-08-07 13:08:01 Check_time: NULL Collation: utf8_general_ci Checksum: NULL Create_options: row_format=DYNAMIC Comment: 二、InnoDB行存储...

April 30, 2024 · 1 min · Egbert Ke

Understanding Character Sets and Collations in MySQL

If you have ever worked with MySQL, you inevitably came across character sets and collations. In this blog post, we will try to give you a more in-depth look at what those two are and how you should use them. What Are Character Sets and Collations? Simply put, character sets in MySQL are sets of symbols and encodings – collations are sets of rules for comparing characters in a character set....

April 30, 2024 · 5 min · Egbert Ke