JACIN Blog

深度的 AI 应用开发者

专注 AI 应用开发、Python 后端与工程实践,持续记录大模型落地、工具构建与真实项目经验。

182篇已发布
主题索引
查看全部分类
全部文章
182
服务器与部署
12 分钟

部署 Kong

这是一份在 Kubernetes 中部署 Kong 网关的配置笔记,重点放在 hostNetwork 模式下如何同时兼顾网关性能、本机 PostgreSQL 连接和外部访问安全。配置先用 Secret 保存 pg_password,再通过 Job 执行 kong migrations bootstrap 初始化数据库,随后在 Deployment 中设置 KONG_DATABASE、KONG_PG_HOST、KONG_PG_USER、KONG_PG_DATABASE 等环境变量,让 Kong 直接连接宿主机 127.0.0.1:5432 上的 postgres 数据库。网关容器启用 hostNetwork 并配合 ClusterFirstWithHostNet,代理端口只开放 0.0.0.0:8000,而 Admin API 和 Admin GUI 分别限制在 127.0.0.1:8001 与 127.0.0.1:1337,避免管理端口被公网直接访问。由于 Kong UI 默认没有账号体系,文章给出 Nginx 反代方案,通过 auth_basic 和 .htpasswd 为 kong-ui 域名增加访问保护,并将 /manager-api/ 转发到本地 8001,根路径转发到本地 1337,其中 proxy_pass 末尾斜杠被特别标注为关键细节。另一组 Nginx 配置用于 api 域名,将外部 HTTPS 请求转发到本地 8000 的 Kong Proxy,同时保留真实 IP、WebSocket Upgrade、关闭代理缓冲和上传大小设置。适合需要在单机或混合 Docker/K8s 环境中部署 Kong、使用本机数据库并通过 Nginx 统一暴露 UI 与 API 的后端和运维读者参考。

容器与云原生
3 分钟

K8s pod 副本与 Uvicorn Workers

这篇笔记围绕 FastAPI/Uvicorn 服务在 Kubernetes 中的并发扩展方式,区分了 Pod 副本和 Uvicorn Workers 的层级差异:前者是由 K8s 管理的容器级横向扩展,后者是在单容器内由 Python/Uvicorn 管理的进程级纵向扩展。正文强调二者本质上都会启动独立 Python 进程,因此无论是单 Pod 多 Worker,还是多 Pod 单 Worker,都可以绕开 GIL 对单解释器线程并行的限制,实现多核并行。差异主要落在资源隔离、负载均衡和故障边界上:多 Worker 会共享同一个容器的 CPU 与内存限制,由 Uvicorn 主进程分发请求;多 Pod 则由 K8s Service 做网络层负载均衡,并可为每个 Pod 设置独立资源配额。单 Pod 多 Worker 的优势是启动快、内存更省、进程切换开销较小,但在 2 核 CPU 开 4 个 Worker 这类配置下会发生资源争抢,容器 OOM 时所有 Worker 会一起退出。多 Pod 单 Worker 的优势是每个进程拥有更明确的资源保障,单个 Pod 死锁或内存泄漏只损失部分服务能力,并可由 K8s 自动重启,适合追求稳定性、容灾和大规模水平扩展的部署。读者可以据此判断在成本、启动速度、资源利用率与故障隔离之间如何取舍,而不是简单把副本数和 Worker 数视为等价参数。

容器与云原生
1 分钟

关于“容器与云原生”类别

“容器与云原生”类别用于归纳与容器化、云原生体系及相关工程实践有关的内容,并为后续文章归类提供一致的判断依据。该类别的重点不只是收纳零散技术笔记,而是明确它适合承载哪些主题、解决哪些分类场景,以及与站内既有类别之间应如何区分。其准则需要说明使用该类别的理由、覆盖范围、典型话题边界,并判断是否存在与其他分类或子分类合并的可能。读者可以据此理解该分类的定位:它面向需要查找容器、平台化、部署运行和云原生相关知识的技术内容,同时强调分类边界的清晰性,避免相近主题被重复放置或分散管理。

部署 k8s 与配置项目
容器与云原生
14 分钟

部署 k8s 与配置项目

