ronantakizawa/codereview-bench huggingface dataset:
Repository: ollama/ollama
File: api/types.go (Go)

Code before:
	if *b == TriStateTrue {
		v = true
	}
	return json.Marshal(v)
}

// EmbeddingRequest is the request passed to [Client.Embeddings].
type EmbeddingRequest struct {
	// Model is the model name.
	Model string `json:"model"`

	// Prompt is the textual prompt to embed.
	// Prompt string `json:"prompt"`
	Prompt interface{} `json:"prompt"`

	// KeepAlive controls how long the model will stay loaded in memory following
	// this request.
	KeepAlive *Duration `json:"keep_alive,omitempty"`

	// Options lists model-specific options.
	Options map[string]interface{} `json:"options"`
}

// EmbeddingResponse is the response from [Client.Embeddings].
type EmbeddingResponse struct {
	Embedding [][]float64 `json:"embedding"`
}

// CreateRequest is the request passed to [Client.Create].
type CreateRequest struct {
	Model     string `json:"model"`
	Path      string `json:"path"`
	Modelfile string `json:"modelfile"`
	Stream    *bool  `json:"stream,omitempty"`
	Quantize  string `json:"quantize,omitempty"`

	// Name is deprecated, see Model
	Name string `json:"name"`

	// Quantization is deprecated, see Quantize
	Quantization string `json:"quantization,omitempty"`
}

// DeleteRequest is the request passed to [Client.Delete].
type DeleteRequest struct {
	Model string `json:"model"`

	// Name is deprecated, see Model
	Name string `json:"name"`
}


Review comment (suggestion):
This looks to be a breaking change. Single string prompts should still return a `[]float64` not a `[][]float64`.

This can be a separate change but we should probably be returning a `float32` here...

Code after:
type EmbeddingRequest struct {
	// Model is the model name.
	Model string `json:"model"`

	// Prompt is the textual prompt to embed.
	Prompt string `json:"prompt"`

	// KeepAlive controls how long the model will stay loaded in memory following
	// this request.
	KeepAlive *Duration `json:"keep_alive,omitempty"`

	// Options lists model-specific options.
	Options map[string]interface{} `json:"options"`
}

// EmbeddingResponse is the response from [Client.Embeddings].
type EmbeddingResponse struct {
	Embedding []float64 `json:"embedding"`
}

// CreateRequest is the request passed to [Client.Create].
type CreateRequest struct {
	Model     string `json:"model"`
	Path      string `json:"path"`
	Modelfile string `json:"modelfile"`
	Stream    *bool  `json:"stream,omitempty"`
	Quantize  string `json:"quantize,omitempty"`

	// Name is deprecated, see Model
	Name string `json:"name"`

	// Quantization is deprecated, see Quantize
	Quantization string `json:"quantization,omitempty"`
}

// DeleteRequest is the request passed to [Client.Delete].
type DeleteRequest struct {
	Model string `json:"model"`

	// Name is deprecated, see Model
	Name string `json:"name"`
}

