mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
refactor: 大规模模块拆分与代码精简,新增 ai-pipeline/data-contracts 独立 crate
- 新增 aether-ai-pipeline 和 aether-data-contracts crate,将 pipeline 逻辑与数据契约从 gateway 中解耦 - 重构 admin handlers:拆分单体模块为 auth/billing/endpoint/features/model/observability/provider/system 等独立子模块 - 合并 chat/cli 重复代码路径:精简 conversion、finalize、planner 中的 sync/chat/cli 分支 - 重构 scheduler/executor/data 层,引入 facade 模式降低模块间耦合 - 移除冗余的 intent 模块,将 plan_fallback/policy/stream_path/sync_path 迁移至 executor - 前端适配:调整 admin API 调用和 provider 模型测试对话框
This commit is contained in:
@@ -3,7 +3,7 @@ use std::sync::RwLock;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use super::types::{BillingReadRepository, StoredBillingModelContext};
|
||||
use super::{BillingReadRepository, StoredBillingModelContext};
|
||||
use crate::DataLayerError;
|
||||
|
||||
type BillingContextKey = (String, String, Option<String>);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
mod memory;
|
||||
mod sql;
|
||||
mod types;
|
||||
|
||||
pub use memory::InMemoryBillingReadRepository;
|
||||
pub use sql::SqlxBillingReadRepository;
|
||||
pub use types::{
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use aether_data_contracts::repository::billing::{
|
||||
AdminBillingCollectorRecord, AdminBillingCollectorWriteInput, AdminBillingPresetApplyResult,
|
||||
AdminBillingRuleRecord, AdminBillingRuleWriteInput, BillingReadRepository,
|
||||
StoredBillingModelContext,
|
||||
};
|
||||
pub use memory::InMemoryBillingReadRepository;
|
||||
pub use sql::SqlxBillingReadRepository;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use async_trait::async_trait;
|
||||
use sqlx::{PgPool, Row};
|
||||
|
||||
use super::types::{BillingReadRepository, StoredBillingModelContext};
|
||||
use crate::DataLayerError;
|
||||
use super::{BillingReadRepository, StoredBillingModelContext};
|
||||
use crate::{error::SqlxResultExt, DataLayerError};
|
||||
|
||||
const FIND_MODEL_CONTEXT_SQL: &str = r#"
|
||||
SELECT
|
||||
@@ -58,7 +58,8 @@ impl SqlxBillingReadRepository {
|
||||
.bind(global_model_name)
|
||||
.bind(provider_api_key_id)
|
||||
.fetch_optional(&self.pool)
|
||||
.await?;
|
||||
.await
|
||||
.map_postgres_err()?;
|
||||
row.as_ref().map(map_row).transpose()
|
||||
}
|
||||
}
|
||||
@@ -77,22 +78,26 @@ impl BillingReadRepository for SqlxBillingReadRepository {
|
||||
|
||||
fn map_row(row: &sqlx::postgres::PgRow) -> Result<StoredBillingModelContext, DataLayerError> {
|
||||
StoredBillingModelContext::new(
|
||||
row.try_get("provider_id")?,
|
||||
row.try_get("provider_billing_type")?,
|
||||
row.try_get("provider_api_key_id")?,
|
||||
row.try_get("provider_api_key_rate_multipliers")?,
|
||||
row.try_get::<Option<i32>, _>("provider_api_key_cache_ttl_minutes")?
|
||||
row.try_get("provider_id").map_postgres_err()?,
|
||||
row.try_get("provider_billing_type").map_postgres_err()?,
|
||||
row.try_get("provider_api_key_id").map_postgres_err()?,
|
||||
row.try_get("provider_api_key_rate_multipliers")
|
||||
.map_postgres_err()?,
|
||||
row.try_get::<Option<i32>, _>("provider_api_key_cache_ttl_minutes")
|
||||
.map_postgres_err()?
|
||||
.map(i64::from),
|
||||
row.try_get("global_model_id")?,
|
||||
row.try_get("global_model_name")?,
|
||||
row.try_get("global_model_config")?,
|
||||
row.try_get("default_price_per_request")?,
|
||||
row.try_get("default_tiered_pricing")?,
|
||||
row.try_get("model_id")?,
|
||||
row.try_get("model_provider_model_name")?,
|
||||
row.try_get("model_config")?,
|
||||
row.try_get("model_price_per_request")?,
|
||||
row.try_get("model_tiered_pricing")?,
|
||||
row.try_get("global_model_id").map_postgres_err()?,
|
||||
row.try_get("global_model_name").map_postgres_err()?,
|
||||
row.try_get("global_model_config").map_postgres_err()?,
|
||||
row.try_get("default_price_per_request")
|
||||
.map_postgres_err()?,
|
||||
row.try_get("default_tiered_pricing").map_postgres_err()?,
|
||||
row.try_get("model_id").map_postgres_err()?,
|
||||
row.try_get("model_provider_model_name")
|
||||
.map_postgres_err()?,
|
||||
row.try_get("model_config").map_postgres_err()?,
|
||||
row.try_get("model_price_per_request").map_postgres_err()?,
|
||||
row.try_get("model_tiered_pricing").map_postgres_err()?,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
use async_trait::async_trait;
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct StoredBillingModelContext {
|
||||
pub provider_id: String,
|
||||
pub provider_billing_type: Option<String>,
|
||||
pub provider_api_key_id: Option<String>,
|
||||
pub provider_api_key_rate_multipliers: Option<Value>,
|
||||
pub provider_api_key_cache_ttl_minutes: Option<i64>,
|
||||
pub global_model_id: String,
|
||||
pub global_model_name: String,
|
||||
pub global_model_config: Option<Value>,
|
||||
pub default_price_per_request: Option<f64>,
|
||||
pub default_tiered_pricing: Option<Value>,
|
||||
pub model_id: Option<String>,
|
||||
pub model_provider_model_name: Option<String>,
|
||||
pub model_config: Option<Value>,
|
||||
pub model_price_per_request: Option<f64>,
|
||||
pub model_tiered_pricing: Option<Value>,
|
||||
}
|
||||
|
||||
impl StoredBillingModelContext {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
provider_id: String,
|
||||
provider_billing_type: Option<String>,
|
||||
provider_api_key_id: Option<String>,
|
||||
provider_api_key_rate_multipliers: Option<Value>,
|
||||
provider_api_key_cache_ttl_minutes: Option<i64>,
|
||||
global_model_id: String,
|
||||
global_model_name: String,
|
||||
global_model_config: Option<Value>,
|
||||
default_price_per_request: Option<f64>,
|
||||
default_tiered_pricing: Option<Value>,
|
||||
model_id: Option<String>,
|
||||
model_provider_model_name: Option<String>,
|
||||
model_config: Option<Value>,
|
||||
model_price_per_request: Option<f64>,
|
||||
model_tiered_pricing: Option<Value>,
|
||||
) -> Result<Self, crate::DataLayerError> {
|
||||
if provider_id.trim().is_empty() {
|
||||
return Err(crate::DataLayerError::UnexpectedValue(
|
||||
"billing.provider_id is empty".to_string(),
|
||||
));
|
||||
}
|
||||
if global_model_id.trim().is_empty() {
|
||||
return Err(crate::DataLayerError::UnexpectedValue(
|
||||
"billing.global_model_id is empty".to_string(),
|
||||
));
|
||||
}
|
||||
if global_model_name.trim().is_empty() {
|
||||
return Err(crate::DataLayerError::UnexpectedValue(
|
||||
"billing.global_model_name is empty".to_string(),
|
||||
));
|
||||
}
|
||||
Ok(Self {
|
||||
provider_id,
|
||||
provider_billing_type,
|
||||
provider_api_key_id,
|
||||
provider_api_key_rate_multipliers,
|
||||
provider_api_key_cache_ttl_minutes,
|
||||
global_model_id,
|
||||
global_model_name,
|
||||
global_model_config,
|
||||
default_price_per_request,
|
||||
default_tiered_pricing,
|
||||
model_id,
|
||||
model_provider_model_name,
|
||||
model_config,
|
||||
model_price_per_request,
|
||||
model_tiered_pricing,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct AdminBillingRuleRecord {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub task_type: String,
|
||||
pub global_model_id: Option<String>,
|
||||
pub model_id: Option<String>,
|
||||
pub expression: String,
|
||||
pub variables: Value,
|
||||
pub dimension_mappings: Value,
|
||||
pub is_enabled: bool,
|
||||
pub created_at_unix_secs: u64,
|
||||
pub updated_at_unix_secs: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct AdminBillingRuleWriteInput {
|
||||
pub name: String,
|
||||
pub task_type: String,
|
||||
pub global_model_id: Option<String>,
|
||||
pub model_id: Option<String>,
|
||||
pub expression: String,
|
||||
pub variables: Value,
|
||||
pub dimension_mappings: Value,
|
||||
pub is_enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct AdminBillingCollectorRecord {
|
||||
pub id: String,
|
||||
pub api_format: String,
|
||||
pub task_type: String,
|
||||
pub dimension_name: String,
|
||||
pub source_type: String,
|
||||
pub source_path: Option<String>,
|
||||
pub value_type: String,
|
||||
pub transform_expression: Option<String>,
|
||||
pub default_value: Option<String>,
|
||||
pub priority: i32,
|
||||
pub is_enabled: bool,
|
||||
pub created_at_unix_secs: u64,
|
||||
pub updated_at_unix_secs: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct AdminBillingCollectorWriteInput {
|
||||
pub api_format: String,
|
||||
pub task_type: String,
|
||||
pub dimension_name: String,
|
||||
pub source_type: String,
|
||||
pub source_path: Option<String>,
|
||||
pub value_type: String,
|
||||
pub transform_expression: Option<String>,
|
||||
pub default_value: Option<String>,
|
||||
pub priority: i32,
|
||||
pub is_enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct AdminBillingPresetApplyResult {
|
||||
pub preset: String,
|
||||
pub mode: String,
|
||||
pub created: u64,
|
||||
pub updated: u64,
|
||||
pub skipped: u64,
|
||||
pub errors: Vec<String>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait BillingReadRepository: Send + Sync {
|
||||
async fn find_model_context(
|
||||
&self,
|
||||
provider_id: &str,
|
||||
provider_api_key_id: Option<&str>,
|
||||
global_model_name: &str,
|
||||
) -> Result<Option<StoredBillingModelContext>, crate::DataLayerError>;
|
||||
}
|
||||
Reference in New Issue
Block a user