zhuyongxin 934d8eee29 feat(observability): 在 Hook 中输出模型返回的文本内容
## 改动内容

### 增强 AgentLoggingHook.afterModel()

在模型调用完成后,提取并输出模型返回的文本内容:

```java
@Override
public AgentCommand afterModel(List<Message> messages, RunnableConfig config) {
    // 查找最后一条 AssistantMessage
    AssistantMessage lastAssistant = ...;

    // 提取文本内容
    String textContent = extractTextContent(lastAssistant);
    log.info("*** [Agent 思考] 模型返回文本: {}", textContent);

    // 检查工具调用
    if (hasToolCalls) {
        log.info("*** [Agent 思考] 模型决定调用 N 个工具");
    } else {
        log.info("*** [Agent 思考] 这是最终答案");
    }
}
```

---

### extractTextContent() 实现

通过反射提取 AssistantMessage 的文本内容:

```java
private String extractTextContent(AssistantMessage message) {
    try {
        // 尝试获取 text 或 content 字段
        Field textField = message.getClass().getDeclaredField("text");
        textField.setAccessible(true);
        Object value = textField.get(message);
        return value != null ? value.toString() : null;
    } catch (NoSuchFieldException e) {
        // 尝试 content 字段
        try {
            Field contentField = message.getClass().getDeclaredField("content");
            // ...
        } catch (NoSuchFieldException ex) {
            // 字段不存在,返回 null
        }
    }
}
```

**为什么用反射?**
- Spring AI 的 `AssistantMessage` 没有公开的 `getText()` 或 `getContent()` 方法
- 不同版本可能使用 `text` 或 `content` 字段
- 反射可以兼容不同实现

---

## 日志输出示例

### 第 1 轮:模型决定调用工具

```
========================================
*** [Agent 思考] 第 1 轮思考完成
*** [Agent 思考] 模型返回文本: 我需要查询知识库来了解支付失败的原因
*** [Agent 思考] 模型决定调用 1 个工具:
  - 工具: lookup_knowledge, 参数: {"query":"支付失败原因"}
*** [Agent 思考] 等待工具执行结果...
========================================
```

---

### 第 2 轮:模型返回最终答案

```
========================================
*** [Agent 思考] 第 2 轮思考完成
*** [Agent 思考] 模型返回文本: 根据知识库的记录,支付失败的主要原因包括:
1. ERR_TIMEOUT - 支付网关响应超时,通常是网络问题或第三方服务不稳定
2. ERR_INVALID_SIGNATURE - 签名验证失败,检查密钥配置
3. ERR_INSUFFICIENT_BALANCE - 账户余额不足
... (已截断,总长度: 1234)
*** [Agent 思考] 模型决定不调用工具
*** [Agent 思考] 这是最终答案,准备返回给用户
========================================
```

---

## 关键观测点

| 轮次 | 模型输出内容 | 决策 |
|------|-------------|------|
| **第 1 轮** | 模型的推理过程(通常很短) | 决定调用工具 |
| **第 2 轮** | 模型的最终答案(完整回复) | 不调用工具 |

---

## 内容截断策略

- 长度 ≤ 500:完整输出
- 长度 > 500:截断前 500 字符,显示总长度

```
模型返回文本: 根据知识库的记录,支付失败的主要原因包括...
(前 500 字符)
... (已截断,总长度: 1234)
```

---

## 异常处理

如果反射失败(字段不存在或访问被拒绝):

```java
catch (Exception e) {
    log.debug("无法提取 AssistantMessage 文本内容: {}", e.getMessage());
    return null;
}
```

日志输出:
```
*** [Agent 思考] 模型返回文本: (无法提取)
```

不会中断程序,只是跳过文本输出。

---

## 完整的思考流程日志

```
📝 用户问题: 支付为什么会失败?

*** [Agent 思考] 第 1 轮思考开始
*** [Agent 思考] 准备调用模型...
*** [Agent 思考] 第 1 轮思考完成
*** [Agent 思考] 模型返回文本: 我需要查询知识库
*** [Agent 思考] 模型决定调用 1 个工具:
  - 工具: lookup_knowledge, 参数: {"query":"支付失败"}

>>> [工具调用] lookup_knowledge
<<< [工具返回] lookup_knowledge
<<< 结果: found=true

*** [Agent 思考] 第 2 轮思考开始
*** [Agent 思考] 准备调用模型...
*** [Agent 思考] 第 2 轮思考完成
*** [Agent 思考] 模型返回文本: 根据知识库的记录,支付失败...
*** [Agent 思考] 模型决定不调用工具
*** [Agent 思考] 这是最终答案,准备返回给用户

⏱️  总耗时: 1523 ms
📏 输出长度: 456 字符
```