// ShowRequest is the request passed to [Client.Show].
type ShowRequest struct {
	Model    string `json:"model"`
	System   string `json:"system"`
	Template string `json:"template"`
	Verbose  bool   `json:"verbose"`

	Options map[string]interface{} `json:"options"`
Repository: ollama/ollama
File: server/routes.go (Go)

Code before:
	}

	checkFit := func(s string, truncate bool) (string, error) {
		tokens, err := r.Tokenize(c.Request.Context(), s)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return "", err
		}

		if len(tokens) > opts.NumCtx {
			if truncate {
				tokens = tokens[:opts.NumCtx]
				return r.Detokenize(c.Request.Context(), tokens)
			} else {
				return "", fmt.Errorf("input length exceeds maximum context length")
			}
		}

		return s, nil
	}

	embeddings := [][]float32{}

	switch reqEmbed := req.Input.(type) {
	case string:
		reqEmbed, err = checkFit(reqEmbed, *req.Truncate)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}
		embeddings, err = r.Embed(c.Request.Context(), []string{reqEmbed})
	case []any:
		reqEmbedArray := make([]string, len(reqEmbed))
		for i, v := range reqEmbed {
			s, err := checkFit(v.(string), *req.Truncate)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
			reqEmbedArray[i] = s
		}
		embeddings, err = r.Embed(c.Request.Context(), reqEmbedArray)
	default:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
	}

	if err != nil {
		slog.Info(fmt.Sprintf("embedding generation failed: %v", err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate embedding"})
		return
	}

Review comment (suggestion):
instead of passing `req.Truncate` here, let's just truncate the string and then check the value of `req.Truncate` on whether to error

Code after:
			}

			tokens = tokens[:ctxLen]
			s, err = r.Detokenize(c.Request.Context(), tokens)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
		}

		input[i] = s
	}
	embeddings, err := r.Embed(c.Request.Context(), input)

	if err != nil {
		slog.Error("embedding generation failed", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate embedding"})
		return
	}

	for i, e := range embeddings {
		embeddings[i] = normalize(e)
	}

	resp := api.EmbedResponse{
		Model:      req.Model,
		Embeddings: embeddings,
	}
	c.JSON(http.StatusOK, resp)
}

func normalize(vec []float32) []float32 {
	var sum float32
	for _, v := range vec {
		sum += v * v
	}

	norm := float32(0.0)
	if sum > 0 {
		norm = float32(1.0 / math.Sqrt(float64(sum)))
	}

	for i := range vec {
		vec[i] *= norm
	}
	return vec
}

func (s *Server) EmbeddingsHandler(c *gin.Context) {
	var req api.EmbeddingRequest
	if err := c.ShouldBindJSON(&req); errors.Is(err, io.EOF) {
Repository: ollama/ollama
File: server/routes.go (Go)

Code before:
		handleScheduleError(c, req.Model, err)
		return
	}

	checkFit := func(s string, truncate bool) (string, error) {
		tokens, err := r.Tokenize(c.Request.Context(), s)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return "", err
		}

		if len(tokens) > opts.NumCtx {
			if truncate {
				tokens = tokens[:opts.NumCtx]
				return r.Detokenize(c.Request.Context(), tokens)
			} else {
				return "", fmt.Errorf("input length exceeds maximum context length")
			}
		}

		return s, nil
	}

	embeddings := [][]float32{}

	switch reqEmbed := req.Input.(type) {
	case string:
		reqEmbed, err = checkFit(reqEmbed, *req.Truncate)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}
		embeddings, err = r.Embed(c.Request.Context(), []string{reqEmbed})
	case []any:
		reqEmbedArray := make([]string, len(reqEmbed))
		for i, v := range reqEmbed {
			s, err := checkFit(v.(string), *req.Truncate)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
			reqEmbedArray[i] = s
		}
		embeddings, err = r.Embed(c.Request.Context(), reqEmbedArray)
	default:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
	}

	if err != nil {
		slog.Info(fmt.Sprintf("embedding generation failed: %v", err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate embedding"})

Review comment (suggestion):
Instead of calling `checkFit` in two places here let's call it once and instead use the switch statement to build the input array

Code after:
				c.JSON(http.StatusBadRequest, gin.H{"error": "input length exceeds maximum context length"})
				return
			}

			tokens = tokens[:ctxLen]
			s, err = r.Detokenize(c.Request.Context(), tokens)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
		}

		input[i] = s
	}
	embeddings, err := r.Embed(c.Request.Context(), input)

	if err != nil {
		slog.Error("embedding generation failed", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate embedding"})
		return
	}

	for i, e := range embeddings {
		embeddings[i] = normalize(e)
	}

	resp := api.EmbedResponse{
		Model:      req.Model,
		Embeddings: embeddings,
	}
	c.JSON(http.StatusOK, resp)
}

