Spring AI 1.x 系列【52】可观测集成 SkyWalking

1. 概述

本文档从零开始,在一个 Spring Boot + Spring AI 项目中实现完整的可观测性体系------将 Tracing(链路追踪)、Metrics(指标)、Logging(日志)通过 OpenTelemetry 协议统一导出到 Apache SkyWalking。

实现路径:Micrometer Observation → OTel Bridge → OTLP gRPC Exporter → SkyWalking OAP。

1.1 上报流程

SkyWalking 支持的多种数据上报方式,常用的有:

  • Java Agent:通过 -javaagent:skywalking-agent.jar 实现,零代码、零依赖、自动埋点、性能最好。
  • OpenTelemetry OTLP:云原生标准,可对接不同类型的监控平台。

Spring 官方支持 Micrometer + OTLP 上报方案,完整数据流:
#mermaid-svg-jFX0dMEAIBRcLV9H{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jFX0dMEAIBRcLV9H .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jFX0dMEAIBRcLV9H .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jFX0dMEAIBRcLV9H .error-icon{fill:#552222;}#mermaid-svg-jFX0dMEAIBRcLV9H .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jFX0dMEAIBRcLV9H .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jFX0dMEAIBRcLV9H .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jFX0dMEAIBRcLV9H .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jFX0dMEAIBRcLV9H .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jFX0dMEAIBRcLV9H .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jFX0dMEAIBRcLV9H .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jFX0dMEAIBRcLV9H .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jFX0dMEAIBRcLV9H .marker.cross{stroke:#333333;}#mermaid-svg-jFX0dMEAIBRcLV9H svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jFX0dMEAIBRcLV9H p{margin:0;}#mermaid-svg-jFX0dMEAIBRcLV9H .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jFX0dMEAIBRcLV9H .cluster-label text{fill:#333;}#mermaid-svg-jFX0dMEAIBRcLV9H .cluster-label span{color:#333;}#mermaid-svg-jFX0dMEAIBRcLV9H .cluster-label span p{background-color:transparent;}#mermaid-svg-jFX0dMEAIBRcLV9H .label text,#mermaid-svg-jFX0dMEAIBRcLV9H span{fill:#333;color:#333;}#mermaid-svg-jFX0dMEAIBRcLV9H .node rect,#mermaid-svg-jFX0dMEAIBRcLV9H .node circle,#mermaid-svg-jFX0dMEAIBRcLV9H .node ellipse,#mermaid-svg-jFX0dMEAIBRcLV9H .node polygon,#mermaid-svg-jFX0dMEAIBRcLV9H .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jFX0dMEAIBRcLV9H .rough-node .label text,#mermaid-svg-jFX0dMEAIBRcLV9H .node .label text,#mermaid-svg-jFX0dMEAIBRcLV9H .image-shape .label,#mermaid-svg-jFX0dMEAIBRcLV9H .icon-shape .label{text-anchor:middle;}#mermaid-svg-jFX0dMEAIBRcLV9H .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jFX0dMEAIBRcLV9H .rough-node .label,#mermaid-svg-jFX0dMEAIBRcLV9H .node .label,#mermaid-svg-jFX0dMEAIBRcLV9H .image-shape .label,#mermaid-svg-jFX0dMEAIBRcLV9H .icon-shape .label{text-align:center;}#mermaid-svg-jFX0dMEAIBRcLV9H .node.clickable{cursor:pointer;}#mermaid-svg-jFX0dMEAIBRcLV9H .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jFX0dMEAIBRcLV9H .arrowheadPath{fill:#333333;}#mermaid-svg-jFX0dMEAIBRcLV9H .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jFX0dMEAIBRcLV9H .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jFX0dMEAIBRcLV9H .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jFX0dMEAIBRcLV9H .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jFX0dMEAIBRcLV9H .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jFX0dMEAIBRcLV9H .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jFX0dMEAIBRcLV9H .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jFX0dMEAIBRcLV9H .cluster text{fill:#333;}#mermaid-svg-jFX0dMEAIBRcLV9H .cluster span{color:#333;}#mermaid-svg-jFX0dMEAIBRcLV9H div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jFX0dMEAIBRcLV9H .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jFX0dMEAIBRcLV9H rect.text{fill:none;stroke-width:0;}#mermaid-svg-jFX0dMEAIBRcLV9H .icon-shape,#mermaid-svg-jFX0dMEAIBRcLV9H .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jFX0dMEAIBRcLV9H .icon-shape p,#mermaid-svg-jFX0dMEAIBRcLV9H .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jFX0dMEAIBRcLV9H .icon-shape .label rect,#mermaid-svg-jFX0dMEAIBRcLV9H .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jFX0dMEAIBRcLV9H .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jFX0dMEAIBRcLV9H .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jFX0dMEAIBRcLV9H :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Storage
OTLP HTTP:4318 上报Trace/gen_ai指标/日志
依据otel-rules配置+MAL解析指标
HTTP查询 OAP:12800
查询存储返回数据
SpringBoot + SpringAI

