我作为开发者的旅程
Source: Dev.to
请提供您想要翻译的正文内容,我将按照要求把它翻译成简体中文并保留原有的格式。
第1级:Lunartech
开端:实验心态
大家好,我叫 Jim Amuto,这就是我的故事。我有一点是热爱实验的。无论做什么项目,我都不走常规。我会自问:
- 我在干什么?
- 最终目标是什么?
- 我能多快把它交付给真实用户,或提升我的工作流速度?
这种好奇心转化为对软件开发,尤其是 DevOps 的热情。我很感激现在的职位,因为它让我发现漏洞并需要更快地交付代码。
挑战:AI 初创公司的全栈角色
我记得自己在一个截止日期前背负着一大堆任务。在 AI 初创公司,你常常需要身兼多职——全栈角色而不是狭窄的专业化。这对成为“全能手”很有帮助,随后在成长过程中可以专注于细分领域。
在压力下交付代码
我的大项目是一个 AI 翻译器,必须处理长篇内容——这是老板坚持的需求。我使用的设备成了瓶颈;AI/ML 工作负载计算量大,但没有借口。我一次又一次尝试,直至失败。
我联系了一位拥有更强大机器的朋友。我们通了电话,他克隆了仓库,我告诉他先安装什么。他运行了依赖安装脚本,结果依赖地狱爆发了。他尽力修复,但构建仍因一堆特定版本要求而失败。最后我只能告诉老板,我的电脑不够用。
我研究了云计算,发现了许多 GPU/CPU 租赁选项,但预算不足。我把这个想法提给老板,等待反馈——等待过程异常漫长。
启示:为什么是 Docker?
我为什么要说这些?我突然领悟到:如果我的代码在朋友的环境里都跑不起来,怎么指望它在生产环境正常运行?
时间在滴答。我的 Jira 里有多个工单,两个月过去了,我仍未完成它们。有些任务——比如构建一个简单的进度追踪器——纸面上看很容易,却因为栈不兼容而卡住。
那时我接受了前端可能比后端更难的事实。一个坏掉的进度追踪器是不可接受的;没有用户愿意看到它。完成的压力非常大,我几乎要放弃。
于是我想:也许我的方法错了。 我深入研究,决定尝试 Docker 来打包我的代码。
Docker 是一种工具,它将代码运行所需的一切打包成镜像,能够启动隔离的、短暂的容器实例。
Docker 的赌注
对我而言,Docker 是一次巨大的赌注。实现它花了好几个小时,并伴随许多现实检查:
- 构建时间长。
- 我的 AI 编码代理(即“助理”)不断执行我现在不会尝试的操作,擦除进度并迫使我回退。
我坐下来,与代理一起规划,并提出问题:
- 为什么要重建这个而不是那个?
- 什么时候应该清理缓存和卷?
这些问题为我节省了大量时间,避免了之前因为重新启动容器而不是重新构建来获取新依赖而浪费的时间。
我通过将主机代码目录绑定到服务(后端和前端)实现了 热重载。容器能够即时看到我的更改,无需重新构建——这是一项改变游戏规则的改进,加快了我的工作流,同时保持环境隔离。
持久化挑战
一切顺利,直到我需要让应用在重启后仍能存活。Docker 容器会持续运行命令,所以我不必重新打开终端来查看更改,但前端仍需实时反映这些更改。
我的技术栈包括:
- Next.js – 前端
- FastAPI – 后端
- 众多模型依赖
- Ollama – 本地 LLM 服务
Ollama 实验
为什么选择 Ollama? 我跟随了本地模型能够保护数据、没有速率限制且查询免费 的热潮。
我正在构建一个翻译器。使用外部 API 会产生…(后文未完)
Source: …
teral,缺乏上下文的翻译。我在互联网上搜寻免费模型——过程痛苦,但这就是权衡。
我的老板给我发了一个 TranslateGemma 的链接,这是一个开源的 Google 模型。当时它非常合适,而且已经有预构建的 Ollama 镜像,于是我运行了:
ollama pull translategemma:4b
我的系统无法承受 12B/27B 参数版本的模型,但我已经下定决心。于是我部署了一个 Ollama 容器,几天内一切都正常。
当我测试长时间运行的内容时,Ollama 把容器分配的全部内存都吃光,导致资源耗尽。我改为在本地运行 Ollama。
问题: 如果它消耗如此多的内存,是否适合投入生产?答案暗示成本会很高——这点我一直记在心里。
引入 Redis:瑞士军刀
我的项目有两种登录方式:
- Demo 登录 – 用于快速原型(老板坚持)。
- Auth 登录 – 生产级别的认证。
我使用 local storage 构建了 Demo 登录,速度快但不安全。为了统一这两条流程并为会话数据添加缓存层,我引入了 Redis。它成为我技术栈的“瑞士军刀”,负责:
- 会话存储
- API 调用的限流
- 模型输出的简单键值缓存
Redis 让 Demo 登录和 Auth 登录共享同一个会话存储,使原型向生产环境的过渡更加顺畅。
要点
- 永远不要假设你的开发机器能代表生产环境。
- Docker 隔离依赖 并消除 “在我的机器上可以运行” 的烦恼。
- 通过绑定挂载实现热重载 能显著加快迭代速度。
- 本地 LLM 服务(Ollama) 对数据隐私非常友好,但可能占用大量内存;务必在生产环境进行基准测试。
- Redis 是在全栈 AI 应用中用于会话管理和轻量缓存的被低估的工具。
我从依赖地狱走向生产级设置的经历让我明白,合适的工具——以及敢于尝试的精神——可以把不可能的截止日期转化为可管理的里程碑。
内存中
我把身份验证登录的工作留到以后再做,主要时间都花在演示模式上,这样每当老板要求查看进度时,我都能立刻提供。
然而,将输出存放在本地内存会与应用需要在重启后仍能存活的要求相冲突,因为本地内存无法在生产环境中使用。于是我必须寻找别的方案。
就在这时,我发现了 Redis——一个小巧、轻量的实例,用途广泛——既可以用作缓存,也可以做持久存储。它的速度非常快。起初,我把它当作演示任务的存储,因为当时并没有使用数据库,效果也非常好。
解锁 Redis 的潜力
后来,我意识到自己没有充分利用 Redis 的潜力。我让后端向 Redis 发送 API 来查询任务进度,前端再从后端获取进度——但这失败了。
我尝试使用 WebSockets 来更新进度,结果部分成功。我感到很兴奋,尤其是因为我需要为五个任务显示进度条。
最后一块:Celery
我常常听说 Redis 和 Celery 是相辅相成的。我曾好奇 RabbitMQ 和 Kafka 是什么。原来它们是 消息代理。我的超级英雄 Redis 再次可以兼任消息代理和任务队列——这已经是四种角色了。
Celery,据我理解,是负责以下工作的 worker:
- 从任务队列中卸载任务。
- 处理这些任务。
- 向 broker 发送完成消息,以通知前端获取结果。
实现它花了我好几个小时,但这确实是我做过的最棒的事情之一。它解决了许多问题。我意识到 FastAPI 是问题的一部分——它无法以我需要的方式异步处理大量并发任务。这也是我之前没有得到适当更新的原因。
现在我的所有进度跟踪器都能正常工作,我唯一要做的就是让进度条看起来统一。
未完待续…