//! 独立诊断:用 df-ai 真实调用 GLM anthropic 流式端点,验证 //! sse_parser + apply_anthropic_event + provider.stream() 整条链路。 //! //! 二分定位「发消息卡掉」: 若本例能正常吐 chunk → provider 层(df-ai)OK, //! 问题在 devflow 应用层(provider 配置/emit/前端); 若卡/空/Err → df-ai 有 bug。 //! //! 运行: cd crates/df-ai && cargo run --example glm_stream_test use df_ai::build_provider; use df_ai_core::CompletionRequest; use futures::StreamExt; #[tokio::main] async fn main() { let token = std::env::var("ANTHROPIC_AUTH_TOKEN") .or_else(|_| std::env::var("ANTHROPIC_API_KEY")) .expect("需要环境变量 ANTHROPIC_AUTH_TOKEN"); eprintln!("[glm-test] token len={}", token.len()); let provider = build_provider( "anthropic", "https://open.bigmodel.cn/api/anthropic", &token, "glm-5.2", ); // 用 JSON 反序列化构造请求,绕开字段列表(devflow 实际用 glm-5.2) let req: CompletionRequest = serde_json::from_str( r#"{"model":"glm-5.2","stream":true,"max_tokens":16,"messages":[{"role":"user","content":"说你好"}]}"#, ) .expect("parse CompletionRequest"); eprintln!("[glm-test] 调用 provider.stream() ..."); let t0 = std::time::Instant::now(); let mut s = match provider.stream(req).await { Ok(s) => { eprintln!("[glm-test] stream() Ok, 建连耗时 {:?}", t0.elapsed()); s } Err(e) => { eprintln!("[glm-test] stream() Err: {:#}", e); return; } }; let mut n = 0; let mut got_text = false; while let Some(chunk_result) = s.next().await { n += 1; match chunk_result { Ok(chunk) => { if !chunk.delta.is_empty() { got_text = true; } eprintln!( "[glm-test] chunk#{} delta={:?} reasoning={:?} finished={} usage={:?} err={:?}", n, chunk.delta, chunk.reasoning_content.as_deref().map(|s| if s.len() > 30 { format!("{}..", &s[..30]) } else { s.to_string() }), chunk.finished, chunk.usage, chunk.error ); } Err(e) => { eprintln!("[glm-test] chunk#{} Err: {}", n, e); } } if n > 60 { eprintln!("[glm-test] 超 60 chunk 截断"); break; } } eprintln!( "[glm-test] 流结束 共 {} chunk, 是否拿到文本={}, 总耗时 {:?}", n, got_text, t0.elapsed() ); }