diff --git a/rig/rig-core/tests/deepseek/agent.rs b/rig/rig-core/tests/deepseek/agent.rs index 2c808582a..0990d55ac 100644 --- a/rig/rig-core/tests/deepseek/agent.rs +++ b/rig/rig-core/tests/deepseek/agent.rs @@ -11,7 +11,7 @@ use crate::support::{BASIC_PREAMBLE, BASIC_PROMPT, assert_nonempty_response}; async fn completion_smoke() { let client = deepseek::Client::from_env().expect("client should build"); let agent = client - .agent(deepseek::DEEPSEEK_CHAT) + .agent(deepseek::DEEPSEEK_V4_FLASH) .preamble(BASIC_PREAMBLE) .build(); diff --git a/rig/rig-core/tests/deepseek/extractor.rs b/rig/rig-core/tests/deepseek/extractor.rs index 1549c765a..abc79888c 100644 --- a/rig/rig-core/tests/deepseek/extractor.rs +++ b/rig/rig-core/tests/deepseek/extractor.rs @@ -10,7 +10,7 @@ use crate::support::{EXTRACTOR_TEXT, SmokePerson, assert_nonempty_response}; async fn extractor_smoke() { let client = deepseek::Client::from_env().expect("client should build"); let extractor = client - .extractor::(deepseek::DEEPSEEK_CHAT) + .extractor::(deepseek::DEEPSEEK_V4_FLASH) .build(); let person = extractor diff --git a/rig/rig-core/tests/deepseek/extractor_usage.rs b/rig/rig-core/tests/deepseek/extractor_usage.rs index b2a0c4fd8..6cbbaa9c6 100644 --- a/rig/rig-core/tests/deepseek/extractor_usage.rs +++ b/rig/rig-core/tests/deepseek/extractor_usage.rs @@ -41,7 +41,9 @@ fn assert_compatible_professions(left: Option<&str>, right: &str) -> Result<()> #[ignore = "requires DEEPSEEK_API_KEY"] async fn extract_backward_compatibility() -> Result<()> { let client = deepseek::Client::from_env().expect("client should build"); - let extractor = client.extractor::(deepseek::DEEPSEEK_CHAT).build(); + let extractor = client + .extractor::(deepseek::DEEPSEEK_V4_FLASH) + .build(); let person = extractor .extract("John Doe is a 30 year old software engineer.") @@ -66,7 +68,9 @@ async fn extract_backward_compatibility() -> Result<()> { #[ignore = "requires DEEPSEEK_API_KEY"] async fn extract_with_usage_returns_data_and_usage() -> Result<()> { let client = deepseek::Client::from_env().expect("client should build"); - let extractor = client.extractor::(deepseek::DEEPSEEK_CHAT).build(); + let extractor = client + .extractor::(deepseek::DEEPSEEK_V4_FLASH) + .build(); let response: ExtractionResponse = extractor .extract_with_usage("Jane Smith is a 45 year old data scientist.") @@ -94,7 +98,9 @@ async fn extract_with_usage_returns_data_and_usage() -> Result<()> { #[ignore = "requires DEEPSEEK_API_KEY"] async fn extract_with_chat_history_with_usage_works() -> Result<()> { let client = deepseek::Client::from_env().expect("client should build"); - let extractor = client.extractor::
(deepseek::DEEPSEEK_CHAT).build(); + let extractor = client + .extractor::
(deepseek::DEEPSEEK_V4_FLASH) + .build(); let chat_history = vec![Message::user( "I'm looking at a property that might be interesting.", @@ -137,7 +143,9 @@ async fn extract_with_chat_history_with_usage_works() -> Result<()> { #[ignore = "requires DEEPSEEK_API_KEY"] async fn extract_and_extract_with_usage_return_same_data() -> Result<()> { let client = deepseek::Client::from_env().expect("client should build"); - let extractor = client.extractor::(deepseek::DEEPSEEK_CHAT).build(); + let extractor = client + .extractor::(deepseek::DEEPSEEK_V4_FLASH) + .build(); let text = "Bob Johnson is a 55 year old retired teacher."; let person = extractor.extract(text).await?; @@ -175,7 +183,9 @@ async fn extract_and_extract_with_usage_return_same_data() -> Result<()> { async fn usage_tracking_works_for_different_schemas() -> Result<()> { let client = deepseek::Client::from_env().expect("client should build"); - let person_extractor = client.extractor::(deepseek::DEEPSEEK_CHAT).build(); + let person_extractor = client + .extractor::(deepseek::DEEPSEEK_V4_FLASH) + .build(); let person_response = person_extractor .extract_with_usage("Alice is a 25 year old developer.") .await?; @@ -184,7 +194,9 @@ async fn usage_tracking_works_for_different_schemas() -> Result<()> { "expected person usage tokens" ); - let address_extractor = client.extractor::
(deepseek::DEEPSEEK_CHAT).build(); + let address_extractor = client + .extractor::
(deepseek::DEEPSEEK_V4_FLASH) + .build(); let address_response = address_extractor .extract_with_usage("456 Oak Avenue, Cambridge, MA 02139") .await?; diff --git a/rig/rig-core/tests/deepseek/mod.rs b/rig/rig-core/tests/deepseek/mod.rs index f73aa70a1..5d2a2053c 100644 --- a/rig/rig-core/tests/deepseek/mod.rs +++ b/rig/rig-core/tests/deepseek/mod.rs @@ -1,6 +1,7 @@ mod agent; mod extractor; mod extractor_usage; +mod models; mod multi_extract; mod permission_control; mod reasoning_roundtrip; diff --git a/rig/rig-core/tests/deepseek/models.rs b/rig/rig-core/tests/deepseek/models.rs new file mode 100644 index 000000000..05c5b7039 --- /dev/null +++ b/rig/rig-core/tests/deepseek/models.rs @@ -0,0 +1,33 @@ +//! DeepSeek model listing smoke test. +//! +//! Run with: +//! `cargo test -p rig-core --test deepseek deepseek::models::list_models_smoke -- --ignored --nocapture` + +use rig::client::{ModelListingClient, ProviderClient}; +use rig::providers::deepseek; + +#[tokio::test] +#[ignore = "requires DEEPSEEK_API_KEY"] +async fn list_models_smoke() { + let client = deepseek::Client::from_env().expect("client should build"); + let models = match client.list_models().await { + Ok(models) => models, + Err(error) => { + panic!("listing DeepSeek models should succeed\nDisplay: {error}\nDebug: {error:#?}") + } + }; + + assert!( + !models.is_empty(), + "expected DeepSeek to return at least one model\nModel list: {models:#?}" + ); + + assert!( + models + .iter() + .any(|model| model.owned_by.as_deref() == Some("deepseek")), + "expected at least one DeepSeek-owned model\nModel list: {models:#?}" + ); + + println!("DeepSeek returned {} models", models.len()); +} diff --git a/rig/rig-core/tests/deepseek/multi_extract.rs b/rig/rig-core/tests/deepseek/multi_extract.rs index 4e0db7ce5..c2e947483 100644 --- a/rig/rig-core/tests/deepseek/multi_extract.rs +++ b/rig/rig-core/tests/deepseek/multi_extract.rs @@ -31,17 +31,17 @@ struct Sentiment { async fn batch_multi_extract_chain() -> Result<()> { let client = deepseek::Client::from_env().expect("client should build"); let names_extractor = client - .extractor::(deepseek::DEEPSEEK_CHAT) + .extractor::(deepseek::DEEPSEEK_V4_FLASH) .preamble("Extract names from the given text.") .retries(2) .build(); let topics_extractor = client - .extractor::(deepseek::DEEPSEEK_CHAT) + .extractor::(deepseek::DEEPSEEK_V4_FLASH) .preamble("Extract topics from the given text.") .retries(2) .build(); let sentiment_extractor = client - .extractor::(deepseek::DEEPSEEK_CHAT) + .extractor::(deepseek::DEEPSEEK_V4_FLASH) .preamble("Extract sentiment and confidence from the given text.") .retries(2) .build(); diff --git a/rig/rig-core/tests/deepseek/permission_control.rs b/rig/rig-core/tests/deepseek/permission_control.rs index b83f9f84e..49defe33c 100644 --- a/rig/rig-core/tests/deepseek/permission_control.rs +++ b/rig/rig-core/tests/deepseek/permission_control.rs @@ -155,7 +155,7 @@ async fn permission_control_prompt_example() -> Result<()> { let agent = deepseek::Client::from_env() .expect("client should build") - .agent(deepseek::DEEPSEEK_CHAT) + .agent(deepseek::DEEPSEEK_V4_FLASH) .preamble("You are a helpful assistant that can read files using different methods.") .tool(ReadFileHead) .tool(ReadFileTail) @@ -197,7 +197,7 @@ async fn permission_control_streaming_example() -> Result<()> { let agent = deepseek::Client::from_env() .expect("client should build") - .agent(deepseek::DEEPSEEK_CHAT) + .agent(deepseek::DEEPSEEK_V4_FLASH) .preamble("You are a helpful assistant that can read files using different methods.") .tool(ReadFileHead) .tool(ReadFileTail) diff --git a/rig/rig-core/tests/deepseek/reasoning_roundtrip.rs b/rig/rig-core/tests/deepseek/reasoning_roundtrip.rs index c4c239c63..bff1d8893 100644 --- a/rig/rig-core/tests/deepseek/reasoning_roundtrip.rs +++ b/rig/rig-core/tests/deepseek/reasoning_roundtrip.rs @@ -5,13 +5,19 @@ use rig::providers::deepseek; use crate::reasoning::{self, ReasoningRoundtripAgent}; +fn thinking_params() -> serde_json::Value { + serde_json::json!({ + "thinking": { "type": "enabled" } + }) +} + #[tokio::test] #[ignore = "requires DEEPSEEK_API_KEY"] async fn streaming() { let client = deepseek::Client::from_env().expect("client should build"); reasoning::run_reasoning_roundtrip_streaming(ReasoningRoundtripAgent::new( - client.completion_model(deepseek::DEEPSEEK_REASONER), - None, + client.completion_model(deepseek::DEEPSEEK_V4_FLASH), + Some(thinking_params()), )) .await; } @@ -21,8 +27,8 @@ async fn streaming() { async fn nonstreaming() { let client = deepseek::Client::from_env().expect("client should build"); reasoning::run_reasoning_roundtrip_nonstreaming(ReasoningRoundtripAgent::new( - client.completion_model(deepseek::DEEPSEEK_REASONER), - None, + client.completion_model(deepseek::DEEPSEEK_V4_FLASH), + Some(thinking_params()), )) .await; } diff --git a/rig/rig-core/tests/deepseek/reasoning_tool_roundtrip.rs b/rig/rig-core/tests/deepseek/reasoning_tool_roundtrip.rs index 88c26df1a..c2ea94dcd 100644 --- a/rig/rig-core/tests/deepseek/reasoning_tool_roundtrip.rs +++ b/rig/rig-core/tests/deepseek/reasoning_tool_roundtrip.rs @@ -10,16 +10,23 @@ use rig::streaming::StreamingChat; use crate::reasoning::{self, WeatherTool}; +fn thinking_params() -> serde_json::Value { + serde_json::json!({ + "thinking": { "type": "enabled" } + }) +} + #[tokio::test] #[ignore = "requires DEEPSEEK_API_KEY"] async fn streaming() { let call_count = Arc::new(AtomicUsize::new(0)); let client = deepseek::Client::from_env().expect("client should build"); let agent = client - .agent(deepseek::DEEPSEEK_REASONER) + .agent(deepseek::DEEPSEEK_V4_FLASH) .preamble(reasoning::TOOL_SYSTEM_PROMPT) .max_tokens(4096) .tool(WeatherTool::new(call_count.clone())) + .additional_params(thinking_params()) .build(); let stream = agent @@ -45,10 +52,11 @@ async fn nonstreaming() { let call_count = Arc::new(AtomicUsize::new(0)); let client = deepseek::Client::from_env().expect("client should build"); let agent = client - .agent(deepseek::DEEPSEEK_REASONER) + .agent(deepseek::DEEPSEEK_V4_FLASH) .preamble(reasoning::TOOL_SYSTEM_PROMPT) .max_tokens(4096) .tool(WeatherTool::new(call_count.clone())) + .additional_params(thinking_params()) .build(); let result = agent diff --git a/rig/rig-core/tests/deepseek/request_hook.rs b/rig/rig-core/tests/deepseek/request_hook.rs index 8e1e080d7..2dd356120 100644 --- a/rig/rig-core/tests/deepseek/request_hook.rs +++ b/rig/rig-core/tests/deepseek/request_hook.rs @@ -70,7 +70,7 @@ where async fn request_hook_records_prompt_and_response() -> Result<()> { let agent = deepseek::Client::from_env() .expect("client should build") - .agent(deepseek::DEEPSEEK_CHAT) + .agent(deepseek::DEEPSEEK_V4_FLASH) .preamble("You are a comedian here to entertain the user using humour and jokes.") .build(); diff --git a/rig/rig-core/tests/deepseek/streaming.rs b/rig/rig-core/tests/deepseek/streaming.rs index 1a7db9b25..8ef14c681 100644 --- a/rig/rig-core/tests/deepseek/streaming.rs +++ b/rig/rig-core/tests/deepseek/streaming.rs @@ -1,7 +1,7 @@ //! DeepSeek streaming smoke test. use rig::client::{CompletionClient, ProviderClient}; -use rig::providers::deepseek::{self, DEEPSEEK_CHAT}; +use rig::providers::deepseek::{self, DEEPSEEK_V4_FLASH}; use rig::streaming::StreamingPrompt; use crate::support::{assert_nonempty_response, collect_stream_final_response}; @@ -11,7 +11,7 @@ use crate::support::{assert_nonempty_response, collect_stream_final_response}; async fn streaming_prompt_smoke() { let client = deepseek::Client::from_env().expect("client should build"); let agent = client - .agent(DEEPSEEK_CHAT) + .agent(DEEPSEEK_V4_FLASH) .preamble("You are a helpful assistant.") .build(); diff --git a/rig/rig-core/tests/deepseek/streaming_tools.rs b/rig/rig-core/tests/deepseek/streaming_tools.rs index 5f6954db0..d212ab331 100644 --- a/rig/rig-core/tests/deepseek/streaming_tools.rs +++ b/rig/rig-core/tests/deepseek/streaming_tools.rs @@ -4,7 +4,7 @@ use rig::OneOrMany; use rig::client::{CompletionClient, ProviderClient}; use rig::completion::CompletionModel; use rig::message::{AssistantContent, Message, ToolChoice}; -use rig::providers::deepseek::{self, DEEPSEEK_CHAT}; +use rig::providers::deepseek::{self, DEEPSEEK_V4_FLASH}; use rig::streaming::StreamingChat; use rig::tool::Tool; @@ -19,16 +19,23 @@ use crate::support::{ zero_arg_tool_definition, }; +fn non_thinking_params() -> serde_json::Value { + serde_json::json!({ + "thinking": { "type": "disabled" } + }) +} + #[tokio::test] #[ignore = "requires DEEPSEEK_API_KEY"] async fn streaming_chat_with_tools() { let client = deepseek::Client::from_env().expect("client should build"); let agent = client - .agent(DEEPSEEK_CHAT) + .agent(DEEPSEEK_V4_FLASH) .preamble("You are a calculator here to help the user perform arithmetic operations.") .max_tokens(1024) .tool(Adder) .tool(Subtract) + .additional_params(non_thinking_params()) .build(); let history: &[Message] = &[]; @@ -44,11 +51,12 @@ async fn streaming_chat_with_tools() { #[ignore = "requires DEEPSEEK_API_KEY"] async fn raw_stream_emits_required_zero_arg_tool_call() { let client = deepseek::Client::from_env().expect("client should build"); - let model = client.completion_model(DEEPSEEK_CHAT); + let model = client.completion_model(DEEPSEEK_V4_FLASH); let request = model .completion_request(REQUIRED_ZERO_ARG_TOOL_PROMPT) .tool(zero_arg_tool_definition("ping")) .tool_choice(ToolChoice::Required) + .additional_params(non_thinking_params()) .build(); let stream = model.stream(request).await.expect("stream should start"); @@ -59,12 +67,13 @@ async fn raw_stream_emits_required_zero_arg_tool_call() { #[ignore = "requires DEEPSEEK_API_KEY"] async fn raw_stream_surfaces_two_distinct_tool_calls_before_text() { let client = deepseek::Client::from_env().expect("client should build"); - let model = client.completion_model(DEEPSEEK_CHAT); + let model = client.completion_model(DEEPSEEK_V4_FLASH); let request = model .completion_request(TWO_TOOL_STREAM_PROMPT) .preamble(TWO_TOOL_STREAM_PREAMBLE.to_string()) .tool(AlphaSignal.definition(String::new()).await) .tool(BetaSignal.definition(String::new()).await) + .additional_params(non_thinking_params()) .build(); let observation = collect_raw_stream_observation( @@ -86,10 +95,11 @@ async fn raw_stream_surfaces_two_distinct_tool_calls_before_text() { async fn streaming_chat_surfaces_two_distinct_tool_calls_before_final_answer() { let client = deepseek::Client::from_env().expect("client should build"); let agent = client - .agent(DEEPSEEK_CHAT) + .agent(DEEPSEEK_V4_FLASH) .preamble(TWO_TOOL_STREAM_PREAMBLE) .tool(AlphaSignal) .tool(BetaSignal) + .additional_params(non_thinking_params()) .build(); let history: &[Message] = &[]; @@ -111,9 +121,10 @@ async fn streaming_chat_surfaces_two_distinct_tool_calls_before_final_answer() { async fn streaming_chat_emits_tool_call_before_later_text() { let client = deepseek::Client::from_env().expect("client should build"); let agent = client - .agent(DEEPSEEK_CHAT) + .agent(DEEPSEEK_V4_FLASH) .preamble(ORDERED_TOOL_STREAM_PREAMBLE) .tool(AlphaSignal) + .additional_params(non_thinking_params()) .build(); let history: &[Message] = &[]; @@ -134,11 +145,12 @@ async fn streaming_chat_emits_tool_call_before_later_text() { #[ignore = "requires DEEPSEEK_API_KEY"] async fn raw_followup_uses_tool_result_without_new_tool_calls() { let client = deepseek::Client::from_env().expect("client should build"); - let model = client.completion_model(DEEPSEEK_CHAT); + let model = client.completion_model(DEEPSEEK_V4_FLASH); let request = model .completion_request(ORDERED_TOOL_STREAM_PROMPT) .preamble(ORDERED_TOOL_STREAM_PREAMBLE.to_string()) .tool(AlphaSignal.definition(String::new()).await) + .additional_params(non_thinking_params()) .build(); let first_turn = collect_raw_stream_observation( @@ -170,6 +182,7 @@ async fn raw_followup_uses_tool_result_without_new_tool_calls() { .preamble("Use the provided tool result and answer directly.".to_string()) .message(assistant_message) .message(tool_result_message) + .additional_params(non_thinking_params()) .build(); let second_turn = collect_raw_stream_observation( diff --git a/rig/rig-core/tests/deepseek/tools.rs b/rig/rig-core/tests/deepseek/tools.rs index 5e94eb3dc..18fbd8d1d 100644 --- a/rig/rig-core/tests/deepseek/tools.rs +++ b/rig/rig-core/tests/deepseek/tools.rs @@ -13,7 +13,7 @@ use crate::support::{ async fn tools_smoke() { let client = deepseek::Client::from_env().expect("client should build"); let agent = client - .agent(deepseek::DEEPSEEK_CHAT) + .agent(deepseek::DEEPSEEK_V4_FLASH) .preamble(TOOLS_PREAMBLE) .tool(Adder) .tool(Subtract)