Ohhnews

分类导航

$ cd ..
foojay原文

BoxLang AI 3.2.0 发布:图像生成、网络搜索、流畅音频、代理注册与MCP可观测性

#boxlang ai#图像生成#网络搜索#代理注册#mcp可观测性

[LOADING...]

BoxLang AI 3.2.0 正式发布,这是一个里程碑版本。我们带来了五大核心功能:图像生成、网页搜索、流畅的音频构建器 API、集中式代理注册表,以及深度 MCP 可观测性,同时还包括一系列分析改进和一项关键错误修复。让我们一探究竟。:tada:

:framed_picture: 图像生成 —— aiImage()

您现在可以直接在 BoxLang 中使用任意支持文生图的提供商生成图像。aiImage() BIF 遵循与 bx-ai 其他功能相同的流畅链式调用哲学,并能通过表达性方法对结果进行处理。

$ java
// 链式生成并保存
aiImage( "日落时分的未来城市景观" )
    .saveToFile( "/images/cityscape.png" )

// 通过参数和提供商实现完全控制
response = aiImage(
    "山水湖泊的水彩画",
    { n: 2, size: "1024x1024", quality: "hd" },
    { provider: "openai" }
)

// 直接嵌入到 HTML 输出中
dataURI = response.toDataURI()

返回的 AiImageResponse 对象提供了您所需的一切:hasImages()getCount()getFirstURL()getFirstBase64()saveToFile()saveAllToDirectory()toDataURI()getMimeType()toStruct()

开箱即用的提供商:

提供商模型环境变量
OpenAIgpt-image-1(默认)、DALL-E 模型OPENAI_API_KEY
Geminiimagen-3.0-generate-008GEMINI_API_KEY
Grok / xAIgrok-2-imageGROK_API_KEY
OpenRouterFLUX Schnell(默认)及其他众多模型OPENROUTER_API_KEY

在模块启动时,generateImage@bxai 代理工具会自动注册到全局工具注册表中,因此您的代理无需任何手动配置即可生成图像:

$ java
agent = aiAgent( tools: [ "generateImage@bxai" ] )

:books: 图像生成文档

:mag: 网页搜索 —— aiWebSearch() & aiWebSearchAsync()

BoxLang AI 现在内置了统一的网页搜索系统,提供提供商抽象和标准化结果。每个提供商都返回相同的字段(title、url、snippet、publishedDate、domain、score、thumbnail、language),因此您无需改动代码即可切换提供商。

$ java
// 同步搜索
results = aiWebSearch( "最新的 BoxLang AI 更新", { provider: "brave", maxResults: 8 } )

// 异步 —— 返回 BoxFuture
future = aiWebSearchAsync( "BoxLang 发布亮点", { provider: "tavily" } )
results = future.get()

支持的提供商:

提供商说明
httpURL 获取与分析 —— 无需 API 密钥
brave注重隐私;支持国家/语言过滤
googleGoogle 自定义搜索
tavily面向检索,非常适合 AI 代理
exa语义搜索与神经网络搜索模式

webSearch@bxai 工具已全局自动注册,任何代理均可立即进行网络搜索:

$ java
agent = aiAgent(
    name: "ResearchAgent",
    tools: [ "webSearch@bxai" ]
)

response = agent.run( "查找并总结最近 BoxLang AI 的发布亮点" )

:books: 网页搜索文档

:microphone: 音频 BIF 的流畅构建器 API

aiSpeak()aiTranscribe()aiTranslate() 现在支持完整的流畅构建器 API。无参数调用任意函数即可返回请求对象,然后链式配置后执行。传统的位置参数语法仍然完全可用 —— 流畅构建器仅为附加特性。

aiSpeak()

$ java
// 传统语法 —— 仍然有效
audio = aiSpeak( "Hello!", { voice: "nova" }, { provider: "openai" } )

// 流畅构建器 —— 更具表现力且自文档化
audio = aiSpeak()
    .of( "Hello, world!" )
    .voice( "nova" )
    .provider( "openai" )
    .asMP3()
    .speak()

// 性别快捷键
audio = aiSpeak()
    .of( "Welcome aboard!" )
    .male()
    .speed( 1.2 )
    .speak()

// 格式快捷键
audio = aiSpeak()
    .of( "System alert." )
    .asWav()
    .outputFile( "/audio/alert.wav" )
    .speak()

关键构建器方法:.of().voice().male() / .female().speed().instructions().outputFile().asMP3() / .asWav() / .asFlac() / .asOpus() / .asPCM().provider().speak()

aiTranscribe()