这份笔记围绕在单机环境中用 k3s 搭建 Kubernetes 并部署实际项目展开,先从 /root/k8s/config.yaml 的基础配置入手,记录了设置 token、tls-san、API 端口、kubeconfig 权限、禁用默认 Traefik 以及把数据目录固定到 /root/k8s/data 的安装方式。可视化管理部分使用 Portainer 官方 manifest 部署到 portainer 命名空间,通过 NodePort 暴露 9000 与 9443,并提醒 Portainer 需要 HTTPS 访问、首次初始化超时后可删除 Pod 触发重建。文章随后给出 Nginx 反向代理到本机 30779 端口的配置示例,包括 SSL、WebSocket 升级头、真实 IP 传递、关闭代理缓冲和上传大小限制。项目部署部分强调用 YAML 与环境文件管理应用,而不是依赖 UI 表单,示例中通过 kubectl create secret generic 从 ragapi.env 创建 Secret,再在 Deployment 中用 envFrom 注入环境变量,并配置私有镜像拉取、RollingUpdate 滚动更新和 Service 的 NodePort 暴露。文中还用类比区分 ConfigMap 与 Secret、Deployment 与 Service:前者分别承载非敏感配置和敏感信息,后者分别负责 Pod 生命周期与流量入口,解释了为什么更新 Pod 时 Service 的地址和端口可以保持稳定。最后整理了一组从 Docker 使用习惯迁移到 kubectl 的常用命令,覆盖查看 Pod/Service/Deployment、跟踪日志、查看资源占用、进入容器,以及通过 rollout restart 或删除 Pod 实现重启,适合刚把个人项目迁移到 k3s 的后端开发者和运维学习者参考。

k8s
K8s 简单介绍
容器与云原生
13 分钟

K8s 简单介绍

这是一篇面向 Docker 使用者的 Kubernetes 入门笔记,核心在于把 K8s 理解为负责管理和调度容器的编排系统,而不是 Docker 的替代品:Docker 负责打包和运行,K8s 通过声明式期望状态维持副本、自愈、伸缩和资源抽象。文章用对照表梳理 Namespace、Pod、Deployment、StatefulSet、Service、Ingress、ConfigMap/Secret、PV/PVC 等常见对象,并解释 Pod 是 K8s 的最小调度单位,同一 Pod 内容器共享 IP、localhost 通信和存储卷,因此端口不能冲突。重点说明 Pod 具有一次性生命周期,重建后 IP 会变化,所以需要 Service 作为稳定访问入口,并依赖 DNS 将服务名导向当前可用的后端 Pod。Namespace 用于隔离开发、测试、生产等环境,Ingress 则作为七层反向代理处理域名、路径和 HTTPS,相比 NodePort 更适合对外暴露 Web 服务。存储部分通过 PV 与 PVC 区分真实存储资源和使用申请,说明它如何让 Pod 跨节点漂移时仍能挂载到持久化数据。文章最后区分 Deployment 管理无状态应用、StatefulSet 管理数据库等有状态应用,并提醒滚动更新只保证新请求入口平滑切换,长连接仍会在宽限期结束或旧 Pod 退出时断开,需要应用处理 SIGTERM 和客户端重连。

k8s
使用 attu 创建向量数据库
AI 大模型开发
8 分钟

使用 attu 创建向量数据库

这篇操作笔记围绕在 Attu 中创建 Milvus Collection 展开,把 RAG 知识库建表时容易混在一起的字段设计、索引配置和检索参数拆开说明。正文先以 FloatVector(1024)、VarChar text 和 JSON metadata 为核心字段,解释向量维度必须与 Embedding 模型输出一致,原文文本用于最终回填给 LLM,元数据则服务于按文档、时间等条件做标量过滤。检索部分重点说明 COSINE 余弦相似度适合文本语义搜索,并区分相似度越大越相关、距离或 radius 越小越严格的参数含义,避免在 Milvus 查询时误解阈值方向。索引配置选择 HNSW,并解释 M=16 与 efConstruction=128 分别影响邻居连接数、内存占用、构建速度和查询准确率。文章还对比 Collection 与 Partition 的层级关系:前者类似表并定义统一 Schema,后者是在集合内按业务或时间切分数据,用于缩小搜索范围和控制内存加载。最后补充 Bounded 一致性在写入可见性与吞吐之间折中,以及 Dense、Sparse 和 Hybrid Search 如何把语义检索与关键词权重结合起来提升召回,适合正在搭建 Milvus RAG 数据库的开发者参考。

