邻二氮杂菲Add DeepSeek support (#23551)29bfb561 year agoHistory
363 lines · 12.9 KB · Rust
RawDownload
use std::sync::Arc; use anyhow::Result;use gpui::App;use language_model::LanguageModelCacheConfiguration;use project::Fs;use schemars::JsonSchema;use serde::{Deserialize, Serialize};use settings::{update_settings_file, Settings, SettingsSources}; use crate::provider::{    self,    anthropic::AnthropicSettings,    cloud::{self, ZedDotDevSettings},    copilot_chat::CopilotChatSettings,    deepseek::DeepSeekSettings,    google::GoogleSettings,    lmstudio::LmStudioSettings,    ollama::OllamaSettings,    open_ai::OpenAiSettings,}; /// Initializes the language model settings.pub fn init(fs: Arc<dyn Fs>, cx: &mut App) {    AllLanguageModelSettings::register(cx);     if AllLanguageModelSettings::get_global(cx)        .openai        .needs_setting_migration    {        update_settings_file::<AllLanguageModelSettings>(fs.clone(), cx, move |setting, _| {            if let Some(settings) = setting.openai.clone() {                let (newest_version, _) = settings.upgrade();                setting.openai = Some(OpenAiSettingsContent::Versioned(                    VersionedOpenAiSettingsContent::V1(newest_version),                ));            }        });    }     if AllLanguageModelSettings::get_global(cx)        .anthropic        .needs_setting_migration    {        update_settings_file::<AllLanguageModelSettings>(fs, cx, move |setting, _| {            if let Some(settings) = setting.anthropic.clone() {                let (newest_version, _) = settings.upgrade();                setting.anthropic = Some(AnthropicSettingsContent::Versioned(                    VersionedAnthropicSettingsContent::V1(newest_version),                ));            }        });    }} #[derive(Default)]pub struct AllLanguageModelSettings {    pub anthropic: AnthropicSettings,    pub ollama: OllamaSettings,    pub openai: OpenAiSettings,    pub zed_dot_dev: ZedDotDevSettings,    pub google: GoogleSettings,    pub copilot_chat: CopilotChatSettings,    pub lmstudio: LmStudioSettings,    pub deepseek: DeepSeekSettings,} #[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct AllLanguageModelSettingsContent {    pub anthropic: Option<AnthropicSettingsContent>,    pub ollama: Option<OllamaSettingsContent>,    pub lmstudio: Option<LmStudioSettingsContent>,    pub openai: Option<OpenAiSettingsContent>,    #[serde(rename = "zed.dev")]    pub zed_dot_dev: Option<ZedDotDevSettingsContent>,    pub google: Option<GoogleSettingsContent>,    pub deepseek: Option<DeepseekSettingsContent>,    pub copilot_chat: Option<CopilotChatSettingsContent>,} #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]#[serde(untagged)]pub enum AnthropicSettingsContent {    Legacy(LegacyAnthropicSettingsContent),    Versioned(VersionedAnthropicSettingsContent),} impl AnthropicSettingsContent {    pub fn upgrade(self) -> (AnthropicSettingsContentV1, bool) {        match self {            AnthropicSettingsContent::Legacy(content) => (                AnthropicSettingsContentV1 {                    api_url: content.api_url,                    available_models: content.available_models.map(|models| {                        models                            .into_iter()                            .filter_map(|model| match model {                                anthropic::Model::Custom {                                    name,                                    display_name,                                    max_tokens,                                    tool_override,                                    cache_configuration,                                    max_output_tokens,                                    default_temperature,                                    extra_beta_headers,                                } => Some(provider::anthropic::AvailableModel {                                    name,                                    display_name,                                    max_tokens,                                    tool_override,                                    cache_configuration: cache_configuration.as_ref().map(                                        |config| LanguageModelCacheConfiguration {                                            max_cache_anchors: config.max_cache_anchors,                                            should_speculate: config.should_speculate,                                            min_total_token: config.min_total_token,                                        },                                    ),                                    max_output_tokens,                                    default_temperature,                                    extra_beta_headers,                                }),                                _ => None,                            })                            .collect()                    }),                },                true,            ),            AnthropicSettingsContent::Versioned(content) => match content {                VersionedAnthropicSettingsContent::V1(content) => (content, false),            },        }    }} #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct LegacyAnthropicSettingsContent {    pub api_url: Option<String>,    pub available_models: Option<Vec<anthropic::Model>>,} #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]#[serde(tag = "version")]pub enum VersionedAnthropicSettingsContent {    #[serde(rename = "1")]    V1(AnthropicSettingsContentV1),} #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct AnthropicSettingsContentV1 {    pub api_url: Option<String>,    pub available_models: Option<Vec<provider::anthropic::AvailableModel>>,} #[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct OllamaSettingsContent {    pub api_url: Option<String>,    pub available_models: Option<Vec<provider::ollama::AvailableModel>>,} #[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct LmStudioSettingsContent {    pub api_url: Option<String>,    pub available_models: Option<Vec<provider::lmstudio::AvailableModel>>,} #[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct DeepseekSettingsContent {    pub api_url: Option<String>,    pub available_models: Option<Vec<provider::deepseek::AvailableModel>>,} #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]#[serde(untagged)]pub enum OpenAiSettingsContent {    Legacy(LegacyOpenAiSettingsContent),    Versioned(VersionedOpenAiSettingsContent),} impl OpenAiSettingsContent {    pub fn upgrade(self) -> (OpenAiSettingsContentV1, bool) {        match self {            OpenAiSettingsContent::Legacy(content) => (                OpenAiSettingsContentV1 {                    api_url: content.api_url,                    available_models: content.available_models.map(|models| {                        models                            .into_iter()                            .filter_map(|model| match model {                                open_ai::Model::Custom {                                    name,                                    display_name,                                    max_tokens,                                    max_output_tokens,                                    max_completion_tokens,                                } => Some(provider::open_ai::AvailableModel {                                    name,                                    max_tokens,                                    max_output_tokens,                                    display_name,                                    max_completion_tokens,                                }),                                _ => None,                            })                            .collect()                    }),                },                true,            ),            OpenAiSettingsContent::Versioned(content) => match content {                VersionedOpenAiSettingsContent::V1(content) => (content, false),            },        }    }} #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct LegacyOpenAiSettingsContent {    pub api_url: Option<String>,    pub available_models: Option<Vec<open_ai::Model>>,} #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]#[serde(tag = "version")]pub enum VersionedOpenAiSettingsContent {    #[serde(rename = "1")]    V1(OpenAiSettingsContentV1),} #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct OpenAiSettingsContentV1 {    pub api_url: Option<String>,    pub available_models: Option<Vec<provider::open_ai::AvailableModel>>,} #[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct GoogleSettingsContent {    pub api_url: Option<String>,    pub available_models: Option<Vec<provider::google::AvailableModel>>,} #[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct ZedDotDevSettingsContent {    available_models: Option<Vec<cloud::AvailableModel>>,} #[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]pub struct CopilotChatSettingsContent {} impl settings::Settings for AllLanguageModelSettings {    const KEY: Option<&'static str> = Some("language_models");     const PRESERVED_KEYS: Option<&'static [&'static str]> = Some(&["version"]);     type FileContent = AllLanguageModelSettingsContent;     fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {        fn merge<T>(target: &mut T, value: Option<T>) {            if let Some(value) = value {                *target = value;            }        }         let mut settings = AllLanguageModelSettings::default();         for value in sources.defaults_and_customizations() {            // Anthropic            let (anthropic, upgraded) = match value.anthropic.clone().map(|s| s.upgrade()) {                Some((content, upgraded)) => (Some(content), upgraded),                None => (None, false),            };             if upgraded {                settings.anthropic.needs_setting_migration = true;            }             merge(                &mut settings.anthropic.api_url,                anthropic.as_ref().and_then(|s| s.api_url.clone()),            );            merge(                &mut settings.anthropic.available_models,                anthropic.as_ref().and_then(|s| s.available_models.clone()),            );             // Ollama            let ollama = value.ollama.clone();             merge(                &mut settings.ollama.api_url,                value.ollama.as_ref().and_then(|s| s.api_url.clone()),            );            merge(                &mut settings.ollama.available_models,                ollama.as_ref().and_then(|s| s.available_models.clone()),            );             // LM Studio            let lmstudio = value.lmstudio.clone();             merge(                &mut settings.lmstudio.api_url,                value.lmstudio.as_ref().and_then(|s| s.api_url.clone()),            );            merge(                &mut settings.lmstudio.available_models,                lmstudio.as_ref().and_then(|s| s.available_models.clone()),            );             // DeepSeek            let deepseek = value.deepseek.clone();             merge(                &mut settings.deepseek.api_url,                value.deepseek.as_ref().and_then(|s| s.api_url.clone()),            );            merge(                &mut settings.deepseek.available_models,                deepseek.as_ref().and_then(|s| s.available_models.clone()),            );             // OpenAI            let (openai, upgraded) = match value.openai.clone().map(|s| s.upgrade()) {                Some((content, upgraded)) => (Some(content), upgraded),                None => (None, false),            };             if upgraded {                settings.openai.needs_setting_migration = true;            }             merge(                &mut settings.openai.api_url,                openai.as_ref().and_then(|s| s.api_url.clone()),            );            merge(                &mut settings.openai.available_models,                openai.as_ref().and_then(|s| s.available_models.clone()),            );            merge(                &mut settings.zed_dot_dev.available_models,                value                    .zed_dot_dev                    .as_ref()                    .and_then(|s| s.available_models.clone()),            );            merge(                &mut settings.google.api_url,                value.google.as_ref().and_then(|s| s.api_url.clone()),            );            merge(                &mut settings.google.available_models,                value                    .google                    .as_ref()                    .and_then(|s| s.available_models.clone()),            );        }         Ok(settings)    }}