Liking cljdoc? Tell your friends :D

im.ttalk.agent.model.content

中立多模态内容部件(content parts)—— provider 无关的图片 / 文件 / 音频表示。

消息的 :content 有两种合法形态:

  1. 字符串(既有形态,纯文本,最常用)
  2. 部件向量(多模态):
{:role :user
 :content [(content/text-part "这张图里有什么?")
           (content/image-part "https://example.com/cat.png")]}

部件形状(对齐 Vercel AI SDK 的 LanguageModelPrompt 部件模型—— 图片 / 音频 / PDF 不各立一类,统一是 :file + :media-type, wire 层按 media type 的顶层类别分派;这样新格式不需要新部件类型):

{:type :text :text "..."}
{:type :file :media-type "image/png"       :data "<base64>"}   ; 内联数据
{:type :file :media-type "image/png"       :url  "https://..."} ; 远端 URL
{:type :file :media-type "application/pdf" :data "<base64>" :filename "a.pdf"}

约束与边界:

  • 中立层只搬运,不解释:能不能发(Anthropic 不收音频、OpenAI 的 PDF 只收内联) 由各 provider 的 wire 转换器判定,不支持时抛规范错误(:validation-error, 不可重试),不静默丢内容。
  • 与厂商原生块共存::content 向量里 :type 为字符串的元素(如 Anthropic 的 {:type "text"} / {:type "document"})被视为厂商原生块, wire 层原样透传——既有那条逃生通道不受影响,两者可混用。
  • 部件里的二进制一律以 base64 字符串落地:对话历史要经 EDN / JSON 往返 (SQLite store),字节数组过不去。

(require '[im.ttalk.agent.model.content :as content] '[im.ttalk.agent.model.message :as msg])

(msg/user [(content/text-part "描述这张图") (content/image-part (io/file "cat.png"))])

中立多模态内容部件(content parts)—— provider 无关的图片 / 文件 / 音频表示。

消息的 `:content` 有两种合法形态:

1. **字符串**(既有形态,纯文本,最常用)
2. **部件向量**(多模态):

```clojure
{:role :user
 :content [(content/text-part "这张图里有什么?")
           (content/image-part "https://example.com/cat.png")]}
```

部件形状(对齐 Vercel AI SDK 的 `LanguageModelPrompt` 部件模型——
图片 / 音频 / PDF **不各立一类**,统一是 `:file` + `:media-type`,
wire 层按 media type 的顶层类别分派;这样新格式不需要新部件类型):

```clojure
{:type :text :text "..."}
{:type :file :media-type "image/png"       :data "<base64>"}   ; 内联数据
{:type :file :media-type "image/png"       :url  "https://..."} ; 远端 URL
{:type :file :media-type "application/pdf" :data "<base64>" :filename "a.pdf"}
```

约束与边界:

- **中立层只搬运,不解释**:能不能发(Anthropic 不收音频、OpenAI 的 PDF 只收内联)
  由各 provider 的 wire 转换器判定,不支持时抛规范错误(`:validation-error`,
  不可重试),**不静默丢内容**。
- **与厂商原生块共存**:`:content` 向量里 `:type` 为**字符串**的元素(如
  Anthropic 的 `{:type "text"}` / `{:type "document"}`)被视为厂商原生块,
  wire 层**原样透传**——既有那条逃生通道不受影响,两者可混用。
- 部件里的二进制一律以 **base64 字符串**落地:对话历史要经 EDN / JSON 往返
  (SQLite store),字节数组过不去。

