Fyb3roptik commited on
Commit
2855cb9
·
verified ·
1 Parent(s): e6d5daf

Update SETUP.md: Q6_K specs, quantization-sensitivity troubleshooting note

Browse files
Files changed (1) hide show
  1. SETUP.md +77 -120
SETUP.md CHANGED
@@ -18,7 +18,7 @@ cd marquee
18
  ollama create marquee -f Modelfile
19
  ```
20
 
21
- ~2.8 GB: the model, plus a catalog of ~122,000 films and shows with full cast and crew.
22
 
23
  ## Run
24
 
@@ -28,36 +28,6 @@ marquee serve --library catalog.jsonl --port 8080
28
 
29
  Loads in about 15 seconds.
30
 
31
- ## Use it
32
-
33
- ```bash
34
- curl -X POST localhost:8080/recommend \
35
- -H 'Content-Type: application/json' \
36
- -d '{"title": "The Sopranos", "row_size": 20}'
37
- ```
38
-
39
- ```
40
- Shows like The Sopranos Gomorrah, Boardwalk Empire, The Wire, ZeroZeroZero
41
- More from Tim Van Patten Game of Thrones, Black Mirror, Boardwalk Empire
42
- More with Edie Falco Nurse Jackie, Oz
43
- Shot by Alik Sakharov Game of Thrones, House of Cards
44
- ```
45
-
46
- Or from the command line:
47
-
48
- ```bash
49
- marquee recommend --library catalog.jsonl --seed "Blade Runner 2049" --row-size 20
50
- marquee person --library catalog.jsonl --name "Roger Deakins"
51
- ```
52
-
53
- Set `MARQUEE_LIBRARY` once and drop the flag:
54
-
55
- ```bash
56
- export MARQUEE_LIBRARY=$PWD/catalog.jsonl
57
- export MARQUEE_MODEL=marquee
58
- marquee recommend --seed "Dune (2021)"
59
- ```
60
-
61
  ## API
62
 
63
  ### `POST /recommend`
@@ -69,131 +39,110 @@ curl -X POST localhost:8080/recommend -H 'Content-Type: application/json' \
69
 
70
  ```json
71
  {
72
- "seed": {"id": "tmdb:tv:1398", "title": "The Sopranos", "year": 1999,
73
- "media_type": "tv", "rating": 8.7, "owned": true},
74
  "rows": [
75
  {"type": "thematic", "title": "Shows like The Sopranos",
76
  "items": [
77
- {"id": "tmdb:tv:31050", "title": "The Last Don", "year": 1997,
78
- "media_type": "tv", "rating": 7.1, "owned": true},
79
- {"id": "tmdb:tv:12822", "title": "The Octopus", "year": 1984,
80
- "media_type": "tv", "rating": 7.8, "owned": true}
81
  ]},
82
  {"type": "director", "title": "More from Tim Van Patten",
83
  "items": [
84
- {"id": "tmdb:tv:1399", "title": "Game of Thrones", "year": 2011,
85
- "media_type": "tv", "rating": 8.5, "owned": true},
86
- {"id": "tmdb:tv:1438", "title": "The Wire", "year": 2002,
87
- "media_type": "tv", "rating": 8.6, "owned": true}
88
  ]}
89
  ]
90
  }
91
  ```
92
 
93
- Body fields: `seed_id` **or** `title`, plus optional `year`, `media_type`, `row_size`
94
- (items per row), `owned_only`, `semantic_k`.
95
-
96
- Rows arrive in a fixed order — thematic, franchise, director, cast, crew — so a UI can
97
- render them top to bottom without sorting.
98
 
99
- An ambiguous title returns **409** with the candidates rather than guessing:
 
100
 
101
  ```json
102
- {"error": "5 items match 'Godzilla'; pass seed_id, or narrow with year/media_type",
103
  "matches": [
104
- {"id": "tmdb:movie:124905", "title": "Godzilla", "year": 2014, "media_type": "movie"},
105
- {"id": "tmdb:movie:929", "title": "Godzilla", "year": 1998, "media_type": "movie"},
106
- {"id": "tmdb:movie:1678", "title": "Godzilla", "year": 1954, "media_type": "movie"}
107
  ]}
108
  ```
109
 
110
- `{"title": "Godzilla", "year": 2014}` or `{"title": "Godzilla (2014)"}` resolves it.
111
 
112
- ### `GET /search?q=`
113
 
114
- Matches titles **and** people, because "Scorsese" is not a title but has 109 credits.
 
 
115
 
116
  ```bash
