Class ::nsmcp::ChatCompletionsBackend (public)
::nx::Class ::nsmcp::ChatCompletionsBackend
Defined in /usr/local/ns/tcl/nsmcp/question-chat-completions.tcl
- Testcases:
- No testcase defined.
Source code: :property apiUrl:required :property apiKeyFile:required :property tokenFile:required :property model:required :property {registry ::nsmcp::tools} :property {authenticator ::nsmcp::auth} :property {authorizer ::nsmcp::authorization} :property {apiOptions {{} object {}}} :property {timeout 180} :property {maxResultBytes 131072} :property {maxHistoryBytes 1048576} :property {maxResponseBytes 8388608} :property {maxOutputTokens 4096} :property {maxToolCalls 32} :property {maxApiRequests 16} :property {streamStore {}} :variable mutex :method init {} { if {${:streamStore} eq ""} {set :streamStore nsmcp:question-http:[ns_info server]} # ns_eval may construct backend copies in several interpreters. Every # copy draining/appending the same NSV stream must use the same lock. if {![nsv_exists nsmcp:question-http-locks ${:streamStore}] || ![nsv_get nsmcp:question-http-locks ${:streamStore} :mutex]} { set :mutex [nsv_set -default nsmcp:question-http-locks ${:streamStore} [ns_mutex create]] } } # Describe non-secret provider settings to the administration interface. :public method describe {} { return [dict create backend chat-completions model ${:model} apiUrl ${:apiUrl} streaming true timeout ${:timeout} maxOutputTokens ${:maxOutputTokens} maxToolCalls ${:maxToolCalls} maxApiRequests ${:maxApiRequests}] } :public method run {question state emit} { set runner [::nsmcp::ChatCompletionsRun new -backend [self] -emit $emit] try { return [$runner run $question $state] } finally { $runner destroy } } # The ns_http task callback runs in another interpreter. Keep only bounded # response bytes and status in NSV; parse SSE and invoke tools in the worker. :public method streamOpen {} { set key [ns_crypto::randombytes -encoding hex 16] nsv_set ${:streamStore} $key {data {} total 0 status 0 contentType {} error {}} return $key } :public method streamHeaders {key fields} { ns_mutex lock ${:mutex} try { if {[nsv_get ${:streamStore} $key record]} { dict set record status [dict get $fields status] dict set record contentType [ns_set iget [dict get $fields headers] content-type] nsv_set ${:streamStore} $key $record } } finally {ns_mutex unlock ${:mutex}} } :public method streamData {key fields} { ns_mutex lock ${:mutex} try { if {[nsv_get ${:streamStore} $key record]} { set data [dict get $fields data] dict incr record total [string bytelength $data] if {[dict get $record total] > ${:maxResponseBytes} || [string bytelength [dict get $record data]] + [string bytelength $data] > 1048576} { dict set record error "API response exceeded its buffer or response size limit" } elseif {[dict get $record error] eq ""} { dict append record data $data } nsv_set ${:streamStore} $key $record } } finally {ns_mutex unlock ${:mutex}} # The request discards its normal output. Returning TCL_OK also works # with cores whose queued callback evaluator does not propagate BREAK. return } :public method streamDrain {key} { ns_mutex lock ${:mutex} try { set record [nsv_get ${:streamStore} $key] set next $record dict set next data {} nsv_set ${:streamStore} $key $next return $record } finally {ns_mutex unlock ${:mutex}} } :public method streamClose {key} { ns_mutex lock ${:mutex} try {nsv_unset -nocomplain ${:streamStore} $key} finally {ns_mutex unlock ${:mutex}} }XQL Not present: Generic, PostgreSQL, Oracle
![[i]](/resources/acs-subsite/ZoomIn16.gif)