• A Story About Litchi

    Litchi 项目 离开 CSDN AI 组以后,我终于有钱买了一台可以运行 Ollama 的工作机。自此以后的近一年间,我一直在尝试做一个适合自己的 AI 工作环境。 尝试和探索 这个方向我的第一个尝试是一个名为 blue-shell 的 ollama 客户端。这是一个简单的对话 repl,我仅仅是在 console 环境将 markdown 处理为更容易阅读的形式。 第二个尝试是名为 In The Shell 的 java 桌面程序,它支持预定义的 prompt 模板,与 Ollama 对话并将对话历史格式化展现。这已经是我每日必用的工具,各种操作习惯都是我为自己量身定制的,我甚至还给它写了一个语音输入。 但是我还是想再写一个,这是因为我需要一个对markdown编辑和技术写作高度友好的环境。我需要它可以将对话过程与编程和写作紧密的结合在一起,并且自然的将AI的对话过程集成进来。并且,In The Shell 没有保存历史记录的功能。我当时只是写 TENSOR DANCER 的间隙,随时增补一些小功能,满足我即时的需要。这使得 In The Shell 始终处在凑合能用的状态。比如,我要拿出 AI生成的内容时,仅需要双击对应的cell,它就会把内容复到剪贴板,这在我用它翻译文档的时候非常方便,但是如果我让AI给我写单元测试,我没有办法直接选中格子中的一部分内容。 因为 In The Shell 也是我拿来练习 JavaFX... [Read More]
  • GGML PCA

    主成分分析 主成分分析(principal components analysis)是一类非常常见的算法,广泛应用于各种需要信息压缩的场景。虽然《深度学习》一书称之为“简单的机器学习算法”,但是PCA通常可以通过确定的数值算法实现。 概略来说,PCA是找到一个映射算法,将高维空间的样本集合在尽量不损失信息的前提下,映射到更低的维度,从N维空间映射到M维空间,可以表示为一个 $M*N$的矩阵。PCA的目的就是通过分析样本集合,解出这个映射矩阵。 这个求解过程主要有这样几个步骤: 将样本集合表达为$样本数特征数$($AF$)的矩阵 将这个矩阵规范化,使后续步骤中我们可以得到一个对角线为1的协方差矩阵,这需要先得到无偏的标准差: 我们先求得样本集的均值向量,均值向量的每个维度都是所有样本在该特征维度的值的平均 用样本集减去这个均值向量,得到一组中心化的数据$B$ 对这个集合求平方,然后求和,再除以$A-1$得到无偏方差 开方得到无偏标准差(Unbiased standard deviation)即样本标准差(Samples standard deviation) 。 为了避免样本标准差的某个维度为0,导致后续计算出错,可以给它加上一个极小的正数作为补偿。 用B矩阵除以标准差 得到规范化的矩阵X之后,我们计算 $X^TX$ 将得到的矩阵除以$A-1$,得到$F*F$的协方差矩阵 求解协方差矩阵的奇异值矩阵$S$和右奇异值$VT$向量矩阵,按从奇异值大到小,取对应的前M个向量,组成PCA转换矩阵 使用这个矩阵,对样本做矩阵乘法时,得到的就是降维后的结果向量。 实现 我最初做PCA算法的动机,来自于将 4096 维度的 ollama 嵌入向量降维到 2000 维以下——我的目标是256,那么在这个计算过程中,如果假设样本集数量为一万,计算过程中就会涉及好几次千万级的浮点数乘法。为了加速计算过程,使之可以优化到足以放到 PostgreSQL 内部使用,我使用AI框架 ggml 实现了一个 PCA 方法。 GGML 是一个 C 库,它支持 CUDA、MPX 等硬件加速方案,可以快速处理大规模的矩阵算法。 GGML 的tensor类型支持最多4个张量维度,PCA仅涉及矩阵和向量计算,只需要用到最多两位维度。所以这里仅使用GGML TENSOR的前两个维度。 在前述步骤中,基础的矩阵算法如乘法,加法等都有对应的 GGML... [Read More]
  • C/C++ 混合编程

    C/C++ 混合编程 这几天踩了一些坑,做个笔记。 两种语言,两个编译器 十多年前,我曾经是个职业的 CPP 程序员,但是那个时候我用 VC,这是一个高度自动化的 CPP 开发环境,它自动的做了太多的工作,以至于我甚至没有注意到自己的很多问题。 理论上,CPP是C的超集,使用 CPP 编译器可以自动的兼容 C 代码。这也导致了有时候我们其实不太注意自己到底在写C还是CPP。甚至很多构建工具允许我们用 CPP 编译器直接编译C 代码。 这在很多项目中是好的功能,不过我还是决定在 tensor dancer 项目中厘清这个问题,让混合编程的过程放到明面上来。 Meson 在默认情况下,使用 C 编译器编译 .c 文件,用 CPP 编译器编译 .cpp 文件。因为前面的理由,我没有将 c 编译器指定为 c++。 这样就暴露出一个问题,如果我在一个 c 程序中 include 一个CPP 头文件,它会递推到相关的 CPP 代码,这就会引发语法错误或符号找不到这样的错误。应对的方式是,定义一个 .h 文件 ,其中仅包含引用符合C标准的导出定义,例如dancer.h的内容是: [Read More]
  • Tensor Dancer 项目的开发环境配置

    环境和依赖 我准备围绕几个基础的算法工具,编写一系列算法,最终形成一个高阶的算法库,并提供相关的 PostgreSQL 插件。 这个系列,我们主要依赖三个第三方库,线性代数计算库BLAS、LAPACK和GGML。 BLAS 全称 Basic Linear Algebra Subprograms ,底层基于 Fortran 代码,是众多线性代数库的基石。 LAPACK 全称Linear Algebra PACKage,基于 BLAS 库开发,提供了一些矩阵计算算法实现,例如SDV分解。 我的日常工作在一台 M3 芯片的 Apple MacBook 笔记本上完成,因此这里也主要围绕 MacOS 展开,兼顾 Linux。不过我手头没有 Navida 显卡,也没有 CUDA 的运行环境,这方面的东西无法实验。 开发工具 BLAS 和 LAPACK 本身有系统内置的版本,但是实验来看,连编时会找不到头文件,好在它们也有 homebrew 版本,可以直接安装。但是ggml 要程序员自己编译。因此我们还是从开发工具的准备开始。 首先,我们需要安装 Apple 的开发工具集,这个不多介绍,Apple Store上现在可以直接下载xcode……嗯我大概是这个世界上少数在apple store上花过45块钱买xcode的苹果用户了。现在xcode是个免费软件。 说个好笑的,xcode和 xcode-commandline 的库搜索路径不一样,我也是在编译 llama.cpp... [Read More]