2024-07-25 11:30:49 +02:00
|
|
|
// Copyright 2024, Command Line Inc.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
package waveai
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"log"
|
|
|
|
"time"
|
|
|
|
|
2024-09-05 23:25:45 +02:00
|
|
|
"github.com/wavetermdev/waveterm/pkg/wshrpc"
|
2024-07-25 11:30:49 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const OpenAIPacketStr = "openai"
|
|
|
|
const OpenAICloudReqStr = "openai-cloudreq"
|
|
|
|
const PacketEOFStr = "EOF"
|
2024-10-09 22:36:02 +02:00
|
|
|
const DefaultAzureAPIVersion = "2023-05-15"
|
2024-11-12 02:11:09 +01:00
|
|
|
const ApiType_Anthropic = "anthropic"
|
2024-07-25 11:30:49 +02:00
|
|
|
|
|
|
|
type OpenAICmdInfoPacketOutputType struct {
|
|
|
|
Model string `json:"model,omitempty"`
|
|
|
|
Created int64 `json:"created,omitempty"`
|
|
|
|
FinishReason string `json:"finish_reason,omitempty"`
|
|
|
|
Message string `json:"message,omitempty"`
|
|
|
|
Error string `json:"error,omitempty"`
|
|
|
|
}
|
|
|
|
|
2024-07-26 22:30:11 +02:00
|
|
|
func MakeOpenAIPacket() *wshrpc.OpenAIPacketType {
|
|
|
|
return &wshrpc.OpenAIPacketType{Type: OpenAIPacketStr}
|
2024-07-25 11:30:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type OpenAICmdInfoChatMessage struct {
|
|
|
|
MessageID int `json:"messageid"`
|
|
|
|
IsAssistantResponse bool `json:"isassistantresponse,omitempty"`
|
|
|
|
AssistantResponse *OpenAICmdInfoPacketOutputType `json:"assistantresponse,omitempty"`
|
|
|
|
UserQuery string `json:"userquery,omitempty"`
|
|
|
|
UserEngineeredQuery string `json:"userengineeredquery,omitempty"`
|
|
|
|
}
|
|
|
|
|
2024-11-11 20:39:08 +01:00
|
|
|
type AIBackend interface {
|
|
|
|
StreamCompletion(
|
|
|
|
ctx context.Context,
|
|
|
|
request wshrpc.OpenAiStreamRequest,
|
|
|
|
) chan wshrpc.RespOrErrorUnion[wshrpc.OpenAIPacketType]
|
2024-07-25 11:30:49 +02:00
|
|
|
}
|
|
|
|
|
2024-10-09 22:36:02 +02:00
|
|
|
const DefaultMaxTokens = 2048
|
2024-08-28 21:05:29 +02:00
|
|
|
const DefaultModel = "gpt-4o-mini"
|
2024-10-09 22:36:02 +02:00
|
|
|
const WCloudWSEndpoint = "wss://wsapi.waveterm.dev/"
|
|
|
|
const WCloudWSEndpointVarName = "WCLOUD_WS_ENDPOINT"
|
2024-07-25 11:30:49 +02:00
|
|
|
|
|
|
|
const CloudWebsocketConnectTimeout = 1 * time.Minute
|
|
|
|
|
2024-10-09 22:36:02 +02:00
|
|
|
func IsCloudAIRequest(opts *wshrpc.OpenAIOptsType) bool {
|
|
|
|
if opts == nil {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return opts.BaseURL == "" && opts.APIToken == ""
|
|
|
|
}
|
|
|
|
|
2024-08-09 03:24:54 +02:00
|
|
|
func makeAIError(err error) wshrpc.RespOrErrorUnion[wshrpc.OpenAIPacketType] {
|
|
|
|
return wshrpc.RespOrErrorUnion[wshrpc.OpenAIPacketType]{Error: err}
|
|
|
|
}
|
|
|
|
|
2024-10-09 22:36:02 +02:00
|
|
|
func RunAICommand(ctx context.Context, request wshrpc.OpenAiStreamRequest) chan wshrpc.RespOrErrorUnion[wshrpc.OpenAIPacketType] {
|
2024-11-12 02:11:09 +01:00
|
|
|
if request.Opts.APIType == ApiType_Anthropic {
|
2024-11-11 20:39:08 +01:00
|
|
|
endpoint := request.Opts.BaseURL
|
|
|
|
if endpoint == "" {
|
|
|
|
endpoint = "default"
|
|
|
|
}
|
|
|
|
log.Printf("sending ai chat message to anthropic endpoint %q using model %s\n", endpoint, request.Opts.Model)
|
|
|
|
anthropicBackend := AnthropicBackend{}
|
|
|
|
return anthropicBackend.StreamCompletion(ctx, request)
|
|
|
|
}
|
2024-10-09 22:36:02 +02:00
|
|
|
if IsCloudAIRequest(request.Opts) {
|
|
|
|
log.Print("sending ai chat message to default waveterm cloud endpoint\n")
|
2024-11-11 20:39:08 +01:00
|
|
|
cloudBackend := WaveAICloudBackend{}
|
|
|
|
return cloudBackend.StreamCompletion(ctx, request)
|
2024-10-09 22:36:02 +02:00
|
|
|
} else {
|
2024-11-11 20:39:08 +01:00
|
|
|
log.Printf("sending ai chat message to user-configured endpoint %s using model %s\n", request.Opts.BaseURL, request.Opts.Model)
|
|
|
|
openAIBackend := OpenAIBackend{}
|
|
|
|
return openAIBackend.StreamCompletion(ctx, request)
|
2024-10-09 22:36:02 +02:00
|
|
|
}
|
|
|
|
}
|