grammar_test.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package llama
  2. import (
  3. "bufio"
  4. "bytes"
  5. "strings"
  6. "testing"
  7. )
  8. // https://github.com/ollama/ollama/issues/7978
  9. const issue7978JSONSchema = `{
  10. "type": "object",
  11. "properties": {
  12. "steps": {
  13. "type": "array",
  14. "items": {
  15. "type": "object",
  16. "properties": {
  17. "explanation": { "type": "string" },
  18. "output": { "type": "string" }
  19. },
  20. "required": ["explanation", "output"],
  21. "additionalProperties": false
  22. }
  23. },
  24. "final_answer": { "type": "string" }
  25. },
  26. "required": ["steps", "final_answer"],
  27. "additionalProperties": false
  28. }`
  29. func TestIssue7978(t *testing.T) {
  30. g := SchemaToGrammar([]byte(issue7978JSONSchema))
  31. if g == nil {
  32. t.Fatal("failed to convert JSON schema to grammar")
  33. }
  34. t.Logf("grammar:\n%s", g)
  35. t.Log()
  36. var sawSteps bool
  37. s := bufio.NewScanner(bytes.NewReader(g))
  38. for s.Scan() {
  39. line := s.Text()
  40. if strings.Contains(line, "steps") {
  41. sawSteps = true
  42. }
  43. if strings.Contains(line, "final-answer") && !sawSteps {
  44. t.Error("expected 'steps' before 'final-answer'")
  45. }
  46. }
  47. }
  48. func TestSchemaToGrammer(t *testing.T) {
  49. cases := []struct {
  50. schema string
  51. prefix []byte // nil is check as nil
  52. }{
  53. {`invalid`, nil},
  54. // Simple heuristic/smoke test
  55. {`{"type":"object"}`, []byte("root ::= object")},
  56. }
  57. for _, c := range cases {
  58. t.Run("x", func(t *testing.T) {
  59. g := SchemaToGrammar([]byte(c.schema))
  60. if c.prefix == nil && g != nil {
  61. t.Fatalf("grammar = %v, want nil", g)
  62. }
  63. if !bytes.HasPrefix(g, c.prefix) {
  64. t.Errorf("grammar = %q, want %q", g, c.prefix)
  65. }
  66. })
  67. }
  68. }