@@ -3693,6 +3693,7 @@ std::unique_ptr<server_res_generator> server_routes::handle_completions_impl(
36933693 auto res = create_response ();
36943694 auto completion_id = gen_chatcmplid ();
36953695 auto & rd = res->rd ;
3696+ auto & params = this ->params ;
36963697
36973698 try {
36983699 std::vector<server_task> tasks;
@@ -3828,7 +3829,7 @@ std::unique_ptr<server_res_generator> server_routes::handle_completions_impl(
38283829 }
38293830 res->status = 200 ;
38303831 res->content_type = " text/event-stream" ;
3831- res->next = [res_this = res.get (), res_type, &req](std::string & output) -> bool {
3832+ res->next = [res_this = res.get (), res_type, &req, ¶ms ](std::string & output) -> bool {
38323833 static auto format_error = [](task_response_type res_type, const json & res_json) {
38333834 if (res_type == TASK_RESPONSE_TYPE_ANTHROPIC ) {
38343835 return format_anthropic_sse ({
@@ -3873,7 +3874,25 @@ std::unique_ptr<server_res_generator> server_routes::handle_completions_impl(
38733874 }
38743875
38753876 // receive subsequent results
3876- auto result = rd.next (req.should_stop );
3877+ bool timeout = false ;
3878+ int64_t start_time = ggml_time_ms ();
3879+ auto result = rd.next ([&timeout, &req, &start_time, ¶ms]() {
3880+ if (req.should_stop ()) {
3881+ return true ; // should_stop condition met
3882+ } else if (params.sse_ping_interval > 0 && ggml_time_ms () - start_time > (int64_t )params.sse_ping_interval * 1000 ) {
3883+ timeout = true ;
3884+ return true ; // timeout
3885+ }
3886+ return false ;
3887+ });
3888+
3889+ if (timeout) {
3890+ // some clients may time out (e.g. undici) will time out if no data is received for a while, so we need to send a ping to keep the connection alive
3891+ SRV_DBG (" %s" , " sending SSE ping\n " );
3892+ output = " :\n\n " ;
3893+ return true ;
3894+ }
3895+
38773896 if (result == nullptr ) {
38783897 SRV_DBG (" %s" , " stopping streaming due to should_stop condition\n " );
38793898 GGML_ASSERT (req.should_stop ());
0 commit comments