117
- curl 'localhost:8080/search?q=Scorsese&limit=3'
118
  ```
119
 
120
  ```json
121
  {
122
- "query": "Scorsese",
123
- "titles": [
124
- {"id": "tmdb:tv:292130", "title": "Mr. Scorsese", "year": 2025,
125
- "media_type": "tv", "rating": 8.1, "owned": true}
126
- ],
127
- "people": [
128
- {"key": "tmdb:person:1032", "name": "Martin Scorsese",
129
- "roles": {"director": 47, "actor": 50, "writer": 12}, "credits": 109}
130
- ],
131
- "count": 6
132
  }
133
  ```
134
 
135
- `kind=title` or `kind=person` narrows it. Names are matched loosely: `samuel l jackson`,
136
- `Jackson Samuel` and `Inarritu` all resolve.
 
 
 
 
 
 
137
 
138
- ### `GET /person?name=`
139
 
140
- Everything someone is credited on, films and shows in one list, best first.
 
 
 
141
 
142
  ```bash
143
  curl 'localhost:8080/person?name=Roger%20Deakins&limit=3'
144
  ```
145
 
146
  ```json
147
- {
148
- "person": "Roger Deakins",
149
- "count": 3,
150
- "credits": [
151
- {"id": "tmdb:movie:278", "title": "The Shawshank Redemption", "year": 1994,
152
- "media_type": "movie", "rating": 8.7, "score": 8.66, "votes": 31061,
153
- "owned": true, "roles": ["cinematographer"]},
154
- {"id": "tmdb:movie:146233", "title": "Prisoners", "year": 2013,
155
- "media_type": "movie", "rating": 8.1, "score": 8.04, "votes": 13352,
156
- "owned": true, "roles": ["cinematographer"]}
157
- ]
158
- }
159
  ```
160
 
161
- `score` is what the ranking uses: the raw rating damped toward the catalog mean by vote
162
- count, so an 8.2 from 600 votes sits below a 7.6 from 4,300. Someone who both directed
163
- and wrote a title appears once with both roles.
164
 
165
- Options: `media_type`, `owned_only`, `limit`, `by_role=true` for per-role shelves.
166
-
167
- ### `GET /health`
168
 
169
  ```json
170
- {
171
- "status": "ok",
172
- "contract_version": 1,
173
- "model_self_test": {"passed": true, "detail": "contract v1 OK (3/3 clean)"},
174
- "cache": {"entries": 0, "hits": 0, "misses": 0, "max": 2048},
175
- "library_items": 121727,
176
- "owned": 121727,
177
- "requestable": 0,
178
- "model": "marquee",
179
- "backend": "http://localhost:11434/v1"
180
- }
181
  ```
182
 
183
- `status` is `degraded` if the self-test fails the model and package disagree, or the
184
- chat template is wrong.
185
-
186
- ### `DELETE /cache`
187
-
188
- Responses are cached per seed. Call this after a library rescan or you will serve rows
189
- referring to items you no longer have.
190
-
191
- `/search` and `/person` are index lookups with no model call, so they are instant. Only
192
- `/recommend` uses the GPU.
193
 
194
  ## Restricting results to your own library (optional)
195
 
196
- By default it recommends from the whole 122k catalog, whether or not you own the title.
197
 
198
  To mark what is actually on your server -- so a UI can show a Request button on the rest
199
  -- export your library and join it:
@@ -221,7 +170,7 @@ curl -X POST localhost:8080/recommend -H 'Content-Type: application/json' \
221
  `/health` reports the split:
222
 
223
  ```json
224
- {"library_items": 121727, "owned": 1670, "requestable": 120057}
225
  ```
226
 
227
  **Jellyfin**: `/Items?Recursive=true&Fields=ProviderIds` gives `ProviderIds.Tmdb`.
@@ -231,9 +180,9 @@ curl -X POST localhost:8080/recommend -H 'Content-Type: application/json' \
231
 
232
  | | |
233
  |---|---|
234
- | VRAM | ~3.5 GB. A 4 GB card is fine; CPU works but is slower. |
235
- | RAM | ~2.2 GB for the 122k catalog |
236
- | Disk | ~2.8 GB |
237
  | Latency | ~1 s per request on an RTX 3060; cached responses are instant |
238
 
239
  ## Troubleshooting
@@ -247,22 +196,30 @@ ollama show --template marquee # must NOT be just "{{ .Prompt }}"
247
  Recreate from the supplied `Modelfile`, and do not remove its `TEMPLATE` block.
248
 
249
  **Output is valid sometimes and not others.**
250
- `temperature` is too high. Structured output needs near-greedy decoding: 0.1 gave 8/8
251
- clean in testing, 0.3 gave 5/8. The Modelfile ships 0.1.
 
 
 
 
 
252
 
253
  **Self-test fails at startup.**
254
  The model and the package are built against different contract versions. Both must be
255
  contract v1.
256
 
257
  **A title I own is missing.**
258
- The catalog covers ~122k titles with 10+ TMDB votes, plus all anime. Genuinely obscure
259
- releases may not be there. `marquee harvest --min-votes 0` rebuilds a wider catalog with
260
- your own free TMDB key.
261
 
262
  ## Data
263
 
264
- Catalog metadata is from TMDB. This product uses the TMDB API but is not endorsed or
265
- certified by TMDB.
 
 
 
 
266
 
267
  ## Licence
268
 
 
18
  ollama create marquee -f Modelfile
19
  ```
