Pass the coding keywords as input instead of baking them into the prompt

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 22:38:29 +08:00
co-authored by Claude Opus 5
parent ce4f9ad481
commit 04d5095e44
8 changed files with 303 additions and 119 deletions
+32 -16
View File
@@ -5,6 +5,7 @@
"""Unit tests for the keyword clusterer module."""
import csv
import io
import json
import tempfile
import unittest
from contextlib import redirect_stderr
@@ -32,7 +33,7 @@ class TestClusterKeywords(unittest.TestCase):
self.__dir: Path = Path(tmp.name)
self.__keywords_txt: Path = self.__dir / "keywords.txt"
self.__groups_csv: Path = self.__dir / "groups.csv"
self.__vocabulary_txt: Path = self.__dir / "vocabulary.txt"
self.__keywords_json: Path = self.__dir / "keywords.json"
@staticmethod
def __two_cluster_vectors() -> Vectors:
@@ -102,7 +103,7 @@ class TestClusterKeywords(unittest.TestCase):
"""
argv: list[str] = [
str(self.__keywords_txt), str(self.__groups_csv),
str(self.__vocabulary_txt)]
str(self.__keywords_json)]
argv.extend(extra_args or [])
fake: Any = self.__fake_encode(
vectors if vectors is not None
@@ -125,16 +126,14 @@ class TestClusterKeywords(unittest.TestCase):
newline="") as file:
return list(csv.reader(file))
def __read_vocabulary(self) -> list[str]:
"""Read the vocabulary text file.
def __read_keywords(self) -> list[str]:
"""Read the group name keyword JSON file.
:return: The group names, one per line, with the trailing
empty line from the final newline removed.
:return: The group names under the "keywords" key.
"""
lines: list[str] = self.__vocabulary_txt.read_text(
encoding="utf-8").split("\n")
self.assertEqual(lines[-1], "")
return lines[:-1]
data: dict[str, list[str]] = json.loads(
self.__keywords_json.read_text(encoding="utf-8"))
return data["keywords"]
def test_groups_csv_header_and_ordering(self) -> None:
"""Test the header row and the group/keyword ordering of
@@ -170,17 +169,34 @@ class TestClusterKeywords(unittest.TestCase):
self.assertEqual(
sorted(x[1] for x in rows), sorted(keywords))
def test_vocabulary_file_sorted_medoids(self) -> None:
"""Test that the vocabulary file holds the sorted medoid
group names."""
def test_keywords_json_sorted_medoids(self) -> None:
"""Test that the keyword JSON file holds the sorted medoid
group names plus the extra a-priori keyword."""
self.__write_keywords([
"a-left", "a-center", "a-right",
"b-north", "b-middle", "b-south"])
status: int
status, _ = self.__run_cluster()
self.assertEqual(status, 0)
keywords: list[str] = self.__read_keywords()
self.assertEqual(
self.__read_vocabulary(), ["a-center", "b-middle"])
keywords,
["a-center", "b-middle", cluster_keywords.EXTRA_KEYWORD])
self.assertEqual(keywords, sorted(keywords))
self.assertEqual(len(keywords), 2 + 1)
def test_extra_keyword_absent_from_groups_csv(self) -> None:
"""Test that the extra a-priori keyword appears in no row
of the group membership CSV file."""
self.__write_keywords([
"a-left", "a-center", "a-right",
"b-north", "b-middle", "b-south"])
status: int
status, _ = self.__run_cluster()
self.assertEqual(status, 0)
rows: list[list[str]] = self.__read_groups()
for row in rows:
self.assertNotIn(cluster_keywords.EXTRA_KEYWORD, row)
def test_duplicate_keyword_rejected(self) -> None:
"""Test that a duplicate keyword line fails the run
@@ -192,7 +208,7 @@ class TestClusterKeywords(unittest.TestCase):
self.assertEqual(status, 1)
self.assertIn("duplicate keyword", stderr)
self.assertFalse(self.__groups_csv.exists())
self.assertFalse(self.__vocabulary_txt.exists())
self.assertFalse(self.__keywords_json.exists())
def test_empty_input_rejected(self) -> None:
"""Test that an empty keyword file fails the run without
@@ -204,4 +220,4 @@ class TestClusterKeywords(unittest.TestCase):
self.assertEqual(status, 1)
self.assertIn("no keywords", stderr)
self.assertFalse(self.__groups_csv.exists())
self.assertFalse(self.__vocabulary_txt.exists())
self.assertFalse(self.__keywords_json.exists())
+64 -3
View File
@@ -75,18 +75,32 @@ class TestExportLlmInput(unittest.TestCase):
finally:
session.close()
def __run_export(self) -> tuple[int, str]:
def __run_export(
self, extras: Path | None = None) -> tuple[int, str]:
"""Run the exporter with the standard error captured.
:param extras: The extras JSON file, or None for none.
:return: A tuple of the exit status and the standard
error.
"""
argv: list[str] = [str(self.__output)]
if extras is not None:
argv += ["--extras", str(extras)]
stderr: io.StringIO = io.StringIO()
with redirect_stderr(stderr):
status: int = export_llm_input.main(
[str(self.__output)])
status: int = export_llm_input.main(argv)
return status, stderr.getvalue()
def __write_extras(self, text: str) -> Path:
"""Write an extras file with the given raw text.
:param text: The raw file content.
:return: The path of the written extras file.
"""
path: Path = self.__dir / "extras.json"
path.write_text(text, encoding="utf-8")
return path
@staticmethod
def __read_records(path: Path) -> list[dict[str, str]]:
"""Read the JSONL records of a file.
@@ -167,3 +181,50 @@ class TestExportLlmInput(unittest.TestCase):
nested)
self.assertEqual(records, [
{"id": "song-1", "content": "hello lyrics\n"}])
def test_extras_merges_lyrics_first_in_file_order(
self) -> None:
"""Test that with extras, content is a JSON object whose
first key is lyrics, followed by the extras' keys in
their file order."""
self.__seed([("Hello", "Adele", "hello lyrics\n")])
extras: Path = self.__write_extras(
'{"b": 2, "a": 1}')
status: int
stderr: str
status, stderr = self.__run_export(extras)
self.assertEqual(status, 0)
records: list[dict[str, str]] = self.__read_records(
self.__output)
self.assertEqual(len(records), 1)
content: dict[str, Any] = json.loads(
records[0]["content"])
self.assertEqual(
list(content.keys()), ["lyrics", "b", "a"])
self.assertEqual(content["lyrics"], "hello lyrics\n")
self.assertEqual(content["b"], 2)
self.assertEqual(content["a"], 1)
def test_extras_non_object_fails(self) -> None:
"""Test that a non-object extras file is rejected."""
self.__seed([("Hello", "Adele", "hello lyrics\n")])
extras: Path = self.__write_extras('[1, 2]')
status: int
stderr: str
status, stderr = self.__run_export(extras)
self.assertEqual(status, 1)
self.assertIn("error:", stderr)
self.assertFalse(self.__output.exists())
def test_extras_with_lyrics_key_fails(self) -> None:
"""Test that an extras file carrying a "lyrics" key is
rejected."""
self.__seed([("Hello", "Adele", "hello lyrics\n")])
extras: Path = self.__write_extras(
'{"lyrics": "not allowed"}')
status: int
stderr: str
status, stderr = self.__run_export(extras)
self.assertEqual(status, 1)
self.assertIn("error:", stderr)
self.assertFalse(self.__output.exists())