fast_json.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. package sample
  2. import (
  3. "errors"
  4. "fmt"
  5. "math"
  6. "slices"
  7. "github.com/ollama/ollama/model"
  8. )
  9. type JSONState int
  10. const (
  11. StateStart JSONState = iota
  12. StateInObject
  13. StateInObjectKey
  14. StateNewline
  15. StateTab
  16. StateSpace
  17. StateInString
  18. StateInInt
  19. StateInFloat
  20. StateInBool
  21. StateInNull
  22. StateInArray
  23. StateInColon
  24. StateInComma
  25. StateInStringEnd
  26. StateInObjectKeyEnd
  27. StateTerminate
  28. StateEnd
  29. )
  30. func (s JSONState) String() string {
  31. switch s {
  32. case StateStart:
  33. return "StateStart"
  34. case StateInObject:
  35. return "StateInObject"
  36. case StateInObjectKey:
  37. return "StateInObjectKey"
  38. case StateInString:
  39. return "StateInString"
  40. case StateNewline:
  41. return "StateNewline"
  42. case StateTab:
  43. return "StateTab"
  44. case StateSpace:
  45. return "StateSpace"
  46. case StateInInt:
  47. return "StateInInt"
  48. case StateInFloat:
  49. return "StateInFloat"
  50. case StateInColon:
  51. return "StateInColon"
  52. case StateInBool:
  53. return "StateInBool"
  54. case StateInNull:
  55. return "StateInNull"
  56. case StateInArray:
  57. return "StateInArray"
  58. case StateEnd:
  59. return "StateEnd"
  60. case StateInComma:
  61. return "StateInComma"
  62. case StateInObjectKeyEnd:
  63. return "StateInObjectKeyEnd"
  64. case StateTerminate:
  65. return "StateTerminate"
  66. case StateInStringEnd:
  67. return "StateInStringEnd"
  68. default:
  69. return fmt.Sprintf("Unknown state: %d", s)
  70. }
  71. }
  72. type JSONSampler struct {
  73. curNode *Node
  74. proc model.TextProcessor
  75. stack []*Node
  76. }
  77. func NewJSONSampler(proc model.TextProcessor) (*JSONSampler, error) {
  78. // fmt.Println("Creating new JSON sampler")
  79. startNode, err := buildStateMachine(proc)
  80. if err != nil {
  81. return nil, err
  82. }
  83. js := &JSONSampler{
  84. curNode: startNode,
  85. proc: proc,
  86. }
  87. return js, nil
  88. }
  89. func (s *JSONSampler) UpdateState(tokenSlice []int32) error {
  90. // fmt.Printf("Updating state with token: %v\n", tokenSlice)
  91. // fmt.Printf("Current state: %s\n", s.curNode.State)
  92. // fmt.Println("tokenSlice", tokenSlice)
  93. // todo: account for strings here
  94. for node, edge := range s.curNode.TransitionEdges {
  95. for _, validToken := range edge {
  96. if slices.Equal(tokenSlice, validToken) {
  97. s.curNode = node
  98. // fmt.Printf("Transitioned to state: %s\n", node.State)
  99. return nil
  100. }
  101. }
  102. }
  103. for node, edge := range s.curNode.TransitionEdges {
  104. for _, validToken := range edge {
  105. if len(validToken) == 1 && validToken[0] == -1 || validToken[0] == -2 {
  106. s.curNode = node
  107. // fmt.Printf("Accepting any token, staying in state: %s\n", node.State)
  108. return nil
  109. }
  110. }
  111. }
  112. fmt.Println("invalid token ", tokenSlice)
  113. return errors.New("invalid token")
  114. }
  115. func (s *JSONSampler) Sample(logits []float64) ([]float64, error) {
  116. fmt.Printf("Sampling in state: %s\n", s.curNode.State)
  117. var err error
  118. switch s.curNode.State {
  119. case StateTerminate:
  120. for i := range logits {
  121. if s.proc.Is(uint32(i), model.SpecialEOS) {
  122. logits[i] = 1.0
  123. } else {
  124. logits[i] = math.NaN()
  125. }
  126. }
  127. return logits, nil
  128. case StateInInt:
  129. validStates := []int32{}
  130. minus, err := s.proc.Encode("-")
  131. if err != nil {
  132. return nil, err
  133. }
  134. digits := make([][]int32, 10)
  135. for i := 0; i < 10; i++ {
  136. digits[i], err = s.proc.Encode(fmt.Sprintf("%d", i))
  137. if err != nil {
  138. return nil, err
  139. }
  140. }
  141. // Allow "-" and digits 0-9 at start
  142. for i := range logits {
  143. for _, d := range digits {
  144. if len(d) == 1 && int32(i) == d[0] {
  145. validStates = append(validStates, int32(i))
  146. }
  147. }
  148. if len(minus) == 1 && int32(i) == minus[0] {
  149. validStates = append(validStates, int32(i))
  150. }
  151. }
  152. return logits, nil
  153. default:
  154. validStates := getValidStates(s.curNode)
  155. logits, err = s.maskLogits(logits, validStates)
  156. if err != nil {
  157. return nil, err
  158. }
  159. return logits, nil
  160. }
  161. }
  162. func getValidStates(node *Node) []int32 {
  163. validStates := []int32{}
  164. for _, edge := range node.TransitionEdges {
  165. for _, token := range edge {
  166. validStates = append(validStates, token...)
  167. }
  168. }
  169. return validStates
  170. }
  171. func (s *JSONSampler) maskLogits(logits []float64, validStates []int32) ([]float64, error) {
  172. // fmt.Printf("Masking logits with valid states: %v\n", validStates)
  173. for i := range logits {
  174. isValid := false
  175. for _, token := range validStates {
  176. if token == -1 {
  177. // fmt.Println("Found sentinel token, returning unmasked logits")
  178. return logits, nil
  179. }
  180. if i == int(token) {
  181. // fmt.Printf("Found valid token: %d\n", token)
  182. isValid = true
  183. break
  184. }
  185. }
  186. if !isValid {
  187. logits[i] = math.NaN()
  188. }
  189. }
  190. return logits, nil
  191. }