mirror of
https://github.com/discourse/discourse-ai.git
synced 2025-02-17 00:45:12 +00:00
This PR adds tool support to available LLMs. We'll buffer tool invocations and return them instead of making users of this service parse the response. It also adds support for conversation context in the generic prompt. It includes bot messages, user messages, and tool invocations, which we'll trim to make sure it doesn't exceed the prompt limit, then translate them to the correct dialect. Finally, It adds some buffering when reading chunks to handle cases when streaming is extremely slow.:M
61 lines
1.5 KiB
Ruby
61 lines
1.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module DiscourseAi
|
|
module Completions
|
|
module Endpoints
|
|
class CannedResponse
|
|
CANNED_RESPONSE_ERROR = Class.new(StandardError)
|
|
|
|
def self.can_contact?(_)
|
|
Rails.env.test?
|
|
end
|
|
|
|
def initialize(responses)
|
|
@responses = responses
|
|
@completions = 0
|
|
@prompt = nil
|
|
end
|
|
|
|
attr_reader :responses, :completions, :prompt
|
|
|
|
def perform_completion!(prompt, _user, _model_params)
|
|
@prompt = prompt
|
|
response = responses[completions]
|
|
if response.nil?
|
|
raise CANNED_RESPONSE_ERROR,
|
|
"The number of completions you requested exceed the number of canned responses"
|
|
end
|
|
|
|
@completions += 1
|
|
if block_given?
|
|
cancelled = false
|
|
cancel_fn = lambda { cancelled = true }
|
|
|
|
# We buffer and return tool invocations in one go.
|
|
if is_tool?(response)
|
|
yield(response, cancel_fn)
|
|
else
|
|
response.each_char do |char|
|
|
break if cancelled
|
|
yield(char, cancel_fn)
|
|
end
|
|
end
|
|
else
|
|
response
|
|
end
|
|
end
|
|
|
|
def tokenizer
|
|
DiscourseAi::Tokenizer::OpenAiTokenizer
|
|
end
|
|
|
|
private
|
|
|
|
def is_tool?(response)
|
|
Nokogiri::HTML5.fragment(response).at("function_calls").present?
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|