跳至正文

3. 声明模型并启动后台 ​

开始前: 应用和凭据已创建。本步目标: 声明一个只聊天的智能体,并让后台提供 /api/ai 标准接口。

1. 理解示例文件 ​

文件(相对 tutorial/backend)你负责什么
build.gradle.ktsSpring MVC 运行时与业务后台 SDK 依赖
TutorialApplication.java普通 Spring Boot 启动类
ModelConfiguration.java提供商、模型、绑定、配置和智能体的清单
LocalIdentity.java本地业务令牌验证及平台 USER 凭据映射
application.yml地址、应用、声明归属、开发发布与聊天开关
Initialize.java上一步的独立初始化入口,不参与聊天启动

示例消费本地 Maven 制品,完整构建文件如下。已有 Spring 项目只需加入 SDK 依赖并提供 MVC Web 运行时,无需替换原工程:

kotlin
plugins { java; application }
repositories {
    mavenCentral()
    maven { url = uri("https://sagetripp.github.io/sparktide-docs/maven/") }
}
java { toolchain { languageVersion = JavaLanguageVersion.of(17) } }
tasks.withType<JavaCompile>().configureEach { options.encoding = "UTF-8" }
tasks.withType<JavaExec>().configureEach { jvmArgs("-Dfile.encoding=UTF-8") }
dependencies {
    implementation(platform("org.springframework.boot:spring-boot-dependencies:4.0.8"))
    implementation("org.springframework.boot:spring-boot-starter-webmvc")
    implementation("dev.sparktide:sdk-spring-boot-starter:0.1.0")
    // 独立初始化命令使用 Jackson 2,与 SDK 核心保持一致。
    implementation("com.fasterxml.jackson.core:jackson-databind:2.20.1")
}
application { mainClass = "tutorial.TutorialApplication" }
tasks.register<JavaExec>("initialize") {
    classpath = sourceSets.main.get().runtimeClasspath
    mainClass = "tutorial.Initialize"
}
tasks.register<JavaExec>("credentials") {
    classpath = sourceSets.main.get().runtimeClasspath
    mainClass = "tutorial.Initialize"
    args("credentials")
}
tasks.register<JavaExec>("selectAgent") {
    classpath = sourceSets.main.get().runtimeClasspath
    mainClass = "tutorial.SelectAgent"
    args(providers.gradleProperty("agentVersion").getOrElse("1.1.0"))
}

2. 用后台 SDK 声明模型与智能体 ​

模型的五层配置分别回答:连到哪里 → 调哪个模型 → 哪个应用可用 → 如何调用 → 谁来执行任务。这里只建一个默认智能体,没有工具、知识和子智能体。

Java / Kotlin 二选一。下载示例已包含 Java 文件;Kotlin 项目需要安装 sdk-kotlin,启用 Kotlin JVM 插件,并用下面 Kotlin 文件替换 Java 同名配置,不能同时保留两份 Bean。

java
package tutorial;
import dev.sparktide.sdk.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import java.net.URI;
import java.util.List;
@Configuration
public class ModelConfiguration {
    @Bean
    RegistrationManifest models(@Value("${tutorial.model-endpoint}") URI endpoint,
                                @Value("${tutorial.model-id}") String modelId) {
        String v = "1.0.0";
        return new RegistrationManifest(List.of(
            ModelDeclarations.openAIProvider("provider", v, endpoint, "MODEL_API_KEY", true),
            ModelDeclarations.model("model", v, "provider", v, modelId,
                ModelCapabilities.builder().supports(ModelCapabilities.Feature.STREAMING, true)
                    .supports(ModelCapabilities.Feature.TOOL_CALLING, true).build()),
            ModelDeclarations.binding("binding", v, "model", v),
            ModelDeclarations.profile("profile", v,
                ModelProfile.builder("binding", v).maxOutputTokens(1024).build()),
            ModelDeclarations.agent("main", v, "你是业务助手,请用中文回答。", "profile", v,
                List.of(), List.of())
        )).managedBy("tutorial-service");
    }
}
kotlin
package tutorial
import dev.sparktide.sdk.*
import dev.sparktide.sdk.kotlin.*
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.net.URI

