ParthSareen 4 месяцев назад
Родитель
Сommit
6556540655
2 измененных файлов с 46 добавлено и 15 удалено
  1. 13 8
      api/types.go
  2. 33 7
      server/routes.go

+ 13 - 8
api/types.go

@@ -103,14 +103,18 @@ type ChatRequest struct {
 	// Tools is an optional list of tools the model has access to.
 	Tools `json:"tools,omitempty"`
 
-	// DryRun when true will prepare and validate the request but stop before sending it to the model.
-	// This allows inspecting how the prompt would be constructed and what parameters would be used.
-	DryRun bool `json:"dry_run,omitempty"`
+	Debug *Debug `json:"debug,omitempty"`
+
+	Dry bool `json:"dry,omitempty"`
 
 	// Options lists model-specific options.
 	Options map[string]interface{} `json:"options"`
 }
 
+type Debug struct {
+	Include []string `json:"include,omitempty"`
+}
+
 type Tools []Tool
 
 func (t Tools) String() string {
@@ -189,11 +193,12 @@ func (t *ToolFunction) String() string {
 // ChatResponse is the response returned by [Client.Chat]. Its fields are
 // similar to [GenerateResponse].
 type ChatResponse struct {
-	Model        string    `json:"model"`
-	CreatedAt    time.Time `json:"created_at"`
-	Message      Message   `json:"message"`
-	DoneReason   string    `json:"done_reason,omitempty"`
-	DryRunOutput string    `json:"dry_run_output,omitempty"`
+	Model      string    `json:"model"`
+	CreatedAt  time.Time `json:"created_at"`
+	Message    Message   `json:"message"`
+	DoneReason string    `json:"done_reason,omitempty"`
+
+	Debug map[string]any `json:"debug,omitempty"`
 
 	Done bool `json:"done"`
 

+ 33 - 7
server/routes.go

@@ -1539,14 +1539,30 @@ func (s *Server) ChatHandler(c *gin.Context) {
 		return
 	}
 
-	if req.DryRun {
+	if req.Dry {
+		var debug map[string]any
+		if req.Debug != nil && req.Debug.Include != nil && slices.Contains(req.Debug.Include, "prompt") {
+			debug = map[string]any{"prompt": prompt}
+		}
+		tokens, err := r.Tokenize(c.Request.Context(), prompt)
+		if err != nil {
+			slog.Error("tokenize error", "error", err)
+			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
+			return
+		}
 		c.JSON(http.StatusOK, api.ChatResponse{
-			Model:        req.Model,
-			CreatedAt:    time.Now().UTC(),
-			Message:      api.Message{Role: "assistant", Content: ""},
-			Done:         true,
-			DoneReason:   "dry_run",
-			DryRunOutput: prompt,
+			Model:      req.Model,
+			CreatedAt:  time.Now().UTC(),
+			Message:    api.Message{Role: "assistant", Content: ""},
+			Done:       true,
+			DoneReason: "dry_run",
+			Debug:      debug,
+			Metrics: api.Metrics{
+				PromptEvalCount:    len(tokens),
+				PromptEvalDuration: 0,
+				EvalCount:          0,
+				EvalDuration:       0,
+			},
 		})
 		return
 	}
@@ -1583,6 +1599,16 @@ func (s *Server) ChatHandler(c *gin.Context) {
 				res.LoadDuration = checkpointLoaded.Sub(checkpointStart)
 			}
 
+			if req.Debug != nil && req.Debug.Include != nil && slices.Contains(req.Debug.Include, "prompt") {
+				res.Debug = map[string]any{"prompt": prompt}
+				if req.Stream != nil && !*req.Stream {
+					tempMsg := res.Message
+					res.Message = api.Message{Role: "assistant", Content: ""}
+					ch <- res
+					res.Message = tempMsg
+				}
+			}
+
 			// TODO: tool call checking and filtering should be moved outside of this callback once streaming
 			// however this was a simple change for now without reworking streaming logic of this (and other)
 			// handlers