Search for a model by name/ID. Returns single model or exits.
(models: list, model_name: str)
| 991 | |
| 992 | |
| 993 | def _search_model(models: list, model_name: str): |
| 994 | """Search for a model by name/ID. Returns single model or exits.""" |
| 995 | query_lower = model_name.lower() |
| 996 | terms = query_lower.split() |
| 997 | size_b = None |
| 998 | |
| 999 | matches = [m for m in models if m.id.lower() == query_lower] |
| 1000 | if not matches: |
| 1001 | matches = [m for m in models if m.id.lower().endswith("/" + query_lower)] |
| 1002 | if not matches: |
| 1003 | text_terms, size_b = _parse_size_tokens(terms) |
| 1004 | matches = [ |
| 1005 | m |
| 1006 | for m in models |
| 1007 | if all(t in m.id.lower() for t in text_terms) |
| 1008 | and (size_b is None or _size_compatible(m, size_b)) |
| 1009 | ] |
| 1010 | |
| 1011 | if not matches: |
| 1012 | console.print(f"[red]No model found matching '{model_name}'.[/]") |
| 1013 | suggestions = [m for m in models if any(t in m.id.lower() for t in terms)] |
| 1014 | if suggestions: |
| 1015 | suggestions.sort(key=lambda m: m.downloads, reverse=True) |
| 1016 | console.print("\n[yellow]Did you mean:[/]") |
| 1017 | for m in suggestions[:5]: |
| 1018 | p = ( |
| 1019 | f"{m.parameter_count / 1e9:.1f}B" |
| 1020 | if m.parameter_count >= 1e9 |
| 1021 | else f"{m.parameter_count / 1e6:.0f}M" |
| 1022 | ) |
| 1023 | console.print(f" • {m.id} ({p})") |
| 1024 | raise typer.Exit(code=1) |
| 1025 | |
| 1026 | if size_b is not None: |
| 1027 | |
| 1028 | def _sort_key(m: ModelInfo) -> tuple: |
| 1029 | id_size = _extract_id_size_b(m.id) |
| 1030 | has_id_size = id_size is not None |
| 1031 | id_dist = abs(id_size - size_b) if has_id_size else float("inf") |
| 1032 | pc_dist = ( |
| 1033 | abs(m.parameter_count / 1e9 - size_b) |
| 1034 | if m.parameter_count > 0 |
| 1035 | else float("inf") |
| 1036 | ) |
| 1037 | return ( |
| 1038 | 0 if (has_id_size or m.parameter_count > 0) else 1, |
| 1039 | id_dist, |
| 1040 | pc_dist, |
| 1041 | -m.downloads, |
| 1042 | ) |
| 1043 | |
| 1044 | matches.sort(key=_sort_key) |
| 1045 | else: |
| 1046 | matches.sort(key=lambda m: m.downloads, reverse=True) |
| 1047 | model = matches[0] |
| 1048 | if len(matches) > 1: |
| 1049 | console.print(f"[dim]Found {len(matches)} matches, using: {model.id}[/]") |
| 1050 | return model |