集成OpenTelemetry
SkyWalking OAP
持久化存储
BanyanDB:17912
ElasticSearch:9200
Booster UI:8080
可视化展示

链路详情 + GenAI指标 + 服务监控大盘

流程说明:

  1. SpringAI 应用通过 OTLP 采集大模型调用链路、Token、耗时gen_ai_*指标
  2. 使用 OTLP 协议 (4318) 推送至 OAP
  3. OAP 加载 otel-rules 规则文件解析指标,存入 BanyanDB/ES
  4. BoosterUI 通过 12800 端口请求 OAP 查询数据
  5. OAP 读取存储数据,UI 渲染监控图表

1.2 环境信息

组件 版本
Spring Boot 3.5.11
Spring AI 1.1.4
Micrometer Tracing 由 Spring Boot 管理
OpenTelemetry 由 Spring Boot 管理
SkyWalking OAP 10.x
传输协议 OTLP gRPC

2. 依赖配置

2.1 Maven 依赖

接入 OTLP 依赖清单:

xml 复制代码
<!-- 1. Spring Boot Actuator:监控基础设施 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- 2. Micrometer Tracing 核心 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing</artifactId>
</dependency>

<!-- 3. Micrometer → OpenTelemetry 桥接 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>

<!-- 4. Micrometer OTLP Registry:Metrics 通过 OTLP 导出 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-otlp</artifactId>
</dependency>

<!-- 5. OTel OTLP Exporter:Tracing 通过 OTLP 导出 -->
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>

<!-- 6. OTel Logback Appender:应用日志通过 OTLP 导出 -->
<dependency>
    <groupId>io.opentelemetry.instrumentation</groupId>
    <artifactId>opentelemetry-logback-appender-1.0</artifactId>
    <version>2.14.0-alpha</version>
</dependency>

依赖关系图:

复制代码
micrometer-tracing (核心 API)
    │
    ├── micrometer-tracing-bridge-otel (Micrometer → OTel)
    │       │
    │       └── opentelemetry-exporter-otlp (OTLP 导出)
    │
    └── micrometer-registry-otlp (Metrics OTLP 导出)

opentelemetry-logback-appender-1.0 (Logback → OTLP)

3. 配置文件

3.1 application.yml --- 可观测性配置

配置说明:

  • log-prompt/log-completion 等高敏感字段默认 false,开启会把 Prompt 存入 Span,存在隐私泄露风险。
  • Metrics 暂不开启:Spring Boot 只支持 HTTP 上报,SkyWalking 10.x 版本又只支持 PRC

11.x 版本说明:

yaml 复制代码
# ==================== Spring Boot Actuator 可观测性配置 ====================
management:
  endpoints:
    web:
      base-path: /actuator
      exposure:
        include: '*'                          # 暴露所有端点
  tracing:
    enabled: true
    sampling:
      probability: 1.0                       # 全量采样(生产环境建议 0.1)
  otlp:
    tracing:
      endpoint: http://192.168.1.235:4319
      transport: grpc
      export:
        enabled: true
    metrics:
      export:
        url: http://192.168.1.235:12800/v1/metrics
        enabled: false                        # Metrics 暂不开启
    logging:
      endpoint: http://192.168.1.235:4319
      transport: grpc
      export:
        enabled: true

# ==================== Spring AI 观测配置 ====================
spring:
  ai:
    chat:
      observations:
        include-error-logging: true           # 错误时记录日志
        log-completion: true                  # 记录模型回答内容
        log-prompt: true                      # 记录 Prompt 内容
      client:
        enabled: true
        observations:
          log-prompt: true
          log-completion: true

