fast_json.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package sample
  2. import (
  3. "errors"
  4. "fmt"
  5. "math"
  6. "github.com/ollama/ollama/model"
  7. )
  8. type JSONState int
  9. const (
  10. StateStart JSONState = iota
  11. StateInObject
  12. StateInObjectKey
  13. StateNewline
  14. StateTab
  15. StateSpace
  16. StateInString
  17. StateInInt
  18. StateInFloat
  19. StateInBool
  20. StateInNull
  21. StateInArray
  22. StateInColon
  23. StateInComma
  24. StateInStringEnd
  25. StateInObjectKeyEnd
  26. StateTerminate
  27. StateEnd
  28. )
  29. func (s JSONState) String() string {
  30. switch s {
  31. case StateStart:
  32. return "StateStart"
  33. case StateInObject:
  34. return "StateInObject"
  35. case StateInObjectKey:
  36. return "StateInObjectKey"
  37. case StateInString:
  38. return "StateInString"
  39. case StateNewline:
  40. return "StateNewline"
  41. case StateTab:
  42. return "StateTab"
  43. case StateSpace:
  44. return "StateSpace"
  45. case StateInInt:
  46. return "StateInInt"
  47. case StateInFloat:
  48. return "StateInFloat"
  49. case StateInColon:
  50. return "StateInColon"
  51. case StateInBool:
  52. return "StateInBool"
  53. case StateInNull:
  54. return "StateInNull"
  55. case StateInArray:
  56. return "StateInArray"
  57. case StateEnd:
  58. return "StateEnd"
  59. case StateInComma:
  60. return "StateInComma"
  61. case StateInObjectKeyEnd:
  62. return "StateInObjectKeyEnd"
  63. case StateTerminate:
  64. return "StateTerminate"
  65. case StateInStringEnd:
  66. return "StateInStringEnd"
  67. default:
  68. return fmt.Sprintf("Unknown state: %d", s)
  69. }
  70. }
  71. type JSONSampler struct {
  72. curNode *Node
  73. proc model.TextProcessor
  74. stack []*Node
  75. bracketCounter int
  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. stack: []*Node{},
  87. bracketCounter: 0,
  88. }
  89. return js, nil
  90. }
  91. func isTokenSubset(subset, superset []int32) bool {
  92. freq1 := make(map[int32]int)
  93. freq2 := make(map[int32]int)
  94. for _, v := range subset {
  95. freq1[v]++
  96. }
  97. for _, v := range superset {
  98. freq2[v]++
  99. }
  100. isSubset := true
  101. for k, count1 := range freq1 {
  102. count2 := freq2[k]
  103. if count1 > count2 {
  104. isSubset = false
  105. break
  106. }
  107. }
  108. return isSubset
  109. }
  110. func (s *JSONSampler) UpdateState(tokenSlice []int32) error {
  111. // fmt.Printf("Updating state with token: %v\n", tokenSlice)
  112. // fmt.Printf("Current state: %s\n", s.curNode.State)
  113. // fmt.Println("tokenSlice", tokenSlice)
  114. // todo: account for strings here
  115. objectTokens, err := ComputeTokenVariants([]string{"{", " {", "{\n", " {\n"}, s.proc)
  116. if err != nil {
  117. return err
  118. }
  119. // only move to terminate state if stack is empty
  120. if s.curNode.State == StateEnd {
  121. fmt.Println("debug: node.State", s.curNode.State)
  122. if len(s.stack) > 0 {
  123. s.stack = s.stack[:len(s.stack)-1]
  124. fmt.Println("popped and cur state", s.curNode.State)
  125. return nil
  126. }
  127. return nil
  128. }
  129. for node, edge := range s.curNode.TransitionEdges {
  130. for _, validToken := range edge {
  131. if isTokenSubset(tokenSlice, validToken) {
  132. s.curNode = node
  133. for _, token := range objectTokens {
  134. if isTokenSubset(tokenSlice, token) {
  135. fmt.Println("Appending to stack", s.curNode.State)
  136. s.stack = append(s.stack, s.curNode)
  137. }
  138. }
  139. // fmt.Printf("Transitioned to state: %s\n", node.State)
  140. return nil
  141. }
  142. }
  143. }
  144. for node, edge := range s.curNode.TransitionEdges {
  145. for _, validToken := range edge {
  146. if len(validToken) == 1 && validToken[0] == -1 || validToken[0] == -2 {
  147. s.curNode = node
  148. // fmt.Printf("Accepting any token, staying in state: %s\n", node.State)
  149. return nil
  150. }
  151. }
  152. }
  153. fmt.Println("invalid token ", tokenSlice)
  154. dec, err := s.proc.Decode(tokenSlice)
  155. if err != nil {
  156. return err
  157. }
  158. fmt.Println("decoded token ", dec)
  159. return errors.New("invalid token")
  160. }
  161. func (s *JSONSampler) Sample(logits []float64) ([]float64, error) {
  162. fmt.Printf("Sampling in state: %s\n", s.curNode.State)
  163. var err error
  164. switch s.curNode.State {
  165. case StateTerminate:
  166. for i := range logits {
  167. if s.proc.Is(uint32(i), model.SpecialEOS) {
  168. logits[i] = 1.0
  169. } else {
  170. logits[i] = math.NaN()
  171. }
  172. }
  173. return logits, nil
  174. case StateInInt:
  175. validStates := []int32{}
  176. minus, err := s.proc.Encode("-")
  177. if err != nil {
  178. return nil, err
  179. }
  180. digits := make([][]int32, 10)
  181. for i := 0; i < 10; i++ {
  182. digits[i], err = s.proc.Encode(fmt.Sprintf("%d", i))
  183. if err != nil {
  184. return nil, err
  185. }
  186. }
  187. // Allow "-" and digits 0-9 at start
  188. for i := range logits {
  189. for _, d := range digits {
  190. if len(d) == 1 && int32(i) == d[0] {
  191. validStates = append(validStates, int32(i))
  192. }
  193. }
  194. if len(minus) == 1 && int32(i) == minus[0] {
  195. validStates = append(validStates, int32(i))
  196. }
  197. }
  198. return logits, nil
  199. case StateInString:
  200. penalizeNewlineVariants := []string{"\n", " \"\n"}
  201. penalizeNewlineToks, err := ComputeTokenVariants(penalizeNewlineVariants, s.proc)
  202. if err != nil {
  203. return nil, err
  204. }
  205. penalizeNewlineToks = append(penalizeNewlineToks, []int32{702})
  206. logits, err = s.maskSpecificLogits(logits, penalizeNewlineToks)
  207. if err != nil {
  208. return nil, err
  209. }
  210. validStates := getValidStates(s.curNode)
  211. logits, err = s.maskLogits(logits, validStates)
  212. if err != nil {
  213. return nil, err
  214. }
  215. return logits, nil
  216. default:
  217. validStates := getValidStates(s.curNode)
  218. logits, err = s.maskLogits(logits, validStates)
  219. if err != nil {
  220. return nil, err
  221. }
  222. return logits, nil
  223. }
  224. }
  225. func getValidStates(node *Node) []int32 {
  226. validStates := []int32{}
  227. for _, edge := range node.TransitionEdges {
  228. for _, token := range edge {
  229. validStates = append(validStates, token...)
  230. }
  231. }
  232. return validStates
  233. }
  234. func (s *JSONSampler) maskLogits(logits []float64, validStates []int32) ([]float64, error) {
  235. // fmt.Printf("Masking logits with valid states: %v\n", validStates)
  236. for i := range logits {
  237. isValid := false
  238. for _, token := range validStates {
  239. if token == -1 {
  240. // fmt.Println("Found sentinel token, returning unmasked logits")
  241. return logits, nil
  242. }
  243. if i == int(token) {
  244. // fmt.Printf("Found valid token: %d\n", token)
  245. isValid = true
  246. break
  247. }
  248. }
  249. if !isValid {
  250. logits[i] = math.NaN()
  251. }
  252. }
  253. return logits, nil
  254. }
  255. func (s *JSONSampler) maskSpecificLogits(logits []float64, tokensToMask []token) ([]float64, error) {
  256. // fmt.Printf("Masking specific logits: %v\n", tokensToMask)
  257. for i := range logits {
  258. for _, token := range tokensToMask {
  259. for _, chunked := range token {
  260. if int(chunked) == i {
  261. logits[i] = math.NaN()
  262. }
  263. }
  264. }
  265. }
  266. return logits, nil
  267. }