$ java
// 从文件
text = aiTranscribe()
    .file( "/audio/meeting.mp3" )
    .withWordTimestamps()
    .asVerboseJSON()
    .transcribe()

// 从 URL
text = aiTranscribe()
    .url( "https://example.com/audio.mp3" )
    .language( "es" )
    .transcribe()

// 直接将音频翻译成英语
english = aiTranscribe()
    .file( "/audio/french.mp3" )
    .translate()

关键构建器方法:.file().url().data().language().withWordTimestamps().withSegmentTimestamps().diarize().asJSON() / .asText() / .asVerboseJSON() / .asSRT() / .asVTT().transcribe().translate()

aiTranslate()

$ java
english = aiTranslate()
    .file( "/audio/german.mp3" )
    .asText()
    .translate()

:books: 音频文档

:robot: 代理注册表 —— aiAgentRegistry()

3.2.0 引入了 AIAgentRegistry —— 一个全局单例,为您 BoxLang 应用程序中运行的所有代理提供集中式的可发现性、可观测性和生命周期管理。

$ java
// 在创建时自动注册
agent = aiAgent(
    name: "support-agent",
    description: "客户支持代理",
    register: true,
    module: "my-app"
)

// 或手动注册
aiAgentRegistry().register( agent, "my-app" )

// 发现正在运行的内容
agents = aiAgentRegistry().listAgents()
info   = aiAgentRegistry().getAgentInfo( "support-agent@my-app" )

// 解析字符串键和实际实例的混合数组
resolved = aiAgentRegistry().resolveAgents( [
    "support-agent@my-app",
    anotherAgentInstance
] )

// 清理
aiAgentRegistry().unregister( "support-agent@my-app" )
aiAgentRegistry().unregisterByModule( "my-app" )

模块作者:一流的代理和工具注册 :dart:

这对 BoxLang 生态系统来说意义重大。开发 BoxLang 模块的开发者现在可以打包那些在模块加载时自动全局注册的代理和工具 —— 应用开发者无需任何手动配置。

  • 使用 register: true 和模块命名空间定义 aiAgent() 实例
  • 定义工具,通过 aiToolRegistry().scan( new MyTools(), "my-module" ) 扫描它们,然后它们会以 toolName@my-module 的形式全局出现
  • 应用开发者可以在安装模块后,从应用的任何部分按名称使用您的代理和工具

这使得 bx-ai 成为一个真正的平台,用于构建可组合、可发现的 AI 生态系统 —— 将模块发布到 ForgeBox,您的代理和工具即可立即使用。:rocket:

两个新的拦截点在注册表变更时触发:onAIAgentRegistryRegisteronAIAgentRegistryUnregister

:pause_button: MCP 服务器暂停/恢复

MCPServer 现在支持在不拆除配置或丢失已注册工具的情况下暂停和恢复。非常适合维护窗口、优雅降级或受控发布。

$ java
server = MCPServer( "my-tools", "提供自定义工具" )
    .registerTool( myTool )

server.pause()

if ( server.isPaused() ) {
    println( "服务器已暂停 —— 拒绝所有非 ping 请求" )
}

server.resume()
  • pause() —— 触发 onMCPServerPause;所有非 ping 请求收到错误代码 -32005
  • resume() —— 触发 onMCPServerResume;恢复正常处理
  • getSummary() 现在包含 paused 布尔值

:bar_chart: MCP 服务器和客户端可观测性

服务器分析

MCP 服务器监控在 3.2.0 中进行了重大改造:

  • 使用所有统计操作中的命名锁实现线程安全计数器
  • 安全失败跟踪 —— 认证失败、API 密钥拒绝、请求体大小违规都有专用计数器
  • 按工具错误跟踪 —— byTool[name].errors,带有 errors.byTool 汇总
  • 活跃并发请求计数器 —— activeRequests 实时递增/递减
  • 每分钟请求速率 —— 在 getSummary() 中公开
  • X-Request-ID 关联 —— 请求 ID 在响应头和事件负载中回显
  • 暂停请求统计 —— 当服务器暂停时,被拒绝的请求被跟踪
  • 现在 onMCPError 会在 METHOD_NOT_FOUND 时触发

客户端统计 —— MCPClient

MCPClient 获得了完整的内部使用和性能跟踪:

$ java
client = MCP( "http://localhost:3000" )

tools  = client.listTools()
result = client.callTool( "search", { query: "BoxLang" } )

// 检查正在发生什么
stats   = client.getStats()   // 按操作、按工具、按 URI 细分
summary = client.getSummary() // totalCalls, successRate, avgResponseTime

// 需要时重置
client.resetStats()

