Skip to content

使用 Firestore 的会话状态管理

Supported in ADKJava

Google Cloud Firestore 是一个灵活、可扩展的 NoSQL 云数据库,用于客户端和服务端开发中的数据存储和同步。 ADK 提供了使用 Firestore 管理持久化智能体会话状态的原生集成,支持持续的多轮对话而不会丢失对话历史。

使用场景

  • 客户支持智能体:在长期支持工单中维护上下文,使智能体能够在多个会话中记住过去的故障排查步骤和偏好。
  • 个性化助手:构建随时间积累用户知识的智能体,基于历史对话个性化未来交互。
  • 多模态工作流:无缝处理涉及图像、视频和音频以及文本对话的复杂用例,利用内置的 GCS 制品存储。
  • 企业级聊天机器人:部署具有生产级持久性的高可靠性对话 AI 应用程序,适用于大规模企业环境。

先决条件

安装依赖项

Note

请确保 google-adkgoogle-adk-firestore-session-service 使用相同版本,以保证兼容性。

将以下依赖项添加到你的 pom.xml(Maven)或 build.gradle(Gradle)中,将 1.2.0 替换为你目标 ADK 版本:

Maven

<dependencies>
    <!-- ADK 核心 -->
    <dependency>
        <groupId>com.google.adk</groupId>
        <artifactId>google-adk</artifactId>
        <version>1.2.0</version>
    </dependency>
    <!-- Firestore 会话服务 -->
    <dependency>
        <groupId>com.google.adk</groupId>
        <artifactId>google-adk-firestore-session-service</artifactId>
        <version>1.2.0</version>
    </dependency>
</dependencies>

Gradle

dependencies {
    // ADK 核心
    implementation 'com.google.adk:google-adk:1.2.0'
    // Firestore 会话服务
    implementation 'com.google.adk:google-adk-firestore-session-service:1.2.0'
}

示例:带有 Firestore 会话管理的智能体

使用 FirestoreDatabaseRunner 来封装你的智能体和 Firestore 支持的会话管理。以下是设置一个能在多轮对话中使用自定义会话 ID 记住上下文的简单助手智能体的完整示例。

import com.google.adk.agents.BaseAgent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.RunConfig;
import com.google.adk.runner.FirestoreDatabaseRunner;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.FirestoreOptions;
import io.reactivex.rxjava3.core.Flowable;
import java.util.Map;
import com.google.adk.sessions.FirestoreSessionService;
import com.google.adk.sessions.Session;
import com.google.adk.tools.Annotations.Schema;
import com.google.adk.tools.FunctionTool;
import com.google.genai.types.Content;
import com.google.genai.types.Part;
import com.google.adk.events.Event;
import java.util.Scanner;
import static java.nio.charset.StandardCharsets.UTF_8;

public class YourAgentApplication {

    public static void main(String[] args) {
        System.out.println("正在启动 YourAgentApplication...");

        RunConfig runConfig = RunConfig.builder().build();
        String appName = "hello-time-agent";

        BaseAgent timeAgent = initAgent();

        // 初始化 Firestore
        FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance();
        Firestore firestore = firestoreOptions.getService();

        // 使用 FirestoreDatabaseRunner 持久化会话状态
        FirestoreDatabaseRunner runner = new FirestoreDatabaseRunner(
                timeAgent,
                appName,
                firestore
        );

        // 创建新会话或加载已有会话
        Session session = new FirestoreSessionService(firestore)
                .createSession(appName, "user1234", null, "12345")
                .blockingGet();

        // 启动交互式命令行界面
        try (Scanner scanner = new Scanner(System.in, UTF_8)) {
            while (true) {
                System.out.print("\\n你 > ");
                String userInput = scanner.nextLine();
                if ("quit".equalsIgnoreCase(userInput)) {
                    break;
                }

                Content userMsg = Content.fromParts(Part.fromText(userInput));
                Flowable<Event> events = runner.runAsync(session.userId(), session.id(), userMsg, runConfig);

                System.out.print("\\n智能体 > ");
                events.blockingForEach(event -> {
                    if (event.finalResponse()) {
                        System.out.println(event.stringifyContent());
                    }
                });
            }
        }
    }

    /** 模拟工具实现 */
    @Schema(description = "获取给定城市的当前时间")
    public static Map<String, String> getCurrentTime(
        @Schema(name = "city", description = "要获取时间的城市名称") String city) {
        return Map.of(
            "city", city,
            "time", "现在的时间是上午 10:30。"
        );
    }

    private static BaseAgent initAgent() {
        return LlmAgent.builder()
            .name("hello-time-agent")
            .description("报告指定城市的当前时间")
            .instruction(\"""
                你是一个有用的助手,可以报告城市的当前时间。
                为此使用 'getCurrentTime' 工具。
                \""")
            .model("gemini-flash-latest")
            .tools(FunctionTool.create(YourAgentApplication.class, "getCurrentTime"))
            .build();
    }
}

配置

Note

Firestore 会话服务支持配置文件设置。这使你可以轻松地定位专用的 Firestore 数据库,并定义用于存储智能体会话数据的自定义集合名称。

你可以通过提供自己的 Firestore 属性设置来自定义 ADK 应用程序以使用 Firestore 会话服务,否则库将使用默认设置。

环境特定配置

库按照以下解析顺序优先使用环境特定的属性文件而非默认设置:

  1. 环境变量覆盖:首先检查名为 env 的环境变量。如果设置了此变量(例如 env=dev),则会尝试加载匹配模板的属性文件:adk-firestore-{env}.properties(例如 adk-firestore-dev.properties)。
  2. 默认回退:如果未设置 env 变量,或无法找到环境特定文件,库默认加载 adk-firestore.properties

示例属性设置:

# 用于存储会话数据的 Firestore 集合名称
firebase.root.collection.name=adk-session
# 用于制品存储的 Google Cloud Storage 存储桶名称
gcs.adk.bucket.name=your-gcs-bucket-name
# 关键字提取的停用词
keyword.extraction.stopwords=a,about,above,after,again,against,all,am,an,and,any,are,aren't,as,at,be,because,been,before,being,below,between,both,but,by,can't,cannot,could,couldn't,did,didn't,do,does,doesn't,doing,don't,down,during,each,few,for,from,further,had,hadn't,has,hasn't,have,haven't,having,he,he'd,he'll,he's,her,here,here's,hers,herself,him,himself,his,how,i,i'd,i'll,i'm,i've,if,in,into,is

Important

FirestoreDatabaseRunner 要求定义 gcs.adk.bucket.name 属性。这是因为运行器内部初始化了 GcsArtifactService 来处理多模态制品存储。如果此属性缺失或为空,应用程序将在启动时抛出 RuntimeException。该属性用于存储智能体生成或处理的图像、视频、音频文件等制品。

资源