AI 大模型开发
11 分钟

RAG 架构的认识

这篇笔记把 RAG 从离线索引到在线回答拆成一条完整工程链路,关注的不是概念定义,而是每个环节如何影响召回准确率、响应速度和幻觉控制。数据准备部分强调先做 ETL 清洗,再选择合适的分块策略,并通过元数据记录来源、页码、日期、章节等结构化信息,让后续检索既能依赖向量相似度,也能进行更可靠的过滤。文章特别提醒入库和查询必须使用一致的 Embedding 模型与参数,并用 HNSW 解释向量索引为什么会带来“入库慢、查询快”的取舍。在线阶段则覆盖查询改写、子问题拆解、混合检索和 RRF 融合,说明向量检索适合语义相近内容,而关键词检索更适合型号、人名、缩写等精确信息。排序与生成部分进一步引入 Rerank、阈值过滤和上下文去噪,用更高成本的精排模型提升候选 Chunk 质量,并在低相关度时返回“不知道”以避免强行编造。最后通过 Prompt 约束和引用溯源把答案限制在检索上下文内,适合正在搭建或优化知识库问答系统、希望从“能检索”推进到“可解释、可调优、可追溯”的 AI 应用开发者。

rag
ping 延迟、三次握手、 TLS/SSL 握手 延迟
计算机网络
6 分钟

ping 延迟、三次握手、 TLS/SSL 握手 延迟

这篇笔记围绕网络请求中的 RTT 成本展开,用 ping 返回的 time=44ms 说明它表示从发出到收到回复的完整往返时间,系统不会把结果除以二来显示单程延迟。正文先从广州到北京的光纤传播估算切入,指出即使理想直连往返约 22ms,真实链路还会受到骨干路由跳数、线路绕行以及电光转换等因素影响,因此 44ms 中包含明显的网络损耗。随后文章用时间线拆解 TCP 三次握手,强调真正阻塞客户端继续发送数据的是等待 SYN-ACK 返回的 1 个 RTT,第三次 ACK 不必等服务器收到后才进入下一阶段。对于 HTTP 请求,第三次 ACK 可以和 HTTP 数据捎带发送,因此一次未加密请求可近似理解为 TCP 建连 1 个 RTT 加请求响应 1 个 RTT。对于 HTTPS,请求在 TCP 之后还要完成 TLS/SSL 协商,TLS 1.3 通常再消耗 1 个 RTT,TLS 1.2 可能更多,所以 HTTPS 最快约为 3 个 RTT 加服务器处理时间。文章也说明四次挥手通常不计入一次请求的可感知耗时,因为业务代码拿到 response 时关键路径已经结束,断开连接多在后台完成,适合需要估算接口首包延迟、理解 TCP/TLS 建连成本的后端和网络学习者阅读。

Python 开发
4 分钟

Python 异步编程 async 处理规则

这篇笔记围绕 Python 异步服务中哪些操作该 await、哪些不能指望 async 加速这一边界展开,适合在 FastAPI 等事件循环模型下处理接口、数据库、缓存、对象存储和本地计算任务的开发者参考。文章先强调网络 I/O 本身不消耗 CPU,调用 OpenAI、数据库、Redis、S3 等等待型操作时,应使用 httpx、asyncpg、motor 等异步库并显式 await,让主线程在等待网络返回时继续处理其他请求。随后区分 CPU/内存密集任务:Pandas 处理 Excel、视频转码、哈希计算或超长循环即使写进 async def,也仍会占用主线程并卡住 Event Loop,协程语法不会把单线程计算变成并行计算。针对这类阻塞,文章给出两类“扔到池子里”的处理方式:优先用 asyncio.to_thread 或线程池释放事件循环,尤其适合 Excel 解析、图片处理和许多 Pandas/Numpy 操作,因为其底层 C 实现可能在重计算或 I/O 时释放 GIL。对于纯 Python 重计算,文中建议使用 ProcessPoolExecutor 绕开 GIL,但同时提醒进程创建、序列化传输和无法共享内存都会带来更高成本。最后还提供了一个 AsyncWrapper 示例,用 __getattr__ 将同步厂商 SDK 方法统一包装成 await asyncio.to_thread(...) 的异步调用形式,用较小线程切换开销换取异步服务对旧同步接口的兼容。

Git
4 分钟

