mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 08:43:02 +08:00
refactor(config): adjust method init and onReload to support polymorphic config loading
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package work.slhaf.partner.runtime.interaction;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import work.slhaf.partner.api.agent.runtime.config.Config;
|
||||
@@ -26,7 +27,7 @@ public class WebSocketGatewayRegistry implements Configurable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(@NotNull WebSocketConfig config) {
|
||||
public void init(@NotNull WebSocketConfig config, JSONObject json) {
|
||||
new WebSocketGateway(config.port, config.heartbeatInterval);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package work.slhaf.partner.api.agent.model
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject
|
||||
import org.slf4j.LoggerFactory
|
||||
import work.slhaf.partner.api.agent.model.ProviderConfig.ProviderType.OPENAI_COMPATIBLE
|
||||
import work.slhaf.partner.api.agent.model.provider.ModelProvider
|
||||
import work.slhaf.partner.api.agent.model.provider.ProviderOverride
|
||||
import work.slhaf.partner.api.agent.model.provider.openai.OpenAiCompatibleProvider
|
||||
@@ -9,6 +11,7 @@ import work.slhaf.partner.api.agent.runtime.config.ConfigDoc
|
||||
import work.slhaf.partner.api.agent.runtime.config.ConfigRegistration
|
||||
import work.slhaf.partner.api.agent.runtime.config.Configurable
|
||||
import java.nio.file.Path
|
||||
import java.util.Locale.getDefault
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
|
||||
@@ -62,17 +65,30 @@ object ModelRuntimeRegistry : Configurable, ConfigRegistration<ModelRuntimeRegis
|
||||
|
||||
override fun type(): Class<ModelRuntimeRegistryConfig> = ModelRuntimeRegistryConfig::class.java
|
||||
|
||||
override fun init(config: ModelRuntimeRegistryConfig) = providerLock.withLock {
|
||||
override fun init(config: ModelRuntimeRegistryConfig, json: JSONObject?) = providerLock.withLock {
|
||||
config.providerConfigSet.forEach { registerProvider(it) }
|
||||
config.runtimeConfigSet.forEach { forkProvider(it) }
|
||||
}
|
||||
|
||||
override fun onReload(config: ModelRuntimeRegistryConfig) = providerLock.withLock {
|
||||
override fun onReload(config: ModelRuntimeRegistryConfig, json: JSONObject?) = providerLock.withLock {
|
||||
val root = json ?: return@withLock
|
||||
val baseProviderSnapshot = baseProvider.toMap()
|
||||
val runtimeProviderSnapshot = runtimeProvider.toMap()
|
||||
try {
|
||||
val providerSetJson = root.getJSONArray("providerConfigSet")
|
||||
?: throw IllegalStateException("providerConfigSet is missing or not an array")
|
||||
baseProvider.clear()
|
||||
config.providerConfigSet.forEach { registerProvider(it) }
|
||||
for (i in providerSetJson.indices) {
|
||||
val providerJson = providerSetJson.getJSONObject(i)
|
||||
?: throw IllegalStateException("providerConfigSet[$i] is not an object")
|
||||
val typeText = providerJson.getString("type")
|
||||
?: throw IllegalStateException("providerConfigSet[$i].type is missing")
|
||||
val providerType = ProviderConfig.ProviderType.valueOf(typeText.uppercase(getDefault()))
|
||||
val concreteProviderConfig = when (providerType) {
|
||||
OPENAI_COMPATIBLE -> providerJson.toJavaObject(OpenAiCompatibleProviderConfig::class.java)
|
||||
}
|
||||
registerProvider(concreteProviderConfig)
|
||||
}
|
||||
runtimeProvider.clear()
|
||||
config.runtimeConfigSet.forEach { forkProvider(it) }
|
||||
} catch (e: Exception) {
|
||||
@@ -92,7 +108,7 @@ object ModelRuntimeRegistry : Configurable, ConfigRegistration<ModelRuntimeRegis
|
||||
setOf(
|
||||
OpenAiCompatibleProviderConfig(
|
||||
"default",
|
||||
ProviderConfig.ProviderType.OPENAI_COMPATIBLE,
|
||||
OPENAI_COMPATIBLE,
|
||||
defaultModel, defaultBaseUrl, defaultApiKey
|
||||
)
|
||||
), setOf()
|
||||
@@ -119,7 +135,7 @@ data class ModelRuntimeRegistryConfig(
|
||||
[
|
||||
{
|
||||
"modelKey": "example_model_key", // 模块通过该 key 定位到对应的提供商配置
|
||||
"providerName: "example_provider_name", // 该配置对应的提供商名称
|
||||
"providerName": "example_provider_name", // 该配置对应的提供商名称
|
||||
"override": { // 该配置需要重写的内容, 如果无需重写,可忽略该字段,该字段的各个子字段均为可选覆写
|
||||
"model": "example_override_model",
|
||||
"temperature": "example_override_temperature",
|
||||
@@ -156,7 +172,7 @@ sealed class ProviderConfig {
|
||||
|
||||
data class OpenAiCompatibleProviderConfig(
|
||||
override val name: String,
|
||||
override val type: ProviderType = ProviderType.OPENAI_COMPATIBLE,
|
||||
override val type: ProviderType = OPENAI_COMPATIBLE,
|
||||
override val defaultModel: String,
|
||||
|
||||
val baseUrl: String,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package work.slhaf.partner.api.agent.runtime.config
|
||||
|
||||
import com.alibaba.fastjson2.JSON
|
||||
import com.alibaba.fastjson2.JSONObject
|
||||
import org.slf4j.LoggerFactory
|
||||
import work.slhaf.partner.api.agent.runtime.exception.AgentLaunchFailedException
|
||||
import work.slhaf.partner.api.common.support.DirectoryWatchSupport
|
||||
@@ -82,14 +83,14 @@ object ConfigCenter : AutoCloseable {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun initAll() {
|
||||
registrations.forEach { (path, registration) ->
|
||||
val config = loadConfig(path, registration)
|
||||
if (config != null) {
|
||||
(registration as ConfigRegistration<Config>).init(config)
|
||||
val pair = loadConfig(path, registration)
|
||||
if (pair != null) {
|
||||
(registration as ConfigRegistration<Config>).init(pair.first, pair.second)
|
||||
return
|
||||
}
|
||||
val defaultConfig = registration.defaultConfig()
|
||||
if (defaultConfig != null) {
|
||||
(registration as ConfigRegistration<Config>).init(defaultConfig)
|
||||
(registration as ConfigRegistration<Config>).init(defaultConfig, null)
|
||||
}
|
||||
val configDoc = resolveConfigDoc(registration.type())
|
||||
throw AgentLaunchFailedException("Failed to init config, related path: $path, config definition: $configDoc")
|
||||
@@ -184,18 +185,20 @@ object ConfigCenter : AutoCloseable {
|
||||
val relativePath = toRelativeConfigPath(file) ?: return
|
||||
val registration = registrations[relativePath] ?: return
|
||||
try {
|
||||
val config = loadConfig(file, registration)
|
||||
if (config != null) {
|
||||
(registration as ConfigRegistration<Config>).onReload(config)
|
||||
val pair = loadConfig(file, registration)
|
||||
if (pair != null) {
|
||||
(registration as ConfigRegistration<Config>).onReload(pair.first, pair.second)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.error("Config reload failed: {}", relativePath, e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadConfig(file: Path, registration: ConfigRegistration<out Config>): Config? {
|
||||
private fun loadConfig(file: Path, registration: ConfigRegistration<out Config>): Pair<Config, JSONObject>? {
|
||||
return try {
|
||||
JSON.parseObject(Files.readString(file, StandardCharsets.UTF_8), registration.type()) as Config
|
||||
val json = JSON.parseObject(Files.readString(file, StandardCharsets.UTF_8))
|
||||
val config = json.toJavaObject(registration.type())
|
||||
config to json
|
||||
} catch (e: Exception) {
|
||||
log.error("Config reload failed: {}", file, e)
|
||||
null
|
||||
@@ -247,8 +250,8 @@ interface Configurable {
|
||||
|
||||
interface ConfigRegistration<T : Config> {
|
||||
fun type(): Class<T>
|
||||
fun init(config: T)
|
||||
fun onReload(config: T) {}
|
||||
fun init(config: T, json: JSONObject?)
|
||||
fun onReload(config: T, json: JSONObject?) {}
|
||||
fun defaultConfig(): T?
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user