]> git.giacomolli.uk - onechat/blobdiff - model.go
Check the width of comment lines
[onechat] / model.go
index 507fbb1a260265dbdd0f61c817ba33aef07d9cfa..cc77f9a434fbdfad519628a08e1fbd8eb1c0ebf6 100644 (file)
--- a/model.go
+++ b/model.go
@@ -41,9 +41,9 @@ const (
 var errModelCallLimit = errors.New("call limit reached")
 
 // modelEndpoint returns the URL and the authorizer of the endpoint in config.
 var errModelCallLimit = errors.New("call limit reached")
 
 // modelEndpoint returns the URL and the authorizer of the endpoint in config.
-// The ChatGPT backend uses the token file in dir. The OpenAI API uses the key in
-// OPENAI_API_KEY, and there is no fallback from one to the other. All clients
-// share the authorizer, so one refresh runs at a time.
+// The ChatGPT backend uses the token file in dir. The OpenAI API uses the key
+// in OPENAI_API_KEY, and there is no fallback from one to the other. All
+// clients share the authorizer, so one refresh runs at a time.
 func modelEndpoint(config Config, dir string) (string, ModelAuthorizer, error) {
        if config.Endpoint == configEndpointAPI {
                key := os.Getenv("OPENAI_API_KEY")
 func modelEndpoint(config Config, dir string) (string, ModelAuthorizer, error) {
        if config.Endpoint == configEndpointAPI {
                key := os.Getenv("OPENAI_API_KEY")
@@ -73,22 +73,22 @@ func newModelClient(url string, auth ModelAuthorizer, cacheKey, usagePath string
 
 // modelUserMessage returns a user input item with one text part for each text.
 func modelUserMessage(texts ...string) any {
 
 // modelUserMessage returns a user input item with one text part for each text.
 func modelUserMessage(texts ...string) any {
-       type part struct {
-               Type string `json:"type"`
-               Text string `json:"text"`
-       }
-
-       content := make([]part, len(texts))
+       content := make([]ModelInputPart, len(texts))
        for n, text := range texts {
        for n, text := range texts {
-               content[n] = part{
+               content[n] = ModelInputPart{
                        Type: "input_text",
                        Text: text,
                }
        }
 
                        Type: "input_text",
                        Text: text,
                }
        }
 
+       return modelUserParts(content)
+}
+
+// modelUserParts keeps text and image parts in one user message.
+func modelUserParts(content []ModelInputPart) any {
        return struct {
        return struct {
-               Role    string `json:"role"`
-               Content []part `json:"content"`
+               Role    string           `json:"role"`
+               Content []ModelInputPart `json:"content"`
        }{
                Role:    "user",
                Content: content,
        }{
                Role:    "user",
                Content: content,
@@ -321,6 +321,13 @@ type ModelOutputItem struct {
        } `json:"content"`
 }
 
        } `json:"content"`
 }
 
+// ModelInputPart is a text or image part in a user message or tool result.
+type ModelInputPart struct {
+       Type     string `json:"type"`
+       Text     string `json:"text,omitempty"`
+       ImageURL string `json:"image_url,omitempty"`
+}
+
 // ModelRequest is one model call. Input holds the input items in order, such as
 // modelUserMessage values or output items of an earlier response. Node names
 // the node that a compaction builds, or is nil. Turn names the request of a
 // ModelRequest is one model call. Input holds the input items in order, such as
 // modelUserMessage values or output items of an earlier response. Node names
 // the node that a compaction builds, or is nil. Turn names the request of a