SciPy 最优化之最小化

 SciPy 是一个开源的算法库和数学工具包,可以处理最优化、线性代数、积分、插值、拟合、特殊函数、快速傅里叶变换、信号处理、图像处理、常微分方程求解器等。 它依赖于 NumPy, Pandas 也依赖了 NumPy。本文重点是体验它怎么处理最优化的问题。很多情形下通过 SciPy 的  optimize.minimize 方法寻求目标函数最小值的过程得到最优化的输入与输出。比如寻找二次元函数的根,求解线性/动态规则,金融行业的计算出最优投资组合的资产分配等。为什么 SciPy 没有 maximize 方法呢,因为没有必要,想要找到最大化的值,只要把目标函数的值取反,或者是模或绝对值的最小值。看到 minimize 方法名更让人觉得目标函数会有一个收敛值。

虽然 SciPy 对特定的问题有更直白的函数,如求根有 optimize.root, 线性规则 optimize.linprog(现不建议使用),但各种优化基本都可以回归到 minimize 方法调用。minimize 方法的原型是

除了必须的目标函数和初始值,还有更多参数,像常用的约束(contraints) - 满足某些特定条件的最优化, 线程或非线性约束等; 求解方法(method) - Powell, Newton-CG 等

下面用 optimize.minimize 来求解一些问题 阅读全文 >>

跨 CA 签发多个证书的 Nginx mTLS 配置

