Extend OllamaApiClient Timeout (Note)

พอดีช่วงนี้มีลอง Side Project ทำ Coding Review Agent โดยใช้ Local LLM ของผมใช้ตัว Ollama ตัว dotnet client ที่ใข้ OllamaSharp หรือยิง REST ตรงๆก็ได้ อันนี้ผมใช้ OllamaSharp เพราะมันใช้กับ Microsoft Agent Framework ได้เลยครับ เพราะตัว OllamaApiClient Implement Interface IChatClient ของ Microsoft.Extensions.AI แล้ว

ที่พอลองเล่นๆ ไปพบว่า Local LLM การทำงานจริงมันช้ามาก ผมใช้เครื่องเก่าด้วยมั่งไฟล์นึงใช้เวลา Review ประมาณ 20-30 นาที (Intel Gen8 / Qwen 3.5 4b) จะเจอ Error แนวๆนี้

Unhandled exception. System.Threading.Tasks.TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
 ---> System.TimeoutException: The operation was canceled.
 ---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.
 ---> System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..
 ---> System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request.
   --- End of inner exception stack trace ---
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource<System.Int32>.GetResult(Int16 token)
   at System.Net.Http.HttpConnection.InitialFillAsync(Boolean async)

ถ้าลองไปดูใน OllamaApiClient ใช้ HttpClient ซึ่งกำหนดค่า Default 100 Second (อ้างอิง HttpClient.Timeout) นี่แหละสาเหตุ

แต่ถ้าเราดู Code ของ OllamaApiClient มันยอมให้ Inject HttpClient มาได้นะ ดังนั้นเราสามารถมา Custom Timeout ได้ อย่าง Code ด้านล่างกำหนดไว้ 30 นาทีครับ

var httpClient = new HttpClient()
{
    Timeout = TimeSpan.FromMinutes(30),
    BaseAddress = uri
};

// Sample Use
var chatClient = new OllamaApiClient(httpClient) { SelectedModel = chatModel };
var embedClient = new OllamaApiClient(httpClient) { SelectedModel = embedModel };

หรือ ถ้าเอาแบบโหดสุดก็กำหนด Timeout.InfiniteTimeSpan

ผมว่า Solution นี้พอแล้ว แต่อีกอันลองเล่นและ ใช้ reflection มาช่วย

  • ข้อดีมัน Set ค่าตอน Run Time เลย
  • แต่ผมว่ามันเกิด Overhead เยอะ

Code ที่ผมทำวางโครงไว้ และให้ + Gemini ปรับมาให้่ อยู่ในนี้นะ sample การใช้ประมาณนี้

// Create Client with Extension
var client = new OllamaApiClient("http://localhost:11434", "mistral")
    .WithLongTimeout(); 

var customClient = new OllamaApiClient("http://localhost:11434", "codellama")
    .SetTimeout(TimeSpan.FromSeconds(30));

// ==========================================
var client = new OllamaApiClient("http://localhost:11434", "deepseek-coder");

client.WithQuickTimeout();    // 2 Minutes for small model
client.WithStandardTimeout(); // 5 Minutes for general 
client.WithLongTimeout();     // 10 Minutes for long task
client.WithExtendedTimeout(); // 30 Minutes for batch job

// ==========================================
// Check Current Timeout
var currentTimeout = client.GetTimeout();
Console.WriteLine($"Current timeout is: {currentTimeout?.TotalSeconds} seconds");

สรุป ถ้าต้องการทำจริงๆ ผมสร้าง inject httpClient ให้กับ OllamaApiClient ตาม use case ที่เราอยากได้เลย งานเร็ว งานช้า หรือ งานเป็น batch ครับ


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.