# ==================== 日志级别 ====================
logging:
  level:
    io.opentelemetry.exporter.otlp: TRACE
    io.opentelemetry.instrumentation.logback: TRACE
    io.opentelemetry.sdk.logs: TRACE
    io.micrometer.tracing: DEBUG
    io.micrometer.registry.otlp: DEBUG

3.2 logback-spring.xml --- Logback OTLP Appender

关键点:

  • %X{traceId:-} 和 %X{spanId:-} 从 MDC 中提取当前 Span 信息,实现日志与 Trace 的关联
  • OpenTelemetryAppender 将日志异步导出到 OTLP 端点,与 application.yml 中配置的地址一致
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 控制台输出格式:包含 traceId 和 spanId -->
    <property name="CONSOLE_LOG_PATTERN"
        value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId:-}][%X{spanId:-}] %-5level %logger{50} - %msg%n"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- OTLP Appender:将日志通过 gRPC 上报到 SkyWalking OAP -->
    <appender name="OTLP" class="io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender">
        <captureExperimentalAttributes>true</captureExperimentalAttributes>
        <captureCodeAttributes>true</captureCodeAttributes>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="OTLP"/>
    </root>
</configuration>

4. Java 代码实现

4.1 OtlpLoggingConfig --- 激活 Logback Appender

OpenTelemetryAppender 需要一个已初始化的 OpenTelemetry 实例才能工作。Spring Boot 自动装配了 OpenTelemetry Bean,但 Appender 默认无法获取。此配置类在启动时完成桥接:

java 复制代码
@Component
public class OtlpLoggingConfig implements InitializingBean {

    private final OpenTelemetry openTelemetry;

    public OtlpLoggingConfig(OpenTelemetry openTelemetry) {
        this.openTelemetry = openTelemetry;
    }

    @Override
    public void afterPropertiesSet() {
        // 将 Spring Boot 自动装配的 OpenTelemetry 实例
        // 注入到 Logback 的 OpenTelemetryAppender 中
        OpenTelemetryAppender.install(openTelemetry);
    }
}

如果不做这一步,OpenTelemetryAppender 会使用默认的空 OpenTelemetry 实例,日志不会真正被导出。

4.2 自定义 ObservationConvention --- 富化 Span 内容

默认的 DefaultChatModelObservationConvention 只记录参数(temperature、maxTokens 等),不记录 Prompt 和回答的文本内容。通过继承它可以添加业务关心的数据。

4.2.1 ChatModel 观测约定

java 复制代码
public class ContentEnrichedChatModelObservationConvention
        extends DefaultChatModelObservationConvention {

    private static final int MAX_CONTENT_LENGTH = 1024;

    @Override
    public KeyValues getHighCardinalityKeyValues(ChatModelObservationContext context) {
        // ① 先拿到父类所有的默认 KeyValues(temperature、token 用量等)
        KeyValues keyValues = super.getHighCardinalityKeyValues(context);

        // ② 追加 Prompt 内容(截断以防止 Span 过大)
        keyValues = appendPromptContent(keyValues, context);

        // ③ 追加模型回答内容
        keyValues = appendCompletionContent(keyValues, context);

        return keyValues;
    }

    private KeyValues appendPromptContent(KeyValues keyValues,
            ChatModelObservationContext context) {
        String content = context.getRequest().getInstructions()
                .stream()
                .map(Content::getText)
                .collect(Collectors.joining("\n"));
        return keyValues.and("gen_ai.prompt.content",
                truncate(content, MAX_CONTENT_LENGTH));
    }

    private KeyValues appendCompletionContent(KeyValues keyValues,
            ChatModelObservationContext context) {
        if (context.getResponse() == null) {
            return keyValues;
        }
        String content = context.getResponse().getResults()
                .stream()
                .map(g -> g.getOutput().getText())
                .collect(Collectors.joining("\n"));
        return keyValues.and("gen_ai.completion.content",
                truncate(content, MAX_CONTENT_LENGTH));
    }

    private String truncate(String text, int maxLen) {
        if (text == null) return "";
        return text.length() <= maxLen ? text
                : text.substring(0, maxLen) + "...[truncated]";
    }
}

4.2.2 ChatClient 观测约定

ChatClient 有自己独立的 ObservationContext,需单独扩展:

java 复制代码
public class ContentEnrichedChatClientObservationConvention
        extends DefaultChatClientObservationConvention {

    private static final int MAX_CONTENT_LENGTH = 1024;

    @Override
    public KeyValues getHighCardinalityKeyValues(ChatClientObservationContext context) {
        KeyValues keyValues = super.getHighCardinalityKeyValues(context);
        keyValues = appendPromptContent(keyValues, context);
        keyValues = appendCompletionContent(keyValues, context);
        return keyValues;
    }

    // ... 实现逻辑与 ChatModel 版本相同,操作 ChatClientObservationContext
}

4.2.3 注册自定义约定

java 复制代码
@Configuration
public class ChatClientConfig {

    // 替换默认 ChatModel 观测约定
    @Bean
    public ChatModelObservationConvention chatModelObservationConvention() {
        return new ContentEnrichedChatModelObservationConvention();
    }

    // 替换默认 ChatClient 观测约定
    @Bean
    public ChatClientObservationConvention chatClientObservationConvention() {
        return new ContentEnrichedChatClientObservationConvention();
    }
}

4.3 ChatController --- 手动创建 Observation 示例

除了框架自动创建的 ChatModel / ChatClient Span,业务代码也可以手动创建自定义 Observation:

java 复制代码
@RestController
@RequestMapping("/chat")
public class ChatController {

    private final ChatClient chatClient;
    private final ObservationRegistry observationRegistry;

    public ChatController(ChatClient chatClient,
            ObservationRegistry observationRegistry) {
        this.chatClient = chatClient;
        this.observationRegistry = observationRegistry;
    }

    @GetMapping
    public String chat(@RequestParam String message) {
        // 框架自动创建 ChatClient Span(透明)
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }

    public void doSomething() {
        // 手动创建自定义 Span
        Observation observation = Observation.createNotStarted(
                "custom.operation", this.observationRegistry);

        observation.lowCardinalityKeyValue("locale", "en-US");
        observation.highCardinalityKeyValue("userId", "42");

        observation.observe(() -> {
            // 此代码块的执行耗时和状态会被记录
            performBusinessLogic();
        });
    }
}

5. 数据流转路径

5.1 整体数据流

复制代码
┌──────────────────────────────────────────────────┐
│              Spring AI Application               │
│                                                  │
│  ┌──────────────┐  ┌──────────────┐              │
│  │ ChatModel    │  │ Custom       │              │
│  │ Observation  │  │ Observation  │              │
│  │ (自动创建)   │  │ (手动创建)   │              │
│  └──────┬───────┘  └──────┬───────┘              │
│         │                 │                      │
│  ┌──────▼─────────────────▼───────┐              │
│  │     Micrometer Observation     │              │
│  │   (统一 API,不感知后端)        │              │
│  └──────────────┬─────────────────┘              │
│                 │                                │
│  ┌──────────────▼─────────────────┐              │
│  │  micrometer-tracing-bridge-otel │             │
│  │  (Micrometer → OTel 格式转换)   │             │
│  └──────────────┬─────────────────┘              │
│                 │                                │
│         ┌───────┴───────┐                        │
│         │               │                        │
│  ┌──────▼──────┐ ┌──────▼──────────┐            │
│  │ OTLP Trace  │ │ Logback OTLP    │            │
│  │ Exporter    │ │ Appender        │            │
│  │ (gRPC)      │ │ (gRPC)          │            │
│  └──────┬──────┘ └──────┬──────────┘            │
└─────────┼───────────────┼────────────────────────┘
          │               │
    ┌─────▼───────────────▼─────┐
    │    SkyWalking OAP         │
    │    (192.168.1.235:4319)   │
    │                           │
    │  ┌─────────────────────┐  │
    │  │  Traces + Logs 关联  │  │
    │  └─────────────────────┘  │
    └───────────────────────────┘

5.2 关键技术点

环节 组件 作用
埋点 Micrometer Observation 统一 API,ChatModel/ChatClient 自动埋点
格式转换 micrometer-tracing-bridge-otel Micrometer Span → OTel Span
Trace 导出 opentelemetry-exporter-otlp OTLP gRPC → SkyWalking OAP
日志导出 OpenTelemetryAppender Logback 日志 → OTLP gRPC → SkyWalking OAP
日志关联 %X{traceId} / %X{spanId} MDC 自动注入当前 Span 信息
内容富化 自定义 ObservationConvention 添加 gen_ai.prompt.content 等业务 Tag

6. 接入步骤总结

6.1 最小接入清单