研究过用同一个 CA 签发的服务端和客户端证书的 Nginx mTLS 配置,本文要试验一番服务端和客户端证书由不同 CA 机构签发的情形。这是常有事,比如与客户间采用 mTLS 加密方式,需要文件交付可能是

  1. 客户端证书由甲方生成,发送客户端私钥和证书(或放在一起的 PKCS#12 格式证书)给乙方
  2. 或由乙方生成客户端私钥或证书,乙方把签发用的 CA 证书发给甲方已配置信任链
  3. 甚至服务端,客户端的证书都由甲方生成的情况下也可能使用不同的 CA 签发

下面来测试不同 CA 签发证书的 Nginx mTLS 配置。

今天升级了 ChatGPT 为 Plus 版本,可以用 ChatGPT 4o, 确实是比较强,输入 "mtls 不同 ca 签发的服务端客户端证书在 nginx 中的配置" 提示符产生的内容几乎可以直接作为博文。但本人必须遵循本博客非 AI 产生的原则,只参考 ChatGTP 的答案,关键是一个要自己亲自动手验证并理解每一项配置的功用。 阅读全文 >>

Wireshark 查看本地浏览器的 HTTPS 加密通信

继续 TLS(或 SSL, HTTPS) 的话题。在我们诊断 HTTP 请求时,为了验证代码中发送了什么样的请求,会用 curl 或 Postman 的辅助,但它们都可能会带上额外的请求头等信息,最为可靠的办法是用网络抓包工具如 Wireshark, 从中看到的 HTTP 文本协议内容才是真正往外发送的内容。可是对于 HTTPS 的协议数据用 Wireshark 抓取到了也没用,因为它是加密了的,作为 TLS 的 Payload, 如果不知道加密算法或密钥是解不开来的。客户端与服务端的密钥交换是采用非对称方式加密的,只通过抓网络包是不可能知道最终确定的密钥是什么,除非像 Zscaler 那样堂而皇之地作为中间人攻击(man in the middle attack)。

但既然是本地浏览器能理解的网页内容,只要浏览器留了口子的话,也是有办法在 WireShark  中显示出抓取到的 HTTPS 的内容,那就是设置环境变量 SSLKEYLOGFILE, 然后启动浏览器(FireFox 或 Chrome), 就会把通信过程中的密钥记录到文件中,WireShark  中引用该 SSLKEY  文件就能显示出确切的 HTTP 请求的内容。 阅读全文 >>

自签发证书配置 HTTPS 单向双向验证

好久以前阅读《HTTP/2 in Action》一书起了个头,又重新放回了书架。近来再次对 HTTPS/TLS 来了劲,自己的博客用的是 Let's Encrypt 签发的证书,这次实践一下自签发证书的过程与配置,并实现单向和双向的认证方式。

如果是配置单向认证的过程需要有以下三个证书

  1. 根(CA) 证书: root.crt
  2. 服务端私钥文件: server.key
  3. 服务端公钥证书: server.crt

证书是含有组织与域名或(CA) 信息以及公钥的文件, root.key 和 root.crt 将被用于签发其他的证书。这里的 crt 证书是 x509 格式的。

浏览器只会信任某些 CA 机构签发的证书,如 DigiCert, GlobalSign, GoDaddy, Amazon Root CA,Let's Encrypt 等。如果是不被信任 CA 签发的证书,我们在浏览器中打开相应的 HTTPS url 就会看到 'Not Secure - Your connection is not private' 的提示,要继续访问需自行承担可能的安全责任。 阅读全文 >>

TLS 与 mTLS 的私钥交换过程

不管是 HTTPS, SSH, SFTP, SCP 等都涉及到 SSL(Secure Sockets Layer) 或 TLS(Transport Layer Security),以及使用非对称加密交互私钥的过程。

很久很久以前傻傻的认为所谓的非对称加密是像 MD5 那样内容加密后,无法从 MD5 码中还原出原始内容,其实那不就加密,是摘要(Digest)。非对称指的是加密与解密使用是不一样的密钥,即用公钥加密,私有解密。

提到 SSL 和 TLS, 顺便了解一下它们的极简史

SSL 由 Netscape 于 90 年代开发,SSL1.0(94 年,未公开), SSL 2.0(95 年发布), SSL 3.0(96 年发布), 后来 IETF 出了个 TLS 1.0 作为 SSL 3.0 的继承者,再就是后面的 TLS 1.1(2006), 1.2(2008), 1.3(2018)。2015 年 TLS 正式的取代了 SSL,从此江湖不再有 SSL 了,而我们习惯说的 SSL 只是在向曾经的 Netscape 致敬,其实指代的就是 TLS。

HTTPS 并非一直使用非对称加密进行数据通信,而只是用 TLS 安全的交换密钥,而后的数据通信使用私钥进行对称加密。如果数据通信都用非对称的方式性能是不允许的,所以只用非对称的方式进行密钥交换。 阅读全文 >>

Ollama - 简化使用本地大语言模型

学习完用 Transformers 和 llama.cpp 使用本地大语言模型后,再继续探索如何使用 Ollama 跑模型。Ollama 让运行和管理大语言模型变得更为简单,它构建在 llama.cpp 之上,并有优化,性能表现同样不俗。下面罗列一下它的特点

  1. 从它的 GitHub 项目 ollama/ollama, Go 语言代码 90.8%, C 代码 3.4%
  2. Ollama 不仅能运行 Llama 模型,还支持 Phi 3, Mistral, Gemma 2 及其他
  3. Ollama 支持 Linux, Windows, 和 macOS, 安装更简单,不用像 llama.cpp 那样需从源码进行编译,并且直接支持 GPU 的
  4. Ollama 有自己的模型仓库,无需申请访问权限,可从 Ollama 拉取所需模型,或 push 自己的模型到 Ollama 仓库pull llama3.2-vision
  5. Ollama 仓库的模型是量化过的,某个模型有大量的 tag 可选择下载,如 llama3.2 的 tags 有 1b, 3b, 3b-instruct-q3_K_M, 1b-instruct-q8_0, 3b-instruct-fp16 等
  6. 如果在 Ollama 上没有的模型,可以到 HuggingFace 上下载,或量化后再传到 Ollama 仓库

其他更多特性我们将在使用当中体验,仍然是在 i9-13900F + 64G 内存 + RTX 4090 + Ubuntu 22.4 台上进行 阅读全文 >>

用 llama.cpp 体验 Meta 的 Llama AI 模型

继续体验 Meta 开源的 Llama 模型,前篇 试用 Llama-3.1-8B-Instruct AI 模型 直接用 Python 的 Tranformers 和 PyTorch 库加载 Llama 模型进行推理。模型训练出来的精度是 float32, 加载时采用的精度是 torch.bfloat16。

注:数据类型 torch.float32, torch.bfloat16, 与 torch.float16 有不同的指数(Exponent),尾数(Fraction)宽度, 它们都有一位是符号位,所以剩下的分别为指数位和尾数位宽度, torch.float32(8, 23), torch.bfloat16(8, 7), torch.float16(5, 10)。

模型依赖于 GPU 的显存,根据经验, 采用 16 位浮点数加载模型的话,推理所需显存大小(以 GB 为单) 是模型参数量(以 10 亿计) 的两倍,如 3B 模型需要约 6G 显存。如果对模型进一步量化,如精度量化到 4 位整数,则所需显存大小降为原来的 1/4 到 1/3, 意味着 3B 模型只要 2 G 显存就能进行推理。所以我们可以把一个 3B 的模型塞到手机里去运行,如果是 1B 的模型 int4 量化后内存占用不到 1G(0.5 ~ 0.67)。

本文体验 llama.cpp 对模型进行推理,在 Hugging Face 的用户设置页面 Local Apps and Hardware, 可看到一些流行的跑模型的应用程序,分别是

  1. 生成文本的: llama.cpp, LM Studio, Jan, Backyard AI, Jellybox, RecurseChat, Msty, Sanctum, LocalAI, vLLM, node-llama-cpp, Ollama, TGI 
  2. 文生图的: Draw Things, DiffusionBee, Invoke, JoyFusion

阅读全文 >>

Oracle, PostgreSQL 字符串排序不一致及调整

有一个使用了不同数据库的应,Oracle 和 PostgreSQL,数据库中的记录完全相同,相同的查询语句(相同的排序,至少从字面上来说是的)取到的记录排序却不同,从而产生了 Bug。 简单演示一下默认排序各自在这两种数据库中的行为, 比如说表中有两条记录,'VFORX' 和 'ibbVA'。此处不创建物理表。

Oracle(Linux)

select * from (
    select 'VFORX' as value from dual
        union
    select 'ibbVA' from dual
) order by 1 desc;

返回的结果是 阅读全文 >>

试用 Llama-3.1-8B-Instruct AI 模型

IT 从业人员累的一个原因是要紧跟时代步伐,甚至是被拽着赶,更别说福报 996. 从早先 CGI, ASP, PHP, 到 Java, .Net, Java 开发是 Spring, Hibernate, 而后云时代 AWS, Azure, 程序一路奔波在掌握工具的使用。而如今言必提的 AI 模型更是时髦,n B 参数, 量化, 微调, ML, LLM, NLP, AGI, RAG, Token, LoRA 等一众词更让坠入云里雾里。

去年以机器学习为名买的(游戏机)一直未被正名,机器配置为 CPU i9-13900F + 内存 64G + 显卡 RTX 4090,从进门之后完全处于游戏状态,花了数百小时对《黑神话》进行了几翻测试。

现在要好好用它的 GPU 来体验一下 Meta 开源的 AI 模型,切换到操作系统 Ubuntu 20.04,  用 transformers 的方式试了下两个模型,分别是

  1. Llama-3.1-8B-Instruct: 显存使用了 16G,它的老版本的模型是 Meta-Llama-3-8B-Instruct(支持中文问话,输出是英文)
  2. Llama-3.2-11B-Vision-Instruct: 显存锋值到了 22.6G(可以分析图片的内容)

都是使用的 torch_dtype=torch.bfloat16, 对于 24 G 显存的 4090 还用不着主内存来帮忙。如果用 float32 则需更多的显存,对于 Llama-3.2-11B-Vision-Instruct 使用 float32, 则要求助于主内存,将看到

Some parameters are on the meta device because they were offloaded to the cpu.

反之,对原始模型降低精度,量化成 8 位或 4 位则更节约显卡,这是后话,这里主要记述使用上面的 Llama-3.1-8B-Instruct 模型的过程以及感受它的强大,可比小瞧了这个 8B 的小家伙。所以在手机上可以离线轻松跑一个 1B 的模型。 阅读全文 >>

ECS Task Definition 中需要的 image:tag 明明在 ECR 中存在却找不到 image

这是近些天遇到的一个问题,因为早先使用 ECS 为求快速验证新的 Docker Image, 一直是用相同的 Tag 覆盖 ECR 中原有的 Docker Image,然后停掉 ECS 中相应的 Task, 新的 Task 起来,拉取最新 Docker Image,这样不用重新部署 Infrastructure, 以最小的改动就能达到偷梁换柱的效果。比如下面的情景:

  1. ECS 任务定义中所用的 Image 是 123456789012.dkr.ecr.us-east-1.amazonaws.com/demo:1.10
  2. 构建新的 Docker Image, 然后再 docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/demo:1.10
  3. 覆盖后,在 ECR 中将有两个 Tag,  刚 push 的是 1.10, 被覆盖的变成 -, 多次覆盖将会产生更多的 -
  4. 停掉 ECS 相应的 Task, 新的 Task 起来,拉取 123456789012.dkr.ecr.us-east-1.amazonaws.com/demo:1.10 代表的新镜像

这种做法在以前是灵验的,每次修改代码,覆盖现有 Tag, 重启 Task 就能快速测试, 不用重新创建 Task Definition 和别的 Infrastructure。

然而最近突然不起作用了,本地不断的修改代码,构建新的镜像,覆盖原有 Tag, 重启 Task, 可是依旧跑的是老代码。怀疑 ECR 中的 Image 有问题,用 docker pull 下来看确实是新代码,就差进到 ECS Task 实例中去找问题。而且即使是重新运行 Terraform 来部署整个 Infrastructure 都无济于事,就是 aws_ecs_service 中指定了 force_new_deployment = true 也没辙,因为只要 Docker Image 的 Tag 没变,  Terraform 就认为是 no change阅读全文 >>