---

## 提交历史

```
当前 feat(observability): 在 Hook 中输出模型返回的文本内容
7c8758d refactor(observability): 简化 ChatService 日志,避免与 Hook 重复
b3ea6e2 feat(observability): 添加 Agent 思考过程日志 Hook
```
2026-06-25 17:27:48 +08:00
2026-04-30 11:19:46 +08:00
2026-05-31 21:45:14 +08:00
2026-04-30 11:19:46 +08:00
2026-04-30 11:19:46 +08:00
2026-04-30 11:19:46 +08:00

SuperBizAgent

基于 Spring Boot + AI Agent 的智能问答与运维系统

📖 项目简介

企业级智能业务代理系统,包含两大核心模块:

1. RAG 智能问答

集成 Milvus 向量数据库和阿里云 DashScope,提供基于检索增强生成的智能问答能力,支持多轮对话和流式输出。

2. AIOps 智能运维

基于 AI Agent 的自动化运维系统,采用 Planner-Executor-Replanner 架构,实现告警分析、日志查询、智能诊断和报告生成。

🚀 核心特性

  • ✅ RAG 问答: 向量检索 + 多轮对话 + 流式输出
  • ✅ AIOps 运维: 智能诊断 + 多 Agent 协作 + 自动报告
  • ✅ 工具集成: 文档检索、告警查询、日志分析、时间工具
  • ✅ 会话管理: 上下文维护、历史管理、自动清理
  • ✅ Web 界面: 提供测试界面和 RESTful API

🛠️ 技术栈

技术 版本 说明
Java 17 开发语言
Spring Boot 3.2.0 应用框架
Spring AI - AI Agent 框架
DashScope 2.17.0 阿里云 AI 服务
Milvus 2.6.10 向量数据库

📦 核心模块

SuperBizAgent/
├── src/main/java/org/example/
│   ├── controller/
│   │   └── ChatController.java        # 统一接口控制器 ⭐
│   ├── service/
│   │   ├── ChatService.java           # 对话服务 ⭐
│   │   ├── AiOpsService.java          # AIOps 服务 ⭐
│   │   ├── RagService.java            # RAG 服务
│   │   └── Vector*.java               # 向量服务
│   ├── agent/tool/                    # Agent 工具集
│   │   ├── DateTimeTools.java         # 时间工具
│   │   ├── InternalDocsTools.java     # 文档检索
│   │   ├── QueryMetricsTools.java     # 告警查询
│   │   └── QueryLogsTools.java        # 日志查询
│   └── config/                        # 配置类
├── src/main/resources/
│   ├── static/                        # Web 界面
│   └── application.yml                # 应用配置
└── aiops-docs/                        # 运维文档库

📡 核心接口

1. 智能问答接口

流式对话(推荐)

POST /api/chat_stream
Content-Type: application/json

{
  "Id": "session-123",
  "Question": "什么是向量数据库?"
}

支持 SSE 流式输出、自动工具调用、多轮对话。

普通对话

POST /api/chat
Content-Type: application/json

{
  "Id": "session-123",
  "Question": "什么是向量数据库?"
}

一次性返回完整结果,支持工具调用和多轮对话。

2. AIOps 智能运维接口

POST /api/ai_ops

自动执行告警分析流程,生成运维报告(SSE 流式输出)。

3. 会话管理

  • POST /api/chat/clear - 清空会话历史
  • GET /api/chat/session/{sessionId} - 获取会话信息

4. 文件管理

  • POST /api/upload - 上传文件并自动向量化
  • GET /milvus/health - Milvus 健康检查

⚙️ 核心配置

application.yml

server:
  port: 9900

# Milvus 向量数据库
milvus:
  host: localhost
  port: 19530

# 阿里云 DashScope
spring:
  ai:
    dashscope:
      api-key: "${DASHSCOPE_API_KEY}" // 环境变量

# RAG 配置
rag:
  top-k: 3
  model: "qwen3-max"

# 文档分片
document:
  chunk:
    max-size: 800
    overlap: 100

环境变量

export DASHSCOPE_API_KEY=your-api-key

🚀 快速开始

1. 环境准备

# 设置 API Key
export DASHSCOPE_API_KEY=your-api-key

