prompt.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package server
  2. import (
  3. "bytes"
  4. "context"
  5. "log/slog"
  6. "slices"
  7. "github.com/ollama/ollama/api"
  8. "github.com/ollama/ollama/llm"
  9. "github.com/ollama/ollama/template"
  10. )
  11. func chatPrompt(ctx context.Context, r *runnerRef, msgs []api.Message) (prompt string, images []llm.ImageData, _ error) {
  12. // extract system messages which should always be included
  13. var system []api.Message
  14. msgs = slices.DeleteFunc(msgs, func(m api.Message) bool {
  15. if m.Role == "system" {
  16. system = append(system, m)
  17. return true
  18. }
  19. return false
  20. })
  21. if len(system) == 0 && r.model.System != "" {
  22. // add model system prompt since it wasn't provided
  23. system = append(system, api.Message{Role: "system", Content: r.model.System})
  24. }
  25. n := len(msgs) - 1
  26. for i := n - 1; i >= 0; i-- {
  27. var b bytes.Buffer
  28. if err := r.model.Template.Execute(&b, template.Values{Messages: append(system, msgs[i:]...)}); err != nil {
  29. return "", nil, err
  30. }
  31. s, err := r.llama.Tokenize(ctx, b.String())
  32. if err != nil {
  33. return "", nil, err
  34. }
  35. c := len(s)
  36. if r.model.ProjectorPaths != nil {
  37. for _, m := range msgs[i:] {
  38. // TODO: get image embedding length from project metadata
  39. c += 768 * len(m.Images)
  40. }
  41. }
  42. if c > r.NumCtx {
  43. slog.Debug("truncating input messages which exceed context length", "truncated", len(msgs[i:]))
  44. break
  45. } else {
  46. n = i
  47. }
  48. }
  49. var b bytes.Buffer
  50. if err := r.model.Template.Execute(&b, template.Values{Messages: append(system, msgs[n:]...)}); err != nil {
  51. return "", nil, err
  52. }
  53. for _, m := range msgs[n:] {
  54. for _, i := range m.Images {
  55. images = append(images, llm.ImageData{
  56. ID: len(images),
  57. Data: i,
  58. })
  59. }
  60. }
  61. return b.String(), images, nil
  62. }