自用 VPS 配置 github action self-hosted runner

这份配置记录聚焦在自用 VPS 上部署 GitHub Actions self-hosted runner,并按“中心安装包 + 项目独立运行目录”的方式管理多个仓库。目录设计把 runner 压缩包统一放在 `/root/github-runners/package/actions-runner.tar.gz`,只需从 GitHub releases 下载一次,后续项目如 `go-react-prod`、`new-api` 都从该位置解压,避免重复下载和混用运行文件。首个项目配置时,需要创建专属目录、解压安装包,并在以 root 用户运行的 VPS 上先设置 `RUNNER_ALLOW_RUNASROOT=1`,再执行 `config.sh` 绑定仓库;如果 GitHub 页面生成的 token 过期,则要重新复制新的 token。运行方式上不建议直接执行 `./run.sh`,而是通过 `./svc.sh install root`、`./svc.sh start` 和 `./svc.sh status` 将 runner 安装为 root 用户下的系统服务,保证后台持续运行。新增仓库时重复建目录、复用压缩包、使用对应仓库 URL 和新 token 配置,再安装并启动服务即可。最后在 GitHub Actions workflow 中指定 `runs-on: self-hosted`,任务就能调度到这台 VPS,适合希望用个人服务器承接构建或部署流程的开发者。

AI 大模型开发
7 分钟

CPU 跑 Rerank 太慢?一个脚本开启 INT8 量化,性能大幅度提升!

面向企业级 RAG 系统中在 CPU 服务器部署 HuggingFace text-embeddings-inference Rerank 的场景,内容聚焦默认 FP32 ONNX 模型推理慢、CPU 利用率不高的问题。文章先用 FP32 与 INT8 的数据宽度差异解释瓶颈来源:全精度权重占用更多内存带宽和计算资源,而 Rerank 更关注排序相对结果,适合通过量化降低推理成本。随后结合 AMD EPYC、Intel Xeon 等现代 CPU 的 AVX-512/VNNI 能力,说明 INT8 在 SIMD 并行吞吐和内存占用上的优势,并给出理论上更高并发处理能力的原因。实践部分提供了基于 optimum.onnxruntime 的动态量化脚本,将 bge-reranker-v2-m3 的 FP32 ONNX 文件转换到 quantized 目录,并使用 avx512_vnni 配置面向 CPU 推理优化。脚本中特别处理了 TEI 启动所需的 tokenizer、config 等文件复制,以及将 model_quantized.onnx 重命名为 model.onnx 的兼容性细节。最后只需在 docker-compose.yml 中把 rerank 模型挂载路径切换到 quantized 目录,TEI 镜像无需更换即可加载 INT8 模型,适合需要在现有 CPU 资源上提升 Rerank 吞吐的 RAG 开发和运维人员参考。

AI 大模型开发
7 分钟

tei-rerank 部署重排模型bge-reranker-v2-m3

这份记录聚焦在用 Hugging Face Text Embeddings Inference 的 CPU 镜像部署 BAAI/bge-reranker-v2-m3 重排模型,场景是为检索结果增加一个独立的 rerank 服务,而不是普通 embedding 服务。流程先通过 snapshot_download 将模型完整下载到本地目录,再安装 optimum、onnx、onnxruntime,并用 ORTModelForSequenceClassification.from_pretrained(export=True) 将 PyTorch 模型导出到模型目录下的 onnx 子目录,同时保存 tokenizer。docker-compose 配置的关键点包括使用 ghcr.io/huggingface/text-embeddings-inference:cpu-1.5,挂载本地模型目录到 /data/rerank,开放 38190:80 端口,并通过 --model-id 指向容器内路径,配合 --auto-truncate 和 --dtype float32 启动服务。文章特别强调 shm_size: 1g 的必要性,因为 Docker 默认共享内存只有 64MB,AI 推理程序在并发或大矩阵数据传输时可能因共享内存不足直接 Bus error 崩溃。最后用 /rerank 接口测试“我想买一个手机”与三星、苹果、联想笔记本三段文本的相关性排序,结果显示手机相关文本得分约 0.3,而笔记本得分接近 0.0001。读者可以从中获得一套可复现的 TEI rerank 部署步骤,并理解重排模型更应关注候选项之间的相对差距和排序效果,而不是孤立解读绝对分值。

文章归档
182