2. 启动应用

方法一: 手动启动

1.先启动向量数据库
docker compose up -d -f vector-database.yml

2.启动服务
mvn clean install
mvn spring-boot:run

方法二:一键启动

make init  # 会自动启动向量数据库并上传运维文档到向量库

3. 使用示例

Web 界面

http://localhost:9900

命令行

# 上传文档
curl -X POST http://localhost:9900/api/upload \
  -F "file=@document.txt"

# 智能问答
curl -X POST http://localhost:9900/api/chat \
  -H "Content-Type: application/json" \
  -d '{"Id":"test","Question":"什么是向量数据库?"}'

# 健康检查
curl http://localhost:9900/milvus/health

🏗️ Phase 1: 基础设施搭建(已完成)

架构概览

Phase 1 完成了项目的基础设施搭建,包括:

  • ✅ 数据持久化层(MySQL + JPA + Flyway)
  • ✅ 会话管理(Redis)
  • ✅ 向量索引(Milvus 集成)
  • ✅ 文档管理服务(上传/查询/删除)
  • ✅ 统一异常处理
  • ✅ RESTful API 接口

本地开发环境

前置要求

  • Java 17+
  • Maven 3.8+
  • Docker & Docker Compose(用于本地数据库)

快速开始

1. 启动依赖服务

# 启动 MySQL + Redis + Milvus(本地开发)
docker-compose up -d

# 查看服务状态
docker-compose ps

2. 配置应用

复制 src/main/resources/application.yml 并根据需要修改:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/super_biz_agent
    username: superbiz
    password: superbiz123
  
  data:
    redis:
      host: localhost
      port: 6379
      password: redis123

milvus:
  host: localhost
  port: 19530

3. 运行应用

# 编译
mvn clean compile

# 运行测试
mvn test

# 启动应用
mvn spring-boot:run

应用将在 http://localhost:9900 启动。

数据库迁移

Flyway 会自动执行数据库迁移:

src/main/resources/db/migration/
├── V001__create_diagnosis_record.sql
├── V002__create_case_library.sql
└── V003__create_api_document.sql

API 文档

文档管理接口:

# 上传文档(仅支持 .md 和 .txt)
POST /api/documents/upload
Content-Type: multipart/form-data

# 查询文档
GET /api/documents/{docId}
GET /api/documents/status/{status}?page=0&size=20
GET /api/documents/faultSource/{faultSource}

# 删除文档
DELETE /api/documents/{docId}

健康检查:

# Milvus 连接测试
mvn test -Dtest=SimpleMilvusTest

# MySQL 连接测试
mvn test -Dtest=MySQLConnectionTest

# Redis 连接测试
mvn test -Dtest=RedisConnectionTest

项目结构

com.superbiz.agent/
├── controller/          # REST 控制器
│   ├── ChatController.java
│   ├── DocumentController.java
│   └── FileUploadController.java
├── service/             # 业务逻辑层
│   ├── DocumentManagementService.java
│   ├── TextExtractorService.java
│   ├── session/         # 会话管理
│   └── ...
├── repository/          # 数据访问层
│   ├── ApiDocumentRepository.java
│   ├── CaseLibraryRepository.java
│   └── DiagnosisRecordRepository.java
├── domain/              # 领域模型
│   ├── entity/          # JPA 实体
│   ├── model/           # 数据模型
│   └── enums/           # 枚举类
├── dto/                 # 数据传输对象
├── exception/           # 异常处理
│   ├── GlobalExceptionHandler.java
│   ├── SessionNotFoundException.java
│   └── DocumentProcessException.java
└── config/              # 配置类

待办事项

  • 向量化索引实现(VectorIndexService.indexDocumentChunks)
  • 混合检索工具(精确匹配 + 语义检索 + RRF 融合)
  • 文档管理集成测试

技术决策

  • 包名重构:org.example → com.superbiz.agent
  • 文本格式:仅支持 Markdown (.md) 和纯文本 (.txt),其他格式需外部转换服务
  • 分块策略:使用 DocumentChunkService 的智能分块(按标题、段落边界)
  • 向量数据库:生产环境推荐 Zilliz Cloud,本地开发可用 Docker Milvus

版本: v1.0.0
作者: chief
许可证: MIT

S
Description
No description provided
Readme Apache-2.0
6.1 MiB
Languages
Java 61.2%
JavaScript 23.9%
CSS 8.2%
Makefile 3.8%
HTML 2.9%