@Configuration
open class ModelConfiguration {
    @Bean
    open fun models(@Value("\${tutorial.model-endpoint}") endpoint: URI,
                    @Value("\${tutorial.model-id}") modelId: String): RegistrationManifest {
        val v = "1.0.0"
        return RegistrationManifest(listOf(
            openAIProvider("provider", v, endpoint, "MODEL_API_KEY", true),
            modelDefinition("model", v, ReleaseBundle.Entry("provider", v), modelId,
                ModelCapabilities.builder().supports(ModelCapabilities.Feature.STREAMING, true)
                    .supports(ModelCapabilities.Feature.TOOL_CALLING, true).build()),
            modelBinding("binding", v, ReleaseBundle.Entry("model", v)),
            modelProfile("profile", v, ModelProfile.builder("binding", v).maxOutputTokens(1024).build()),
            agentDefinition("main", v, "你是业务助手,请用中文回答。",
                ReleaseBundle.Entry("profile", v), emptyList(), emptyList())
        )).managedBy("tutorial-service")
    }
}

完整请求地址和实际模型 ID 来自 business.env。Key 只由底座读取,代码中保存的是名称 MODEL_API_KEY。功能声明必须与服务实际能力匹配,不能靠填写 true 获得供应商不支持的功能。

3. 启用声明与聊天 HTTP API ​

src/main/resources/application.yml 已包含下面配置:

yaml
server:
  address: 127.0.0.1
  port: 8091
tutorial:
  model-endpoint: ${TUTORIAL_MODEL_ENDPOINT}
  model-id: ${TUTORIAL_MODEL_ID}
sparktide:
  enabled: true
  platform-url: ${SPARKTIDE_PLATFORM_URL}
  app-id: tutorial
  token: ${SPARKTIDE_TOKEN}
  default-agent:
    id: main
    version: 1.0.0
  deployment:
    mode: DEVELOPMENT
    source: tutorial-service
    auto-sync: true
  chat:
    enabled: true
    platform-url: ${SPARKTIDE_PLATFORM_URL}
    app-id: tutorial
    path: /api/ai

sparktide.enabled 控制能力注册;sparktide.chat.enabled 控制聊天 HTTP API。它们是独立开关。本教程把二者放在同一业务服务方便学习,生产可独立部署不持有管理凭据的聊天网关。

DEVELOPMENT + auto-sync=true 会预检并原子发布这份清单,设置默认入口;同内容再次启动不会新建版本。生产改成显式发布,第 7 步说明。

4. 接入用户身份 ​

LocalIdentity.java 已提供完整的本地适配:先验证随机业务 Bearer 令牌,再产生固定可信 Principal,最后由 ChatCredentialResolver 返回底座 USER 凭据。只在 local profile 生效,后台绑定回环地址。

真实项目用原有 Spring Security / 登录过滤器产生 Principal,再将它映射到平台可验证凭据。不要从用户名请求头、Context 或模型文本获得可信身份;Cookie 登录还需要原业务 CSRF 校验。

你不需要编写聊天 Controller、转发会话数据库或自己转发 SSE,Starter 已提供它们。

5. 启动与检查 ​

新开终端,在 tutorial/backend 执行:

powershell
& '..\scripts\use-env.ps1' '..\.local\business.env'
$env:SPRING_PROFILES_ACTIVE='local'
.\gradlew.bat run

保持终端运行。另一终端在 tutorial 根目录执行:

powershell
& '.\scripts\use-env.ps1' '.\.local\business.env'
$headers=@{Authorization="Bearer $env:DEV_BROWSER_TOKEN"}
Invoke-RestMethod 'http://127.0.0.1:8091/api/ai/conversations' -Headers $headers

检查点 ​

首次应返回 items: [] 和 nextOffset: null。去掉 Authorization 应返回 401,表示业务登录校验在起作用。这个请求只检查身份和会话入口,模型将在第 5 步调用。

如果启动报告清单归属 / 版本冲突,先核对是否复用了他人 tutorial 应用;不覆盖或认领已有资源。配置变化要发布新版本,详见声明与发布。

适用版本:0.1 发布线 · 最近核对:2026-10-09 · SparkTide 产品文档

汇聚智能,驱动涌现。