func normalize(vec []float32) []float32 {
	var sum float32
	for _, v := range vec {
		sum += v * v
	}

	norm := float32(0.0)
	if sum > 0 {
		norm = float32(1.0 / math.Sqrt(float64(sum)))
	}

	for i := range vec {
		vec[i] *= norm
	}
	return vec
}

func (s *Server) EmbeddingsHandler(c *gin.Context) {
Repository: ollama/ollama
File: server/routes_test.go (Go)

Code before:
		t.Fatal(err)
	}

	if resp.ModelInfo["general.architecture"] != "test" {
		t.Fatal("Expected model architecture to be 'test', but got", resp.ModelInfo["general.architecture"])
	}

	if resp.ProjectorInfo["general.architecture"] != "clip" {
		t.Fatal("Expected projector architecture to be 'clip', but got", resp.ProjectorInfo["general.architecture"])
	}
}

func TestNormalize(t *testing.T) {
	type testCase struct {
		input []float32
	}

	testCases := []testCase{
		{input: []float32{1}},
		{input: []float32{0, 1, 2, 3}},
		{input: []float32{0.1, 0.2, 0.3}},
		{input: []float32{-0.1, 0.2, 0.3, -0.4}},
		{input: []float32{0, 0, 0}},
	}

	assertNorm := func(vec []float32) (res bool) {
		sum := 0.0
		for _, v := range vec {
			sum += float64(v * v)
		}
		if math.Abs(sum-1) > 1e-6 {
			return sum == 0
		} else {
			return true
		}
	}

	for _, tc := range testCases {
		t.Run("", func(t *testing.T) {
			normalized := normalize(tc.input)
			if !assertNorm(normalized) {
				t.Errorf("Vector %v is not normalized", tc.input)
			}
		})
	}
}


Review comment (suggestion):
```suggestion
	isNormalized := func(vec []float32) (res bool) {
```

Code after:
	createRequest(t, s.CreateModelHandler, api.CreateRequest{
		Name: "show-model",
		Modelfile: fmt.Sprintf(
			"FROM %s\nFROM %s",
			createBinFile(t, llm.KV{"general.architecture": "test"}, nil),
			createBinFile(t, llm.KV{"general.architecture": "clip"}, nil),
		),
	})

	w := createRequest(t, s.ShowModelHandler, api.ShowRequest{
		Name: "show-model",
	})

	if w.Code != http.StatusOK {
		t.Fatalf("expected status code 200, actual %d", w.Code)
	}

	var resp api.ShowResponse
	if err := json.NewDecoder(w.Body).Decode(&resp); err != nil {
		t.Fatal(err)
	}

	if resp.ModelInfo["general.architecture"] != "test" {
		t.Fatal("Expected model architecture to be 'test', but got", resp.ModelInfo["general.architecture"])
	}

	if resp.ProjectorInfo["general.architecture"] != "clip" {
		t.Fatal("Expected projector architecture to be 'clip', but got", resp.ProjectorInfo["general.architecture"])
	}
}

