Zing 论坛

正文

clj-llm:Clojure生态中优雅的LLM交互方案

探索clj-llm如何以函数式编程理念重新定义大语言模型调用,提供纯数据配置、流式响应、工具调用等完整功能,让LLM集成回归Clojure的简洁哲学。

ClojureLLM函数式编程大语言模型Malli工具调用多模态
发布时间 2026/04/10 16:09最近活动 2026/04/10 16:22预计阅读 4 分钟
clj-llm:Clojure生态中优雅的LLM交互方案
1

章节 01

导读 / 主楼:clj-llm:Clojure生态中优雅的LLM交互方案

探索clj-llm如何以函数式编程理念重新定义大语言模型调用,提供纯数据配置、流式响应、工具调用等完整功能,让LLM集成回归Clojure的简洁哲学。

2

章节 02

背景:为什么Clojure需要专属的LLM库

Clojure社区向来推崇简单性、组合性和数据驱动设计。传统的LLM SDK往往带有浓重的面向对象或命令式编程风格,与Clojure的哲学格格不入。开发者不得不编写大量的适配代码,将外部API的响应转换为Clojure数据结构,处理状态管理,以及应对异步操作的复杂性。

clj-llm的诞生正是为了解决这些痛点。它的核心理念可以用一句话概括:"提供者是纯映射,结果是纯映射,所有操作都与标准Clojure无缝组合。"这种设计让LLM调用真正成为Clojure程序中的一等公民。

3

章节 03

架构设计:数据即配置

clj-llm的架构设计体现了Clojure社区对"数据即代码"理念的坚持。每一个LLM提供商都被表示为一个简单的Clojure映射(map),而不是复杂的对象实例。

(def openai (openai/backend {:api-key "sk-..."}))
(def claude (anthropic/backend {:api-key "sk-ant-..."}))
(def ollama (openai/backend {:api-base "http://localhost:11434/v1"
                            :api-key false}))

这种设计的优雅之处在于其可组合性。开发者可以使用标准的Clojure映射操作来构建和修改配置,无需学习新的API或面对复杂的构建器模式。通过简单的assocupdatemerge操作,就能创建出针对不同场景的定制化配置。

4

章节 04

统一的生成接口

无论底层是哪个提供商,clj-llm都提供统一的generate函数。这种一致性大大降低了在多提供商环境中切换的成本。

(:text (llm/generate ai "What is the capital of France?"))
;; => "The capital of France is Paris."

结果同样是一个纯映射,包含:text:usage等标准字段,便于后续处理和监控。

5

章节 05

结构化输出与Malli集成

现代LLM应用常常需要从模型输出中提取结构化数据。clj-llm与Malli(Clojure生态中流行的数据验证库)深度集成,支持通过模式定义来约束和解析模型输出。

(llm/generate ai
  {:schema [:map [:name :string] [:age :int] [:occupation :string]]}
  "Marie Curie was a 66 year old physicist")
;; => {:text "{...}" :structured {:name "Marie Curie" :age 66 :occupation "physicist"} ...}

这种集成不仅确保了数据格式的正确性,还提供了一种声明式的方式来定义期望的输出结构。

6

章节 06

工具调用与Agent循环

clj-llm完整支持函数调用(Tool Calling)功能。工具被定义为带有Malli函数模式的普通Clojure函数,无需额外的注解或元数据。

(defn get-weather
  {:malli/schema [:=> [:cat [:map {:name "get_weather"
                                   :description "Get current weather"}
                              [:city {:description "City name"} :string]]]
                   :string]}
  [{:keys [city]}]
  (str "Sunny, 22°C in " city))

库提供了两种调用模式:单次调用的generate(模型决定是否使用工具)和持续循环的run-agent(自动处理多轮工具调用直到任务完成)。这种分层设计让开发者可以根据应用场景灵活选择。

7

章节 07

流式响应与异步支持

对于需要实时反馈的场景,clj-llm支持通过回调函数处理流式输出。:on-text选项允许在接收每个文本块时执行自定义操作,同时仍然返回完整的结果映射。

对于推理模型(如o1、o3系列),:on-reasoning回调可以捕获模型的内部思考过程,为调试和优化提供宝贵的洞察。

8

章节 08

多模态内容处理

clj-llm内置了对图像和PDF文档的支持。通过content/imagecontent/pdf函数,开发者可以轻松地将多媒体内容纳入LLM对话。

(:text (llm/generate ai ["What's in this image?" (content/image "photo.jpg")]))
(:text (llm/generate ai ["Describe this" (content/image "https://example.com/chart.png")]))
(:text (llm/generate claude-ai ["Summarize" (content/pdf "invoice.pdf")]))

库还提供了图像处理选项,如调整尺寸、格式转换和质量控制,帮助开发者优化成本和性能。