Techniques
Adopt
-
1. 1% canary
For many years, we've used the canary release approach to encourage early feedback on new software versions, while reducing risk through incremental rollout to selected users. The 1% canary is a useful technique where we roll out new features to a very small segment (say 1%) of users carefully chosen across various user categories. This enables teams to capture fast user feedback, observe the impact of new releases on performance and stability and respond as necessary. This technique becomes especially crucial when teams are rolling out software updates to mobile applications or a fleet of devices like edge computing devices or software-defined vehicles. With proper observability and early feedback, it gives the opportunity to contain the blast radius in the event of unexpected scenarios in production. While canary releases can be useful to get faster user feedback, we believe starting with a small percentage of users is mandatory to reduce and contain the risk of large-scale feature rollouts.
-
2. Component testing
Automated testing remains a cornerstone of effective software development. For front-end tests we can argue whether the distribution of different test types should be the classic test pyramid or whether it should be a trophy shape. In either case, though, teams should focus on component testing because test suites should be stable and run quickly. Instead, what we're seeing is that teams forgo mastering component testing in favor of end-to-end browser-based testing as well as very narrowly defined unit tests. Unit tests have a tendency to force components to expose what should be purely internal functionality, while browser-based tests are slow, more flaky and harder to debug. Our recommendation is to have a significant amount of component tests and use a library like jsdom to run the component tests in memory. Browser tools like Playwright of course still have a place in end-to-end tests, but they shouldn't be used for component testing.
-
3. Continuous deployment
We believe organizations should adopt continuous deployment practices whenever possible. Continuous deployment is the practice of automatically deploying every change that passes automated tests to production. This practice is a key enabler of fast feedback loops and allows organizations to deliver value to customers more quickly and efficiently. Continuous delivery differs from continuous deployment in that it only requires that code can be deployed at any time; it doesn't require that every change actually is deployed to production. We've hesitated to move continuous deployment into the Adopt ring in the past, as it’s a practice that requires a high level of maturity in other areas of software delivery and is therefore not appropriate for all teams. However, Thoughtworker Valentina Servile’s recent book Continuous Deployment provides a comprehensive guide to implementing the practice in an organization. It offers a roadmap for organizations to follow in order to achieve the level of maturity required to adopt continuous deployment practices.
-
4. Retrieval-augmented generation (RAG)
Retrieval-augmented generation (RAG) is the preferred pattern for our teams to improve the quality of responses generated by a large language model (LLM). We’ve successfully used it in many projects, including the Jugalbandi AI platform. With RAG, information about relevant and trustworthy documents is stored in a database. For a given prompt, the database is queried, relevant documents are retrieved and the prompt augmented with the content of the documents, thus providing richer context to the LLM. This results in higher quality output and greatly reduced hallucinations. The context window — which determines the maximum size of the LLM input — has grown significantly with newer models, but selecting the most relevant documents is still a crucial step. Our experience indicates that a carefully constructed smaller context can yield better results than a broad and large context. Using a large context is also slower and more expensive. We used to rely solely on embeddings stored in a vector database to identify additional context. Now, we're seeing reranking and hybrid search: search tools such as Elasticsearch Relevance Engine as well as approaches like GraphRAG that utilize knowledge graphs created with the help of an LLM. A graph-based approach has worked particularly well in our work on understanding legacy codebases with GenAI.
Trial
-
5. 领域叙事(Domain storytelling)
领域驱动设计(DDD)已成为我们开发软件的基础方法。我们利用它来建模事件、指导软件设计、在微服务周围建立上下文边界,以及阐述复杂的业务需求。DDD 建立了一种普遍语言,非技术利益相关者和软件开发人员都可以用来有效沟通业务。一旦建立,领域模型会不断演变。但许多团队发现很难开始使用 DDD。构建初始领域模型没有一种通用的方法。我们最近遇到的一种前景看好的技术是领域叙事(Domain storytelling)。领域叙事是一种引导技术,业务专家被提示描述业务中的活动。在专家的叙述过程中,主持人使用图示语言捕捉实体和参与者之间的关系和动作。使这些故事可视化的过程有助于澄清和发展参与者之间的共同理解。由于没有单一的最佳方法来开发领域模型,领域叙事提供了一个值得关注的替代方案,或者作为更全面的 DDD 方法,作为我们经常用来开始 DDD 的另一种技术事件风暴的补充。
-
6. 微调嵌入模型
在构建基于 检索增强生成(RAG)的大语言模型应用时,嵌入的质量直接影响到相关文档的检索和响应质量。 微调嵌入模型 可以提高特定任务或领域嵌入的准确性和相关性。我们的团队在开发领域特定的大语言模型应用时进行了嵌入微调,因为精确的信息提取至关重要。然而,当你 急于微调 嵌入模型之前,请仔细权衡这种方式。
-
7. 用LLMs进行函数调用
用 LLMs 进行函数调用 是指通过根据给定查询和相关文档确定并调用适当的函数,将 LLM 与外部函数、API 或工具集成的能力。这将 LLM 的实用性扩展到文本生成之外,使它们能够执行特定任务,如信息检索、代码执行和 API 交互。通过触发外部函数或 API,LLM 可以执行之前超出其独立能力的操作。这一技术使 LLM 能够对其输出进行操作,有效地弥合了思想与行动之间的差距——就像人类使用工具来完成各种任务一样。通过引入函数调用,LLM 为生成过程增加了确定性和真实性,在创造力和逻辑之间达成了平衡。这种方法允许 LLM 连接到内部系统和数据库,甚至通过连接的浏览器进行互联网搜索。像 OpenAI 的 GPT 系列这样的模型支持函数调用,而像 Gorilla 这样的微调模型则专门针对从自然语言指令生成的可执行 API 调用,增强其准确性和一致性。作为一种技术,函数调用适用于检索增强生成 (RAG) 和代理架构。它应被视为一种抽象的使用模式,强调其作为多种实现中基础工具的潜力,而非特定解决方案。
-
8. LLM as a judge
许多我们构建的系统具有两个关键特征:一是能够根据大量数据集中的问题提供答案, 二是几乎不可能追踪到该答案的得出过程。尽管这些系统具有不透明性,我们仍然希望评估并提高其响应质量。通过 大语言模型(LLM)作为评判者 的模式,我们可以使用一个 LLM 来评估另一个系统的响应,这个系统可能本身也是基于 LLM 的。我们看到这种模式用于评估产品目录中搜索结果的相关性,以及判断基于 LLM 的聊天机器人是否在合理地引导用户。当然,评估系统必须经过仔细设置和校准。这种方法能够显著提高效率,从而降低成本。这是一个正在进行的研究领域,其现状可以在这篇文章 中找到总结。
-
9. Passkeys
在 FIDO 联盟的引导下,并由 Apple、Google 和 Microsoft 支持,passkeys正逐步接近主流可用性。使用 passkeys 设置新登录会生成一对密钥:网站接收公钥,而用户保留私钥。登录过程使用非对称加密,用户通过证明自己拥有私钥来进行身份验证,该私钥存储在用户设备上,永远不会发送到网站。访问 passkeys 通过生物识别或 PIN 码保护。passkeys 可以在大科技生态系统中存储和同步,如 Apple 的 iCloud 钥匙串、Google 密码管理器或 Windows Hello。对于跨平台用户, 客户端到身份验证器协议 (CTAP) 使得 passkeys 可以存储在创建密钥或需要登录的设备之外的其他设备上。对 passkeys 最常见的反对意见是它对技术不太熟悉的用户来说是个挑战,而我们认为这种观点实际上是在自我否定。这类用户通常也不善于管理密码,因此他们最能从替代方法中受益。实际上,使用 passkeys 的系统在必要时可以回退到更传统的认证方式。
-
10. 小语言模型(SLMs)
大语言模型(LLMs)在许多应用领域中被证明是有用的,但它们的体积庞大可能会带来一些问题:响应一个提示需要大量计算资源,导致查询速度慢且成本高;这些模型是专有的,体积庞大,必须由第三方托管在云中,这可能对敏感数据造成问题;而且,在大多数情况下,训练一个模型的费用是非常高的。最后一个问题可以通过RAG 模式来解决,该模式绕过了训练和微调基础模型的需求,但成本和隐私问题往往依然存在。为此,我们现在看到对 小语言模型(SLMs) 的兴趣日益增长。与更流行的 LLMs 相比,SLMs 的参数更少、精度较低,通常在 35 亿到 100 亿个参数之间。最近的研究表明,在适当的上下文中,正确设置时,SLMs 可以执行甚至超越 LLMs。它们的体积也使得在 端侧设备上运行成为可能。我们之前提到过谷歌的 Gemini Nano,但随着微软推出其Phi-3系列,该领域正在迅速发展。
-
11. 用于测试和训练模型的合成数据
合成数据集创建涉及生成可以模拟现实世界场景的人工数据,而无需依赖敏感或有限访问的数据源。虽然合成数据在结构化数据集中的应用已得到广泛探索(例如,用于性能测试或隐私安全环境),但我们看到在非结构化数据中重新使用合成数据的趋势。企业通常面临领域特定数据缺乏标注的问题,尤其是在训练或微调大语言模型(LLMs)时。像Bonito和 Microsoft's AgentInstruct 这样的工具可以从原始数据源(如文本文档和代码文件)生成合成的指令调优数据。这有助于加速模型训练,同时降低成本和对手动数据管理的依赖。另一个重要的用例是生成合成数据来解决不平衡或稀疏数据的问题,这在欺诈检测或客户细分等任务中很常见。像SMOTE这样的技术通过人工创建少数类实例来帮助平衡数据集。同样,在金融等行业,生成对抗网络(GANs)用于模拟稀有交易,使模型在检测边缘案例方面更加稳健,从而提高整体性能。
-
12. 利用生成式AI理解遗留代码库
生成式 AI (GenAI) 和大型语言模型 (LLMs) 能帮助开发人员编写和理解代码。尤其是在处理遗留代码库时,这种帮助显得尤为有用,特别是当文档质量差、过时或具有误导性时。自我们上次讨论此话题以来, 利用生成式 AI 理解遗留代码库 的技术和产品得到了进一步的发展,我们已经成功实践了一些方法,尤其是在帮助大型机现代化改造的逆向工程中。我们使用的一个特别有前景的技术是 retrieval-augmented generation (RAG) 方法,其中信息检索基于代码库的知识图谱。知识图谱可以保留代码库的结构化信息,而这往往超出了 LLM 从文本代码中推导的内容。这对于那些不具备自我描述性和一致性的遗留代码库尤其有帮助。另一个提升代码理解的机会是,图谱可以通过现有的或 AI 生成的文档、外部依赖关系、业务领域知识等内容进一步丰富,从而让 AI 的工作更加轻松。
Assess
-
13. AI 团队助手
AI 编码辅助工具通常是在帮助和增强个人贡献者的工作方面被讨论的。然而,软件交付始终是团队合作的过程,因此您应该寻找创建 AI 团队助手 的方法,以帮助形成 10 倍效能的团队,而不是一群 AI 辅助孤立的 10x 工程师。幸运的是,最近工具市场的发展让我们更接近于实现这一目标。 Unblocked 是一个将团队的所有知识来源汇聚在一起,并智能地整合到团队成员工具中的平台。而 Atlassian 的 Rovo 则将 AI 引入最广泛使用的团队协作平台,为团队提供新的搜索类型和访问其文档的方式,并通过 Rovo 代理解锁新的自动化和软件实践支持方式。在我们等待市场在这个领域进一步发展的同时,我们自己也在探索 AI 在知识增强和团队实践支持方面的潜力:我们开源了我们的 Haiven 团队助手,并开始收集与 非编码任务(如需求分析)相关的 AI 辅助 的学习经验。
-
14. 动态少样本提示
动态少样本提示 构建在少样本提示(few-shot prompting)的基础上,通过动态地在提示中包含特定的示例来引导模型的响应。 调整这些示例的数量和相关性可以优化上下文长度和相关性,从而提升模型的效率和性能。像 scikit-llm 这样的库实现了这一技术,它使用最近邻搜索来获取与用户查询最相关的示例。该 技术 可以更好地利用模型有限的上下文窗口,并减少 token 消耗。开源 SQL 生成器 vanna 就是利用动态少样本提示来提高响应的准确性的。
-
15. 用于数据产品的 GraphQL
用于数据产品的 GraphQL 是指使用 GraphQL 作为数据产品的输出端口,供客户端消费产品的技术。我们之前讨论过 GraphQL 作为一种 API 协议,它使开发者能够创建一个统一的 API 层,抽象底层数据的复杂性,为客户端提供一个更加一致且易于管理的接口。将 GraphQL 用于数据产品,使得消费者可以通过 GraphQL 结构无缝地发现数据格式和关系,并使用熟悉的客户端工具进行各种操作。我们的团队正在探索将这一技术应用于特定场景,例如通过 talk-to-data 来探索和发现大数据洞察。在此场景下,GraphQL 查询由大语言模型(LLM)根据用户提示词构建,同时还可以在提示词中引入 GraphQL 结构以便于 LLM 参考以生成准确的查询语句。
-
16. LLM 驱动的自主代理
-
17. 可观察性 2.0
可观察性 2.0 代表了一种从传统的、分散的监控工具向统一方法的转变,它利用结构化的、高基数的事件数据存储在单一数据存储中。该模型捕捉丰富的、带有详细元数据的原始事件,为综合分析提供单一的真实来源。通过以原始形式存储事件,这种方法简化了关联性分析,支持实时和取证分析,并能够深入了解复杂的分布式系统。它允许高分辨率的监控和动态调查能力。可观察性 2.0 优先捕捉高基数和高维度数据,能够进行详细的检查而不会产生性能瓶颈。统一的数据存储减少了复杂性,提供了系统行为的连贯视图,并使可观察性实践与软件开发生命周期更加紧密地结合。
-
18. 本地设备上的大语言模型推理
大语言模型(LLMs)现在可以在网络浏览器和智能手机、笔记本电脑等边缘设备上运行,这使得本地 AI 应用成为可能。这允许在不传输到云端的情况下安全处理敏感数据,为边缘计算、实时图像或视频处理等任务提供极低的延迟,通过本地计算降低成本,并在网络连接不稳定或不可用时依然能够正常工作。这是一个活跃的研究和开发领域。我们之前曾提到过 MLX,这是一个在 Apple Silicon 上高效执行机器学习的开源框架。其他新兴工具包括 Transformers.js 和 Chatty。 Transformers.js 允许你通过 ONNX Runtime 在浏览器中运行 transformers,支持从 PyTorch、TensorFlow 和 JAX 转换的模型。Chatty 利用 WebGPU 在浏览器中本地和私密地运行 LLMs,提供了功能丰富的浏览器内 AI 体验。
-
19. 从LLMs获取结构化输出
从 LLMs 获取结构化输出 是指通过定义的结构模式来约束语言模型的响应。这可以通过指示通用模型以特定格式响应,或者通过微调模型使其“原生”输出例如 JSON 的结构化数据来实现。OpenAI 现在支持结构化输出,允许开发人员提供 JSON Schema、pydantic 或 Zod 对象来约束模型响应。这种能力在函数调用、API 交互和外部集成中尤其有价值,因为这些场景中格式的准确性和一致性至关重要。结构化输出不仅提升了 LLMs 与代码交互的方式,还支持更广泛的使用场景,例如生成用于呈现图表的标记语言。此外,结构化输出已被证明可以减少模型输出中的幻觉现象。
Hold
-
20. 自满于 AI 生成的代码
AI 编程助手,如 GitHub Copilot 和 Tabnine,已经变得非常受欢迎。根据 StackOverflow 2024 年开发者调查 的数据,“72% 的受访者对开发中的 AI 工具持赞成或非常赞成的态度”。尽管我们也看到了这些工具的好处,但我们对它们在中长期对代码质量的影响持谨慎态度,并提醒开发者警惕 自满于 AI 生成的代码 。在经历了几次积极的 AI 辅助体验后,很容易在审查 AI 建议时变得不够谨慎。像 GitClear 的这项研究 显示了代码库快速增长的趋势,我们怀疑这与更大的 Pull Request 有关。还有 GitHub 的这项研究 让我们开始思考,提到的 15% 的 Pull Request 合并率的增加是否真的是好事,还是人们因为过于信任 AI 的结果而更快地合并了更大的请求。我们仍在使用 一年多前提供的基本 “入门建议”,也就是要警惕自动化偏见、沉没成本谬误、锚定偏见和审查疲劳。我们还建议程序员建立一个良好的 在何时何地不使用和信任 AI 心理框架 。
-
21. 企业范围的集成测试环境
创建 企业范围的集成测试环境 是一种常见且浪费的做法,会拖慢整个开发流程。这些环境往往成为难以复制的珍贵资源,成为开发的瓶颈。由于不同环境之间不可避免的数据和配置开销差异,它们还会提供一种虚假的安全感。讽刺的是,常见的对替代方案(如临时环境或多个本地测试环境)的反对意见是成本问题。然而,这种观点未能考虑到企业级集成测试环境所造成的延迟成本,因为开发团队往往需要等待其他团队完成任务或等待依赖系统的新版本部署。相反,团队应使用临时环境,最好是开发团队拥有的一系列测试,这些测试可以快速创建和销毁,使用替身(fake stubs)而不是实际的副本。关于支持这种替代方案的其他技术,可以查看 契约测试、将部署和发布解耦、关注平均恢复时间 和在生产环境测试。
-
22. 禁用大语言模型
与其在工作场所全面 禁用大语言模型 ,组织应专注于提供一套经过批准的 AI 工具。禁令只会促使员工寻找未经批准且可能不安全的替代方案,带来不必要的风险。正如个人计算机早期一样,人们会使用他们认为有效的工具来完成工作,无论是否存在障碍。如果公司不提供安全且获得认可的替代方案,员工可能会使用未经批准的大语言模型,这会带来知识产权、数据泄露和法律责任的风险。相反,提供安全、经企业批准的大语言模型或 AI 工具可以确保安全性和生产力的双赢。一个良好管理的方案能够帮助组织管理数据隐私、安全性、合规性和成本问题,同时赋能员工利用大语言模型的功能。最理想的情况下,对 AI 工具的妥善管理访问可以加速组织学习如何在工作场所中最好地利用 AI。
-
23. 使用AI代替结对编程
当人们谈论编码助手的时候,关于 结对编程 的话题就会不可避免地被提及。我们所处的行业对于它爱恨交织: 有的同行信任它,有的同行讨厌它。现在大家都会对编码助手们提出同样的问题: 一个程序员可以选择与人工智能,而不是另外一个程序员,进行结对编程,从而达到同样的团队产出吗?Github Copilot 甚至自称为“你的 AI 结对程序员”。然而当大家都认为编程助手可以在结对编程方面带来好处时,我们还是不建议完全使用 AI 代替结对编程。把编码助手当做结对编程者忽略了结对编程的一个关键收益: 它可以让团队而不只是个人变得更好。在帮助解决难题,学习新技术,引导新人,或者提高技术任务的效率从而让团队更关注战略性设计等这些方面,使用编程助手确实大有裨益。但在诸如将正在进行的工作的数量控制在低水平,减少团队交接与重复学习,让持续集成成为可能,或者改善集体代码所有权等等这些团队合作相关的层面,它没有带来什么好处。
Unable to find something you expected to see?
Each edition of the Radar features blips reflecting what we came across during the previous six months. We might have covered what you are looking for on a previous Radar already. We sometimes cull things just because there are too many to talk about. A blip might also be missing because the Radar reflects our experience, it is not based on a comprehensive market analysis.