func TestNormalize(t *testing.T) {
	type testCase struct {
		input []float32
	}

	testCases := []testCase{
		{input: []float32{1}},
		{input: []float32{0, 1, 2, 3}},
		{input: []float32{0.1, 0.2, 0.3}},
		{input: []float32{-0.1, 0.2, 0.3, -0.4}},
		{input: []float32{0, 0, 0}},
	}

	isNormalized := func(vec []float32) (res bool) {
		sum := 0.0
		for _, v := range vec {
			sum += float64(v * v)
		}
		if math.Abs(sum-1) > 1e-6 {
			return sum == 0
Repository: ollama/ollama
File: integration/embed_test.go (Go)

Code before:

	if res["Target Truncation"].Embeddings[0][0] != res["Default Truncate"].Embeddings[0][0] {
		t.Fatalf("expected default request to truncate correctly")
	}

	if res["Default Truncate"].Embeddings[0][0] != res["Explicit Truncate"].Embeddings[0][0] {
		t.Fatalf("expected default request and truncate true request to be the same")
	}

	// check that truncate set to false returns an error if context length is exceeded
	_, err := embedTestHelper(ctx, t, api.EmbedRequest{
		Model:    "all-minilm",
		Input:    "why is the sky blue?",
		Truncate: &truncFalse,
		Options:  map[string]any{"num_ctx": 1},
	})

	if err == nil {
		t.Fatalf("expected error, got nil")
	}
}

func embedTestHelper(ctx context.Context, t *testing.T, req api.EmbedRequest) (*api.EmbedResponse, error) {
	client, _, cleanup := InitServerConnection(ctx, t)
	defer cleanup()
	require.NoError(t, PullIfMissing(ctx, client, req.Model))

	response, err := client.Embed(ctx, &req)

	if err != nil {
		return nil, err
	}

	return response, nil
}


Review comment (bug):
something like

```
if err:= PullIfMissing(ctx, client, req.Model); err != nil {
    t.Fatalf("failed to pull model %s: %v", req.Model, err)
}
```

Code after:
	if res["Target Truncation"].Embeddings[0][0] != res["Default Truncate"].Embeddings[0][0] {
		t.Fatal("expected default request to truncate correctly")
	}

	if res["Default Truncate"].Embeddings[0][0] != res["Explicit Truncate"].Embeddings[0][0] {
		t.Fatal("expected default request and truncate true request to be the same")
	}

	// check that truncate set to false returns an error if context length is exceeded
	_, err := embedTestHelper(ctx, t, api.EmbedRequest{
		Model:    "all-minilm",
		Input:    "why is the sky blue?",
		Truncate: &truncFalse,
		Options:  map[string]any{"num_ctx": 1},
	})

	if err == nil {
		t.Fatal("expected error, got nil")
	}
}

func embedTestHelper(ctx context.Context, t *testing.T, req api.EmbedRequest) (*api.EmbedResponse, error) {
	client, _, cleanup := InitServerConnection(ctx, t)
	defer cleanup()
	if err := PullIfMissing(ctx, client, req.Model); err != nil {
		t.Fatalf("failed to pull model %s: %v", req.Model, err)
	}

	response, err := client.Embed(ctx, &req)

	if err != nil {
		return nil, err
	}

	return response, nil
}
Repository: ollama/ollama
File: server/routes.go (Go)

Code before:
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}

		ctxLen := min(opts.NumCtx, int(kvData.ContextLength()))
		if len(tokens) > ctxLen {
			if *req.Truncate {
				tokens = tokens[:ctxLen]
				s, err = r.Detokenize(c.Request.Context(), tokens)
				if err != nil {
					c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
					return
				}
			} else {
				c.JSON(http.StatusBadRequest, gin.H{"error": "input length exceeds maximum context length"})
				return
			}
		}

		reqEmbedArray[i] = s
	}
	embeddings, err := r.Embed(c.Request.Context(), reqEmbedArray)

	if err != nil {
		slog.Info(fmt.Sprintf("embedding generation failed: %v", err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate embedding"})
		return
	}

	for i, e := range embeddings {
		embeddings[i] = normalize(e)
	}

	resp := api.EmbedResponse{
		Model:      req.Model,
		Embeddings: embeddings,
	}
	c.JSON(http.StatusOK, resp)
}

func normalize(vec []float32) []float32 {
	var sum float32
	for _, v := range vec {
		sum += v * v
	}

	norm := float32(0.0)
	if sum > 0 {
		norm = float32(1.0 / math.Sqrt(float64(sum)))
	}

Review comment (bug):
```suggestion
		slog.Error("embedding generation failed", "error", err)
```

Code after:
			return
		}

		ctxLen := min(opts.NumCtx, int(kvData.ContextLength()))
		if len(tokens) > ctxLen {
			if !truncate {
				c.JSON(http.StatusBadRequest, gin.H{"error": "input length exceeds maximum context length"})
				return
			}

			tokens = tokens[:ctxLen]
			s, err = r.Detokenize(c.Request.Context(), tokens)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
		}

		input[i] = s
	}
	embeddings, err := r.Embed(c.Request.Context(), input)

	if err != nil {
		slog.Error("embedding generation failed", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate embedding"})
		return
	}

	for i, e := range embeddings {
		embeddings[i] = normalize(e)
	}

	resp := api.EmbedResponse{
		Model:      req.Model,
		Embeddings: embeddings,
	}
	c.JSON(http.StatusOK, resp)
}

