Class ::nsmcp::ChatCompletionsBackend (public)

 ::nx::Class ::nsmcp::ChatCompletionsBackend[i]

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
[ hide source ] | [ make this the default ]
Show another procedure: