Liking cljdoc? Tell your friends :D

im.ttalk.agent.chat-client

ChatClient 核心 - 中央编排器

ChatClient 构建使用声明式 map:

(build-chat-client {:chat-model my-chat-model :tools [#'get-weather #'get-time] :filters [memory-filter logging-filter] :settings {:max-tool-iterations 10}})

Tool 定义(支持 tags): (deftool get-weather "获取天气" [[city :string "城市"]] {:tags [:weather :read-only]} (str city ": 25°C"))

Invoke API - 调用函数/LLM: (invoke-tool chat-client :get-weather {:city "北京"} context) (invoke-chat chat-client messages opts) (invoke chat-client messages opts) (invoke chat-client messages {:tags [:weather]}) ;; 只用带 :weather tag 的工具 (invoke chat-client messages {:exclude-tags [:dangerous]}) ;; 排除危险工具

Query API - 查询 ChatClient 状态: (tool-registry/tool-schemas chat-client) ;; 所有 tool schemas (list-functions chat-client) ;; 所有函数名 (find-function chat-client :get-weather)

ChatModel 格式: ChatModel 是一个 map,定义 LLM 调用接口: {:chat-fn (fn [messages opts] -> {:text "..." :tool-calls [...]})}

返回值格式: invoke-tool: {:value v (:writes {k v})} ;; context 只读,写意图经 :writes invoke-chat: {:response r :context ctx} invoke: {:response r :context ctx :tool-calls-made [...]}

ChatClient 核心 - 中央编排器

ChatClient 构建使用声明式 map:

  (build-chat-client {:chat-model my-chat-model
                      :tools [#'get-weather #'get-time]
                      :filters [memory-filter logging-filter]
                      :settings {:max-tool-iterations 10}})

Tool 定义(支持 tags):
  (deftool get-weather
    "获取天气"
    [[city :string "城市"]]
    {:tags [:weather :read-only]}
    (str city ": 25°C"))

Invoke API - 调用函数/LLM:
  (invoke-tool chat-client :get-weather {:city "北京"} context)
  (invoke-chat chat-client messages opts)
  (invoke chat-client messages opts)
  (invoke chat-client messages {:tags [:weather]})           ;; 只用带 :weather tag 的工具
  (invoke chat-client messages {:exclude-tags [:dangerous]}) ;; 排除危险工具

Query API - 查询 ChatClient 状态:
  (tool-registry/tool-schemas chat-client)     ;; 所有 tool schemas
  (list-functions chat-client)                 ;; 所有函数名
  (find-function chat-client :get-weather)

ChatModel 格式:
ChatModel 是一个 map,定义 LLM 调用接口:
  {:chat-fn (fn [messages opts] -> {:text "..." :tool-calls [...]})}

返回值格式:
  invoke-tool: {:value v (:writes {k v})}   ;; context 只读,写意图经 :writes
  invoke-chat: {:response r :context ctx}
  invoke:      {:response r :context ctx :tool-calls-made [...]}
raw docstring

build-chat-clientclj

(build-chat-client {:keys [chat-model tools tool-vars filters settings
                           state-slots eligibility-fn tool-manager]
                    :or {tools [] filters [] settings {}}})

构建 ChatClient 实例

参数 opts map:

  • :chat-model ChatModel map(必需)
  • :tools tool var 向量(如 [#'get-weather]),也可混入内联工具 map (含 :handler,由 delegate-tool 等动态构建)。工具名必须 唯一——var 与内联共用一个命名空间,重名装配期即抛
  • :filters filter 向量(如 [memory-filter logging-filter]),注册顺序即执行顺序
  • :settings 额外设置(可选),如 {:max-tool-iterations 10}
  • :state-slots 状态槽声明(可选){k {:init v0 :reduce (fn [old new] merged)}}—— 工具批次 :writes 的合并语义(未声明的槽默认 last-writer)
  • :eligibility-fn 循环续跑判据(可选)(fn [response context] -> boolean)—— 响应带 tool-call 时是否真的执行并续跑;返回 false 则 该响应按最终答案收尾(工具不执行)。缺省恒真,即「有 tool-call 就跑」。对标 Spring AI ToolExecutionEligibilityChecker

返回: ChatClient record

示例: (build-chat-client {:chat-model cm :tools [#'get-weather #'get-time] :filters [memory-filter retry-filter] :settings {:max-tool-iterations 10}})

构建 ChatClient 实例

参数 opts map:
- :chat-model  ChatModel map(必需)
- :tools       tool var 向量(如 [#'get-weather]),也可混入内联工具 map
               (含 :handler,由 delegate-tool 等动态构建)。**工具名必须
               唯一**——var 与内联共用一个命名空间,重名装配期即抛
- :filters     filter 向量(如 [memory-filter logging-filter]),注册顺序即执行顺序
- :settings    额外设置(可选),如 {:max-tool-iterations 10}
- :state-slots 状态槽声明(可选){k {:init v0 :reduce (fn [old new] merged)}}——
               工具批次 :writes 的合并语义(未声明的槽默认 last-writer)
- :eligibility-fn 循环续跑判据(可选)(fn [response context] -> boolean)——
               响应带 tool-call 时是否**真的**执行并续跑;返回 false 则
               该响应按最终答案收尾(工具不执行)。缺省恒真,即「有
               tool-call 就跑」。对标 Spring AI ToolExecutionEligibilityChecker

返回:
ChatClient record

示例:
(build-chat-client {:chat-model cm
                    :tools [#'get-weather #'get-time]
                    :filters [memory-filter retry-filter]
                    :settings {:max-tool-iterations 10}})
sourceraw docstring

invoke-chatclj

(invoke-chat chat-client messages opts)

发送 Chat Completion 请求(经 chat filter 洋葱链,不含工具调用循环)

组装 ChatRequest → 预编译的 :chat 链包裹 → terminal 调 LLM。 memory 等「读历史 / 改写请求 / 加工响应」能力以 chat filter 形态注入; filter 可 around(短路 / 重试 / 计时),详见 chat-client.filter。

参数:

  • chat-client: ChatClient 实例(需已配置 chat-model)
  • messages: 消息列表(本轮 delta)
  • opts: {:tools 工具 schema 列表 / :tool-choice / :system-prompt / :context} 除 :context 外的键全部进 ChatRequest 的 :options(provider 私有 参数照样穿得过去——不筛白名单)

返回: ChatClientResponse{:response ChatResponse :context updated-ctx}

发送 Chat Completion 请求(经 chat filter 洋葱链,不含工具调用循环)

组装 ChatRequest → 预编译的 :chat 链包裹 → terminal 调 LLM。
memory 等「读历史 / 改写请求 / 加工响应」能力以 chat filter 形态注入;
filter 可 around(短路 / 重试 / 计时),详见 chat-client.filter。

参数:
- chat-client:   ChatClient 实例(需已配置 chat-model)
- messages: 消息列表(本轮 delta)
- opts:     {:tools 工具 schema 列表 / :tool-choice / :system-prompt / :context}
            除 :context 外的键全部进 ChatRequest 的 :options(provider 私有
            参数照样穿得过去——不筛白名单)

返回:
`ChatClientResponse`{:response ChatResponse :context updated-ctx}
sourceraw docstring

invoke-chat-asyncclj

(invoke-chat-async chat-client messages opts)

invoke-chat 的异步版:返回 deferred<ChatClientResponse>,调用线程不阻塞。

ChatModel 实现 IAsyncChatModel 时走原生异步;否则虚拟线程兜底 (cm/call-async*)——任何 provider 都可用。

⚠️ 走这条路时 :chat filter 的 (chain req) 真的返回 deferred,响应侧 必须用 flt/fmap / flt/fbind((let [r (chain req)] …) 不报错,但拿到的是 future——静默错)。

`invoke-chat` 的异步版:返回 **deferred<`ChatClientResponse`>**,调用线程不阻塞。

ChatModel 实现 `IAsyncChatModel` 时走原生异步;否则虚拟线程兜底
(`cm/call-async*`)——任何 provider 都可用。

⚠️ 走这条路时 `:chat` filter 的 `(chain req)` **真的返回 deferred**,响应侧
必须用 `flt/fmap` / `flt/fbind`(`(let [r (chain req)] …)` 不报错,但拿到的是
future——静默错)。
sourceraw docstring

invoke-chat-streamclj

(invoke-chat-stream chat-client messages opts)

invoke-chat 的流式版本:terminal 调 chat-model 的 :stream-fn,token 经 on-token 实时回调。

与 invoke-chat 共用同一条 chat filter 洋葱链(memory 等照常生效);on-token 经 request 透传到 terminal。:stream-fn 在流结束时返回最终归一化响应,故 memory-filter 落库的是 完整 assistant 消息——与同步路径历史不分叉。

filter 的 :token-xform(transducer)在 terminal 内组合成出站 token 变换链: provider 原始 token → xform 链(注册顺序,靠前者先见原始 token)→ on-token。 正常完流调 completion arity(缓冲 flush),stream-fn 抛异常则不 flush; 下游 reduced(如 take)后不再喂 token,completion 照常。只变换交付流, 不改最终 :response。设计见 docs/token-stream-filter-design.md。

参数:

  • opts: 同 invoke-chat,外加 :on-token (fn [token-data] ...)

返回: ChatClientResponse{:response ChatResponse :context ctx}

invoke-chat 的流式版本:terminal 调 chat-model 的 :stream-fn,token 经 on-token 实时回调。

与 invoke-chat 共用同一条 chat filter 洋葱链(memory 等照常生效);on-token 经 request
透传到 terminal。:stream-fn 在流结束时返回最终归一化响应,故 memory-filter 落库的是
**完整** assistant 消息——与同步路径历史不分叉。

filter 的 :token-xform(transducer)在 terminal 内组合成出站 token 变换链:
provider 原始 token → xform 链(注册顺序,靠前者先见原始 token)→ on-token。
正常完流调 completion arity(缓冲 flush),stream-fn 抛异常则不 flush;
下游 reduced(如 take)后不再喂 token,completion 照常。**只变换交付流,
不改最终 :response**。设计见 docs/token-stream-filter-design.md。

参数:
- opts: 同 invoke-chat,外加 :on-token (fn [token-data] ...)

返回: `ChatClientResponse`{:response ChatResponse :context ctx}
sourceraw docstring

invoke-chat-stream-asyncclj

(invoke-chat-stream-async chat-client messages opts)

invoke-chat-stream 的异步版:返回 deferred<ChatClientResponse>。

:token-xform 的组装位置与同步版完全一致(chat 链之后、terminal 之内), flush 挪进 fmap 的续延——正常完流才 flush,异常(error channel)不 flush, 与同步版的 try 语义逐字相同。

⚠️ on-token 的调用线程不保证(见 cm/stream-call-async*)。

`invoke-chat-stream` 的异步版:返回 deferred<`ChatClientResponse`>。

`:token-xform` 的组装位置与同步版完全一致(chat 链之后、terminal 之内),
flush 挪进 fmap 的续延——**正常完流才 flush,异常(error channel)不 flush**,
与同步版的 try 语义逐字相同。

⚠️ on-token 的调用线程不保证(见 `cm/stream-call-async*`)。
sourceraw docstring

invoke-toolclj

(invoke-tool chat-client fn-name args context)

调用 ChatClient 中注册的函数(经 tool filter 洋葱链)

组装 ToolRequest {:function :args :context} → 预编译的 :tool 链包裹 → terminal 执行函数。filter 可改写 args、短路(不调 chain,如审批拒绝/熔断/ 限流/安全策略)、around(超时计时)。:context 是请求侧只读字段:filter 与 工具都不改写它;工具的写意图经返回值 :writes 声明,由批次屏障处的 reducer 折叠(见 context/apply-writes)。

参数:

  • chat-client: ChatClient 实例
  • fn-name: 函数名(关键字或字符串)
  • args: 参数 map
  • context: Context 对象(只读快照)

返回: {:value result (:writes {k v}) (:error {:class :message})}

错误: 抛 ex-info(仅函数未找到;执行异常被 terminal 捕获为错误结果字符串 + :error 分类信息 {:class :semantic|:transient|:environment},供屏障路由; 失败调用无 :writes——写意图不生效)

调用 ChatClient 中注册的函数(经 tool filter 洋葱链)

组装 ToolRequest {:function :args :context} → 预编译的 :tool 链包裹
→ terminal 执行函数。filter 可改写 args、短路(不调 chain,如审批拒绝/熔断/
限流/安全策略)、around(超时计时)。**:context 是请求侧只读字段**:filter 与
工具都不改写它;工具的写意图经返回值 :writes 声明,由批次屏障处的
reducer 折叠(见 context/apply-writes)。

参数:
- chat-client:  ChatClient 实例
- fn-name: 函数名(关键字或字符串)
- args:    参数 map
- context: Context 对象(只读快照)

返回:
{:value result (:writes {k v}) (:error {:class :message})}

错误:
抛 ex-info(仅函数未找到;执行异常被 terminal 捕获为错误结果字符串 +
:error 分类信息 {:class :semantic|:transient|:environment},供屏障路由;
失败调用无 :writes——写意图不生效)
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close