cat-stack 1.1.0__tar.gz → 1.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {cat_stack-1.1.0 → cat_stack-1.1.1}/PKG-INFO +1 -1
  2. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/__about__.py +1 -1
  3. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_category_analysis.py +15 -6
  4. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_providers.py +9 -4
  5. {cat_stack-1.1.0 → cat_stack-1.1.1}/.gitignore +0 -0
  6. {cat_stack-1.1.0 → cat_stack-1.1.1}/LICENSE +0 -0
  7. {cat_stack-1.1.0 → cat_stack-1.1.1}/README.md +0 -0
  8. {cat_stack-1.1.0 → cat_stack-1.1.1}/pyproject.toml +0 -0
  9. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/cat_stack/__init__.py +0 -0
  10. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/__init__.py +0 -0
  11. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_batch.py +0 -0
  12. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_chunked.py +0 -0
  13. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_embeddings.py +0 -0
  14. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_formatter.py +0 -0
  15. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_pilot_test.py +0 -0
  16. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_prompts.py +0 -0
  17. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_review_ui.py +0 -0
  18. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_tiebreaker.py +0 -0
  19. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_utils.py +0 -0
  20. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/_web_fetch.py +0 -0
  21. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/calls/CoVe.py +0 -0
  22. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/calls/__init__.py +0 -0
  23. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/calls/all_calls.py +0 -0
  24. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/calls/image_CoVe.py +0 -0
  25. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/calls/image_stepback.py +0 -0
  26. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/calls/pdf_CoVe.py +0 -0
  27. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/calls/pdf_stepback.py +0 -0
  28. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/calls/stepback.py +0 -0
  29. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/calls/top_n.py +0 -0
  30. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/classify.py +0 -0
  31. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/explore.py +0 -0
  32. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/extract.py +0 -0
  33. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/image_functions.py +0 -0
  34. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/images/circle.png +0 -0
  35. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/images/cube.png +0 -0
  36. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/images/diamond.png +0 -0
  37. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/images/overlapping_pentagons.png +0 -0
  38. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/images/rectangles.png +0 -0
  39. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/model_reference_list.py +0 -0
  40. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/pdf_functions.py +0 -0
  41. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/prompt_tune.py +0 -0
  42. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/summarize.py +0 -0
  43. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/text_functions.py +0 -0
  44. {cat_stack-1.1.0 → cat_stack-1.1.1}/src/catstack/text_functions_ensemble.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cat-stack
3
- Version: 1.1.0
3
+ Version: 1.1.1
4
4
  Summary: Domain-agnostic text, image, PDF, and DOCX classification engine powered by LLMs
5
5
  Project-URL: Documentation, https://github.com/chrissoria/cat-stack#readme
6
6
  Project-URL: Issues, https://github.com/chrissoria/cat-stack/issues
@@ -1,7 +1,7 @@
1
1
  # SPDX-FileCopyrightText: 2025-present Christopher Soria <chrissoria@berkeley.edu>
2
2
  #
3
3
  # SPDX-License-Identifier: GPL-3.0-or-later
4
- __version__ = "1.1.0"
4
+ __version__ = "1.1.1"
5
5
  __author__ = "Chris Soria"
6
6
  __email__ = "chrissoria@berkeley.edu"
7
7
  __title__ = "cat-stack"
@@ -19,13 +19,22 @@ __all__ = ["has_other_category", "check_category_verbosity"]
19
19
  _MAX_HEURISTIC_WORDS = 4
20
20
 
21
21
  # Tier 1: Anchored patterns — safe at any category length.
22
- # These only match when the keyword IS the category label itself.
22
+ # These only match when the keyword IS the category label itself (or its prefix).
23
23
  _ANCHORED_PATTERNS = [
24
- re.compile(r"^other\s*$", re.IGNORECASE), # exact "Other"
25
- re.compile(r"^other\s*[:(]", re.IGNORECASE), # "Other: ...", "Other (..."
26
- re.compile(r"^n/?a\s*$", re.IGNORECASE), # exact "N/A", "NA"
27
- re.compile(r"^miscellaneous\s*$", re.IGNORECASE), # exact "Miscellaneous"
28
- re.compile(r"^catch[\s-]?all\s*$", re.IGNORECASE), # exact "catch-all"
24
+ re.compile(r"^other\s*$", re.IGNORECASE), # exact "Other"
25
+ re.compile(r"^other\s*[:(]", re.IGNORECASE), # "Other: ...", "Other (..."
26
+ re.compile(r"^n/?a\s*$", re.IGNORECASE), # exact "N/A", "NA"
27
+ re.compile(r"^miscellaneous\s*$", re.IGNORECASE), # exact "Miscellaneous"
28
+ re.compile(r"^catch[\s-]?all\s*$", re.IGNORECASE), # exact "catch-all"
29
+ # Sentiment/opinion contexts — "Neutral" serves as the ambivalent catch-all
30
+ re.compile(r"^neutral\s*$", re.IGNORECASE), # exact "Neutral"
31
+ re.compile(r"^neutral\s*[:(]", re.IGNORECASE), # "Neutral: ...", "Neutral (..."
32
+ # Other common ambivalent labels
33
+ re.compile(r"^ambiguous\s*$", re.IGNORECASE), # exact "Ambiguous"
34
+ re.compile(r"^ambiguous\s*[:(]", re.IGNORECASE), # "Ambiguous: ..."
35
+ re.compile(r"^unclear\s*$", re.IGNORECASE), # exact "Unclear"
36
+ re.compile(r"^unclassified\s*$", re.IGNORECASE), # exact "Unclassified"
37
+ re.compile(r"^unknown\s*$", re.IGNORECASE), # exact "Unknown"
29
38
  ]
30
39
 
31
40
  # Tier 2: Phrase patterns — only applied to short categories (≤ _MAX_HEURISTIC_WORDS).
@@ -772,12 +772,17 @@ def check_ollama_model(model: str, host: str = "localhost", port: int = 11434) -
772
772
  True if model is available, False otherwise
773
773
  """
774
774
  available_models = list_ollama_models(host, port)
775
- # Check for exact match or partial match (e.g., "llama3.2" matches "llama3.2:latest")
776
775
  model_lower = model.lower()
776
+ if ":" in model_lower:
777
+ # User specified an explicit tag (e.g. "qwen2.5:14b") — require exact
778
+ # match. An installed "qwen2.5:7b" must NOT satisfy a request for
779
+ # "qwen2.5:14b"; the previous prefix-match logic let this through,
780
+ # which caused silent classification failures downstream.
781
+ return any(m.lower() == model_lower for m in available_models)
782
+ # User specified just the family (e.g. "llama3.2") — any installed
783
+ # variant of that family counts (e.g. "llama3.2:latest", "llama3.2:7b").
777
784
  return any(
778
- model_lower == m.lower() or
779
- m.lower().startswith(f"{model_lower}:") or
780
- model_lower.startswith(m.lower().split(":")[0])
785
+ m.lower() == model_lower or m.lower().startswith(f"{model_lower}:")
781
786
  for m in available_models
782
787
  )
783
788
 
File without changes
File without changes
File without changes
File without changes