(require '[im.ttalk.agent.model.content :as content]
         '[im.ttalk.agent.model.message :as msg])

(msg/user [(content/text-part "描述这张图")
           (content/image-part (io/file "cat.png"))])
raw docstring

audio-partclj

(audio-part source)
(audio-part source opts)

音频部件。内联数据须给 :media-type(如 "audio/wav" / "audio/mpeg")。

音频部件。内联数据须给 :media-type(如 "audio/wav" / "audio/mpeg")。
sourceraw docstring

audio?clj

(audio? part)
source

bytes->base64clj

(bytes->base64 data)

字节数组 → base64 字符串

字节数组 → base64 字符串
sourceraw docstring

data-uriclj

(data-uri {:keys [media-type data]})

内联部件 → "data:<media-type>;base64,<data>"(无 :data 返回 nil)

内联部件 → "data:<media-type>;base64,<data>"(无 :data 返回 nil)
sourceraw docstring

file-partclj

(file-part source)
(file-part source {:keys [media-type filename]})

文件部件(图片 / 音频 / PDF 等统一走这里)。

参数:

  • source: URL 字符串 / data URI / base64 字符串 / byte[] / java.io.File / java.net.URL / java.net.URI
  • opts: {:media-type "image/png" :filename "a.png"} 内联数据(非 URL、非 File)必须给 :media-type——猜不出来的东西 不猜,否则错的 media type 会让服务端报一个与真实原因无关的错。

返回:{:type :file :media-type ... (:data | :url) ... (:filename)}

文件部件(图片 / 音频 / PDF 等统一走这里)。

参数:
- source: URL 字符串 / data URI / base64 字符串 / byte[] / java.io.File /
          java.net.URL / java.net.URI
- opts:   {:media-type "image/png" :filename "a.png"}
          内联数据(非 URL、非 File)**必须**给 :media-type——猜不出来的东西
          不猜,否则错的 media type 会让服务端报一个与真实原因无关的错。

返回:{:type :file :media-type ... (:data | :url) ... (:filename)}
sourceraw docstring

file-part?clj

(file-part? x)
source

image-partclj

(image-part source)
(image-part source opts)

图片部件。(image-part "https://.../a.png") / (image-part (io/file "a.png")) / (image-part base64 {:media-type "image/png"})。

URL 来源猜不出 media type 时缺省 "image/*"——OpenAI 的 image_url 用不到它, Anthropic 的 url source 也不带 media_type,留个顶层类别足够 wire 层分派。

图片部件。`(image-part "https://.../a.png")` / `(image-part (io/file "a.png"))` /
`(image-part base64 {:media-type "image/png"})`。

URL 来源猜不出 media type 时缺省 "image/*"——OpenAI 的 image_url 用不到它,
Anthropic 的 url source 也不带 media_type,留个顶层类别足够 wire 层分派。
sourceraw docstring

image?clj

(image? part)
source

media-typeclj

(media-type part)
source

part?clj

(part? x)

是否为中立内容部件(:type 为 keyword)。 :type 为字符串的一律不是——那是厂商原生块,wire 层原样透传。

是否为**中立**内容部件(:type 为 keyword)。
`:type` 为字符串的一律不是——那是厂商原生块,wire 层原样透传。
sourceraw docstring

parts?clj

(parts? content)

content 是否为多模态部件向量(含至少一个中立部件)。 纯字符串 content 与纯厂商原生块向量都返回 false。

content 是否为多模态部件向量(含至少一个中立部件)。
纯字符串 content 与纯厂商原生块向量都返回 false。
sourceraw docstring

text-ofclj

(text-of content)

取 content 的纯文本(字符串原样;部件向量取其中文本部件拼接; 厂商原生块认 :text 键)。多模态消息要做关键词匹配 / 日志时用它。

取 content 的纯文本(字符串原样;部件向量取其中文本部件拼接;
厂商原生块认 :text 键)。多模态消息要做关键词匹配 / 日志时用它。
sourceraw docstring

text-partclj

(text-part text)

文本部件 {:type :text :text "..."}

文本部件 {:type :text :text "..."}
sourceraw docstring

text-part?clj

(text-part? x)
source

top-level-media-typeclj

(top-level-media-type part)

media type 的顶层类别:"image/png" → "image"(无则 nil)

media type 的顶层类别:"image/png" → "image"(无则 nil)
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