func normalize(vec []float32) []float32 {
	var sum float32
	for _, v := range vec {
		sum += v * v
	}

	norm := float32(0.0)
	if sum > 0 {
		norm = float32(1.0 / math.Sqrt(float64(sum)))
	}

	for i := range vec {
Repository: ollama/ollama
File: server/routes.go (Go)

Code before:
		return
	}

	streamResponse(c, ch)
}

func (s *Server) EmbedHandler(c *gin.Context) {
	var req api.EmbedRequest
	err := c.ShouldBindJSON(&req)
	switch {
	case errors.Is(err, io.EOF):
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
		return
	case err != nil:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if req.Truncate == nil {
		truncate := true
		req.Truncate = &truncate
	}

	reqEmbed := []string{}

	switch embeddings := req.Input.(type) {
	case string:
		if embeddings == "" {
			c.JSON(http.StatusOK, api.EmbedResponse{Model: req.Model, Embeddings: [][]float32{}})
			return
		}
		reqEmbed = []string{embeddings}
	case []any:
		if len(embeddings) == 0 {
			c.JSON(http.StatusOK, api.EmbedResponse{Model: req.Model, Embeddings: [][]float32{}})
			return
		}

		for _, v := range embeddings {
			if _, ok := v.(string); !ok {
				c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
				return
			}
			reqEmbed = append(reqEmbed, v.(string))
		}
	default:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
		return
	}

	r, m, opts, err := s.scheduleRunner(c.Request.Context(), req.Model, []Capability{}, req.Options, req.KeepAlive)

Review comment (suggestion):
```suggestion
	switch i := req.Input.(type) {
```

Code after:
		return
	}

	streamResponse(c, ch)
}