20
 
21
+ ~3 GB: the model, plus a catalog of ~195,000 films and shows with full cast and crew.
22
 
23
  ## Run
24
 
 
28
 
29
  Loads in about 15 seconds.
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  ## API
32
 
33
  ### `POST /recommend`
 
39
 
40
  ```json
41
  {
42
+ "seed": {"id": "wd:Q23628", "title": "The Sopranos", "year": 1999,
43
+ "media_type": "tv", "rating": 0.0, "owned": true},
44
  "rows": [
45
  {"type": "thematic", "title": "Shows like The Sopranos",
46
  "items": [
47
+ {"id": "wd:Q...", "title": "Gomorrah", "year": 2014,
48
+ "media_type": "tv", "owned": true},
49
+ {"id": "wd:Q...", "title": "Boardwalk Empire", "year": 2010,
50
+ "media_type": "tv", "owned": true}
51
  ]},
52
  {"type": "director", "title": "More from Tim Van Patten",
53
  "items": [
54
+ {"id": "wd:Q...", "title": "Game of Thrones", "year": 2011,
55
+ "media_type": "tv", "owned": true}
 
 
56
  ]}
57
  ]
58
  }
59
  ```
60
 
61
+ Body: `seed_id` **or** `title`, plus optional `year`, `media_type`, `row_size`,
62
+ `owned_only`, `semantic_k`. Rows arrive in a fixed order -- thematic, franchise,
63
+ director, cast, crew.
 
 
64
 
65
+ An ambiguous title returns **409** with the candidates rather than guessing. A catalog
66
+ this size holds many remakes sharing a bare title:
67
 
68
  ```json
69
+ {"error": "22 items match 'Macbeth'; pass seed_id, or narrow with year/media_type",
70
  "matches": [
71
+ {"id": "wd:Q15934383", "title": "Macbeth", "year": 2015, "media_type": "movie"},
72
+ {"id": "wd:Q2573008", "title": "Macbeth", "year": 1951, "media_type": "movie"}
 
73
  ]}
74
  ```
75
 
76
+ `{"title": "Macbeth", "year": 2015}` or `{"title": "Macbeth (2015)"}` resolves it.
77
 
78
+ ### `GET /metadata` and `POST /metadata/batch`
79
 
80
+ Full catalog record for one item, or up to 500 in one call. Pure index lookups -- no
81
+ model, no GPU. Look up by `id`, `tmdb_id`, `imdb_id` (all exact), or `title` (fuzzy,
82
+ can be ambiguous like `/recommend`).
83
 
84
  ```bash
85
+ curl 'localhost:8080/metadata?tmdb_id=335984'
86
  ```
87
 
88
  ```json
89
  {
90
+ "id": "wd:Q21500755", "title": "Blade Runner 2049", "media_type": "movie",
91
+ "year": 2017, "genres": ["cyberpunk", "dystopian film", "neo-noir"],
92
+ "people": [{"name": "Denis Villeneuve", "role": "director"},
93
+ {"name": "Roger Deakins", "role": "cinematographer"}],
94
+ "summary": "Blade Runner 2049 is a 2017 American science fiction film...",
95
+ "franchise": "Blade Runner", "runtime_min": 164,
96
+ "country": "United Kingdom", "language": "English",
97
+ "external": {"wikidata": "Q21500755", "tmdb": "335984", "imdb": "tt1856101"}
 
 
98
  }
99
  ```
100
 
101
+ ```bash
102
+ curl -X POST localhost:8080/metadata/batch -H 'Content-Type: application/json' -d '{
103
+ "queries": [{"tmdb_id": 335984}, {"imdb_id": "tt0141842"}]
104
+ }'
105
+ ```
106
+
107
+ Every query gets a result in the order sent -- found, ambiguous with candidates, or
108
+ not found -- so you can zip the response against your input.
109
 