步骤 文件 操作
1 pom.xml 添加 6 个依赖
2 application.yml 配置 otel + management.otlp + spring.ai.chat.observations
3 logback-spring.xml 添加 OpenTelemetryAppender + traceId/spanId 格式
4 OtlpLoggingConfig.java OpenTelemetryAppender.install(openTelemetry)
5 自定义 ObservationConvention 继承默认实现,添加业务 Key(可选)

6.2 验证方法

bash 复制代码
# 1. 启动应用
mvn spring-boot:run -pl ai-chat-demo

# 2. 请求接口,产生 Span
curl "http://localhost:8080/chat?message=hello"

# 3. 检查控制台日志是否包含 traceId
# 输出示例:
# 2026-06-08 10:30:00.123 [http-nio-8080-exec-1] [abc123][def456] INFO  ... - ...

# 4. 在 SkyWalking UI 中查看
# - 链路追踪:查看 gen_ai.client.operation Span
# - 日志关联:点击 Span 可见关联的日志内容
# - 自定义 Tag:gen_ai.prompt.content / gen_ai.completion.content

AI 相关指标(SkyWalking 从链路数据中主动解析的):

日志:

链路需要通过 http://192.168.1.1:8080/zipkin 查询:

6.3 生产环境调优建议

配置项 开发环境 生产环境
sampling.probability 1.0 0.1 ~ 0.3
MAX_CONTENT_LENGTH 1024 256 ~ 512
OTel 日志级别 TRACE / DEBUG WARN
log-completion / log-prompt true false(避免日志过大)

7. 关键设计模式

7.1 埋点与后端解耦

复制代码
业务代码 → Micrometer Observation API (稳定)
              │
              ├── Bridge A → OTel → SkyWalking
              ├── Bridge B → OTel → Jaeger
              └── Bridge C → Brave → Zipkin

应用层代码只依赖 Micrometer Observation API,后端存储(SkyWalking / Jaeger / Zipkin)通过更换 Bridge 即可切换,无需改动业务代码。

7.2 Convention 扩展模式

复制代码
DefaultChatModelObservationConvention
    │ 提供 17 个默认 KeyValue(参数 + 用量)
    │
    └── ContentEnrichedChatModelObservationConvention
         │ 追加 gen_ai.prompt.content
         │ 追加 gen_ai.completion.content

通过继承而非修改来扩展,调用 super.getHighCardinalityKeyValues() 保留框架默认行为,仅追加自定义数据。

7.3 日志与 Trace 的关联

不是通过配置文件中的固定规则关联,而是通过 MDC 的实时注入:

复制代码
请求到达 → Micrometer 创建 Span → traceId/spanId 写入 MDC
                                         │
                        Logback %X{traceId:-} 从 MDC 读取
                                         │
                        日志携带 traceId → OTLP Appender 导出
                                         │
                        SkyWalking 按 traceId 自动关联日志与 Span

这一切是自动的 ------开发者不需要在代码中手动传递 traceId。

相关推荐
孟健13 分钟前
从单体失控到解耦管道:用 Unix 哲学重构 Anthropic 式多 Agent 动态工作流
人工智能·python·架构
火山引擎开发者社区20 分钟前
模力全开|火山引擎 ADG 创作挑战赛火热开启!
人工智能
ZZHow102423 分钟前
Ascend C算子开发(高级)笔记
c++·人工智能·笔记·深度学习·华为云
llgdwuhan38 分钟前
光制造突围 | 国产耦合设备的替代与迭代
人工智能·光模块·耦合测试设备·光模块耦合设备·芯片测试设备·双透镜自动耦合设备
秦先生在广东44 分钟前
Microsoft BitNet b1.58: 重新定义本地化 AI 推理的性能与能效极限
人工智能
秦先生在广东1 小时前
去中心化与全能化:深入剖析 Open WebUI 的自托管架构与工程实践
人工智能
IvorySQL1 小时前
PostgreSQL 日报|堆表选择性索引更新(10 月 13 日)
数据库·人工智能·postgresql·开源·区块链
蜗牛互联网1 小时前
Java 17 调用视觉 Responses API:JSON 约束与人工复核路由
java·人工智能·后端
秦先生在广东1 小时前
Agent 驱动的逆向工程工作流:REA 全栈二进制与多格式分析工具深度解析
人工智能
2603_968817341 小时前
AI视频怎么超清增强
人工智能