三个新的拦截点覆盖了整个客户端生命周期:onMCPClientRequestonMCPClientResponseonMCPClientError

:wrench: 类型感知工具参数支持

bx-ai 中的工具模式现在直接从可调用参数元数据生成,因此 LLM 最终能够为每个参数接收准确的 JSON Schema 类型,而不仅仅是一堆字符串。ClosureTool.getArgumentsSchema() 自然地映射 BoxLang 类型 —— numeric、integer、float 和 double 变为 "number";boolean 变为 "boolean";array 变为 "array" 并带有 "items": {};struct 变为 "object" —— 这意味着 LLM 可以为非字符串参数发送原生的 JSON 值,并且工具的行为完全按照它们签名的声明。在输出方面,BaseTool.invoke() 继续一致地序列化结果以保证提供商兼容性,通过 toString() 转换简单值,通过 JSON 序列化转换复杂值,从而在双向保持工具契约的清晰。:dart:

$ java
// 带有数字和布尔参数的工具
// LLM 发送 { "quantity": 3, "applyDiscount": true } —— 无需类型转换
calculateTotal = aiTool(
    name: "calculateTotal",
    description: "计算订单总额,可选折扣",
    tool: ( numeric price, numeric quantity, boolean applyDiscount = false ) -> {
        total = price * quantity
        if ( applyDiscount ) total *= 0.9
        return { summary: "订单总额已计算", total: total }
    }
)

// 带有数组参数的工具
// LLM 发送 { "tags": ["boxlang", "ai", "tools"] } —— 原生数组
tagContent = aiTool(
    name: "tagContent",
    description: "为内容项应用标签列表",
    tool: ( string contentId, array tags ) -> {
        // tags 以真实的 BoxLang 数组到达
        return {
            summary : "标签已应用到 #contentId#",
            applied : tags.len(),
            tags    : tags
        }
    }
)

// 带有结构参数的工具
// LLM 发送 { "filter": { "status": "active", "minAge": 18 } } —— 原生结构
queryUsers = aiTool(
    name: "queryUsers",
    description: "按过滤条件查询用户",
    tool: ( struct filter, numeric limit = 10 ) -> {
        results = userService.query( filter, limit )
        return {
            summary : "找到 #results.len()# 个用户",
            count   : results.len(),
            data    : results
        }
    }
)

agent = aiAgent(
    tools: [ calculateTotal, tagContent, queryUsers ]
)

:bug: 错误修复 —— ClosureTool.doInvoke() JSON 结构处理

发送 JSON 字段为真实对象或数组(而非预序列化的 JSON 字符串)的 MCP 客户端,不再导致 "Can't cast Struct to a string" 错误。doInvoke() 现在会检查声明参数,并对任何声明类型为 string 的非简单值调用 jsonSerialize()。静默、自动、无需代码更改。

:package: 模块配置

新的图像设置块

$ cat
{
  "modules": {
    "bxai": {
      "settings": {
        "image": {
          "defaultProvider": "openai",
          "defaultApiKey": "",
          "defaultModel": "gpt-image-1",
          "defaultSize": "1024x1024",
          "defaultQuality": "standard",
          "defaultStyle": "vivid",
          "defaultInstructions": ""
        }
      }
    }
  }
}

新的拦截点

3.2.0 将 bx-ai 的总拦截点提升至 50 个,新增 10 个事件:

事件触发时机
beforeAIImageGeneration图像生成请求之前
afterAIImageGeneration图像生成响应之后
onAIImageRequest图像请求对象创建
onAIImageResponse图像响应接收
onAIAgentRegistryRegister代理注册
onAIAgentRegistryUnregister代理注销
onMCPServerPauseMCP 服务器暂停
onMCPServerResumeMCP 服务器恢复
onMCPClientRequestMCP 客户端 HTTP 请求
onMCPClientResponseMCP 客户端 HTTP 响应
onMCPClientErrorMCP 客户端 HTTP 错误

:rocket: 立即升级

# CommandBox
box install bx-ai

# OS
install-bx-module bx-ai

:books: 完整文档:ai.ortusbooks.com
:speech_balloon: 社区:community.ortussolutions.com
:star: GitHub:github.com/ortus-boxlang/bx-ai

BoxLang AI 3.2.0 是一个平台级发布:图像生成、网页搜索、流畅音频、全局代理与工具注册表,以及深度可观测性,全部集成在一起。我们迫不及待想看到您构建的作品。:tada:

该文章最初发表于 foojayBoxLang AI 3.2.0 — Image Generation, Web Search, Fluent Audio, Agent Registry & MCP Observability