110
+ ### `GET /search?q=` and `GET /person?name=`
111
 
112
+ `/search` matches titles **and** people in one call -- "Scorsese" isn't a title but has
113
+ 109 credits. `/person` returns everything someone worked on, films and shows together,
114
+ ranked by a popularity-weighted score, deduplicated across roles. Both are index
115
+ lookups, no model call.
116
 
117
  ```bash
118
  curl 'localhost:8080/person?name=Roger%20Deakins&limit=3'
119
  ```
120
 
121
  ```json
122
+ {"person": "Roger Deakins", "count": 3, "credits": [
123
+ {"id": "wd:...", "title": "The Shawshank Redemption", "year": 1994,
124
+ "score": 8.66, "roles": ["cinematographer"]}
125
+ ]}
 
 
 
 
 
 
 
 
126
  ```
127
 
128
+ `score` is what ranking actually uses -- popularity-weighted, so a well-known film
129
+ outranks an obscure one even without a raw rating to sort by.
 
130
 
131
+ ### `GET /health` and `DELETE /cache`
 
 
132
 
133
  ```json
134
+ {"status": "ok", "contract_version": 1,
135
+ "model_self_test": {"passed": true, "detail": "contract v1 OK (3/3 clean)"},
136
+ "library_items": 194509, "owned": 194509, "requestable": 0}
 
 
 
 
 
 
 
 
137
  ```
138
 
139
+ `status` is `degraded` if the self-test fails -- model and package disagree, or the
140
+ chat template is wrong. Recommendations are cached per seed; call `DELETE /cache`
141
+ after a library rescan or you'll serve rows referring to items you no longer have.
 
 
 
 
 
 
 
142
 
143
  ## Restricting results to your own library (optional)
144
 
145
+ By default it recommends from the whole 195k-title catalog, whether or not you own it.
146
 
147
  To mark what is actually on your server -- so a UI can show a Request button on the rest
148
  -- export your library and join it:
 
170
  `/health` reports the split:
171
 
172
  ```json
173
+ {"library_items": 194509, "owned": 1670, "requestable": 192839}
174
  ```
175
 
176
  **Jellyfin**: `/Items?Recursive=true&Fields=ProviderIds` gives `ProviderIds.Tmdb`.
 
180
 
181
  | | |
182
  |---|---|
183
+ | VRAM | ~4.7 GB (Q6_K at 6144 context). A 6 GB card is fine; CPU works but is slower. |
184
+ | RAM | ~2.5 GB for the 195k-title catalog |
185
+ | Disk | ~3.6 GB |
186
  | Latency | ~1 s per request on an RTX 3060; cached responses are instant |
187
 
188
  ## Troubleshooting
 
196
  Recreate from the supplied `Modelfile`, and do not remove its `TEMPLATE` block.
197
 
198
  **Output is valid sometimes and not others.**
199
+ Two independent causes, both already fixed in the shipped model/Modelfile:
200
+ - `temperature` too high -- structured output needs near-greedy decoding. 0.1 gave 8/8
201
+ clean in testing, 0.3 gave 5/8. The Modelfile ships 0.1.
202
+ - Quantizing below Q6_K measurably hurts this model: on 20 held-out seeds through real
203
+ Ollama serving, Q4_K_M gave 1/20 clean vs Q6_K's 19/20, same weights, same decoding --
204
+ llama.cpp's 4-bit rounding alone is enough to collapse it into repeating
205
+ `<tool_call>` tokens instead of JSON. Don't requantize to Q4_K_M to save disk space.
206
 
207
  **Self-test fails at startup.**
208
  The model and the package are built against different contract versions. Both must be
209
  contract v1.
210
 
211
  **A title I own is missing.**
212
+ The catalog covers ~195k titles from Wikidata. Genuinely obscure releases may not be
213
+ there. `marquee harvest-wikidata --min-votes 0` (if rebuilding) widens coverage.
 
214
 
215
  ## Data
216
 
217
+ The catalog is built from Wikidata (CC0) and Wikipedia (summaries, embedded then
218
+ discarded -- never redistributed as text). No TMDB data is shipped.
219
+
220
+ No poster/image URLs are included -- text and structured facts only. Pull artwork
221
+ from your media server, or from TMDB/Fanart yourself using the `external.tmdb`/
222
+ `external.imdb` ids returned by `/metadata`.
223
 
224
  ## Licence
225