main
rb 86 lines 1.79 KB
Raw
1 require "yaml"
2
3 # Parses a Hugging Face-style "model card": a Markdown README whose leading
4 # section is a YAML front-matter block delimited by `---` lines, e.g.
5 #
6 # ---
7 # license: apache-2.0
8 # base_model: Qwen/Qwen2.5-3B-Instruct
9 # pipeline_tag: text-generation
10 # library_name: gguf
11 # tags:
12 # - text-generation
13 # - gguf
14 # ---
15 # # Qwen2.5-3B-Instruct-GGUF
16 # ...markdown body...
17 #
18 # The metadata drives the model page sidebar and the discovery-page facets; the
19 # body is the rendered card content with the front-matter stripped out.
20 class ModelCard
21 FRONT_MATTER = /\A---\s*\n(.*?\n)---\s*\n?(.*)\z/m
22
23 attr_reader :metadata, :body
24
25 def self.parse(content)
26 new(content)
27 end
28
29 def initialize(content)
30 content = content.to_s
31 if (m = content.match(FRONT_MATTER))
32 @metadata = safe_yaml(m[1])
33 @body = m[2].to_s
34 else
35 @metadata = {}
36 @body = content
37 end
38 end
39
40 def license
41 value("license")
42 end
43
44 def pipeline_tag
45 value("pipeline_tag")
46 end
47
48 def library_name
49 value("library_name") || value("library")
50 end
51
52 def base_model
53 Array(metadata["base_model"]).flatten.compact.first.presence
54 end
55
56 def language
57 Array(metadata["language"]).flatten.compact.map(&:to_s)
58 end
59
60 def datasets
61 Array(metadata["datasets"]).flatten.compact.map(&:to_s)
62 end
63
64 def tags
65 Array(metadata["tags"]).flatten.compact.map(&:to_s).uniq
66 end
67
68 # True when there is any structured metadata worth showing in the sidebar.
69 def present?
70 metadata.present?
71 end
72
73 private
74
75 def value(key)
76 v = metadata[key]
77 v.is_a?(Array) ? v.first : v
78 end
79
80 def safe_yaml(raw)
81 parsed = YAML.safe_load(raw, permitted_classes: [ Date, Time ], aliases: false)
82 parsed.is_a?(Hash) ? parsed : {}
83 rescue Psych::SyntaxError
84 {}
85 end
86 end