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