func (s *Server) EmbedHandler(c *gin.Context) {
	var req api.EmbedRequest
	err := c.ShouldBindJSON(&req)
	switch {
	case errors.Is(err, io.EOF):
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
		return
	case err != nil:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	truncate := true

	if req.Truncate != nil && !*req.Truncate {
		truncate = false
	}

	var input []string

	switch i := req.Input.(type) {
	case string:
		if len(i) > 0 {
			input = append(input, i)
		}
	case []any:
		for _, v := range i {
			if _, ok := v.(string); !ok {
				c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
				return
			}
			input = append(input, v.(string))
		}
	default:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
		return
	}

	if len(input) == 0 {
		c.JSON(http.StatusOK, api.EmbedResponse{Model: req.Model, Embeddings: [][]float32{}})
		return
	}

	r, m, opts, err := s.scheduleRunner(c.Request.Context(), req.Model, []Capability{}, req.Options, req.KeepAlive)
	if err != nil {
Repository: ollama/ollama
File: server/routes.go (Go)

Code before:

	streamResponse(c, ch)
}

func (s *Server) EmbedHandler(c *gin.Context) {
	var req api.EmbedRequest
	err := c.ShouldBindJSON(&req)
	switch {
	case errors.Is(err, io.EOF):
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
		return
	case err != nil:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if req.Truncate == nil {
		truncate := true
		req.Truncate = &truncate
	}

	reqEmbed := []string{}

	switch embeddings := req.Input.(type) {
	case string:
		if embeddings == "" {
			c.JSON(http.StatusOK, api.EmbedResponse{Model: req.Model, Embeddings: [][]float32{}})
			return
		}
		reqEmbed = []string{embeddings}
	case []any:
		if len(embeddings) == 0 {
			c.JSON(http.StatusOK, api.EmbedResponse{Model: req.Model, Embeddings: [][]float32{}})
			return
		}

		for _, v := range embeddings {
			if _, ok := v.(string); !ok {
				c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
				return
			}
			reqEmbed = append(reqEmbed, v.(string))
		}
	default:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
		return
	}

	r, m, opts, err := s.scheduleRunner(c.Request.Context(), req.Model, []Capability{}, req.Options, req.KeepAlive)
	if err != nil {
		handleScheduleError(c, req.Model, err)

Review comment (suggestion):
```
if len(embeddings) > 0 {
  input = append(input, i)
}
```

Code after:

	streamResponse(c, ch)
}

func (s *Server) EmbedHandler(c *gin.Context) {
	var req api.EmbedRequest
	err := c.ShouldBindJSON(&req)
	switch {
	case errors.Is(err, io.EOF):
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
		return
	case err != nil:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	truncate := true

	if req.Truncate != nil && !*req.Truncate {
		truncate = false
	}

	var input []string

	switch i := req.Input.(type) {
	case string:
		if len(i) > 0 {
			input = append(input, i)
		}
	case []any:
		for _, v := range i {
			if _, ok := v.(string); !ok {
				c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
				return
			}
			input = append(input, v.(string))
		}
	default:
		c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid input type"})
		return
	}

	if len(input) == 0 {
		c.JSON(http.StatusOK, api.EmbedResponse{Model: req.Model, Embeddings: [][]float32{}})
		return
	}

	r, m, opts, err := s.scheduleRunner(c.Request.Context(), req.Model, []Capability{}, req.Options, req.KeepAlive)
	if err != nil {
		handleScheduleError(c, req.Model, err)
		return
Repository: ollama/ollama
File: server/routes.go (Go)

Code before:
	}

	kvData, err := getKVData(m.ModelPath, false)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	reqEmbedArray := make([]string, len(reqEmbed))
	for i, s := range reqEmbed {
		tokens, err := r.Tokenize(c.Request.Context(), s)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}

		ctxLen := min(opts.NumCtx, int(kvData.ContextLength()))
		if len(tokens) > ctxLen {
			if *req.Truncate {
				tokens = tokens[:ctxLen]
				s, err = r.Detokenize(c.Request.Context(), tokens)
				if err != nil {
					c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
					return
				}
			} else {
				c.JSON(http.StatusBadRequest, gin.H{"error": "input length exceeds maximum context length"})
				return
			}
		}

		reqEmbedArray[i] = s
	}
	embeddings, err := r.Embed(c.Request.Context(), reqEmbedArray)

	if err != nil {
		slog.Info(fmt.Sprintf("embedding generation failed: %v", err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate embedding"})
		return
	}

	for i, e := range embeddings {
		embeddings[i] = normalize(e)
	}

	resp := api.EmbedResponse{
		Model:      req.Model,
		Embeddings: embeddings,
	}
	c.JSON(http.StatusOK, resp)
}

Review comment (suggestion):
```
if *req.Truncate == false {
  c.JSON(http.StatusBadRequest, gin.H{"error": "input length exceeds maximum context length"})
return
}

Code after:

	kvData, err := getKVData(m.ModelPath, false)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	for i, s := range input {
		tokens, err := r.Tokenize(c.Request.Context(), s)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}

		ctxLen := min(opts.NumCtx, int(kvData.ContextLength()))
		if len(tokens) > ctxLen {
			if !truncate {
				c.JSON(http.StatusBadRequest, gin.H{"error": "input length exceeds maximum context length"})
				return
			}

			tokens = tokens[:ctxLen]
			s, err = r.Detokenize(c.Request.Context(), tokens)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
		}

		input[i] = s
	}
	embeddings, err := r.Embed(c.Request.Context(), input)

	if err != nil {
		slog.Error("embedding generation failed", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate embedding"})
		return
	}

	for i, e := range embeddings {
		embeddings[i] = normalize(e)
	}

	resp := api.EmbedResponse{
		Model:      req.Model,
		Embeddings: embeddings,
	}
	c.JSON(http.StatusOK, resp)
}

func normalize(vec []float32) []float32 {