WUT_Computer_Science/Programming/NLP/rating.py
Krzysztof kuhy Rudnicki b017c7500e NLP: zero findings, and two real bugs found on the way
384 findings to none across ten scripts. Most of it is annotation and
docstring work, but the lint surfaced two defects that had nothing to do with
style:

- `gpt_chunks.py` stripped its GPT preamble with
  `input_string.strip("iSTS chunks:")`. str.strip takes a SET OF CHARACTERS,
  not a prefix, so it also ate any leading i/S/T/s/c/h/u/n/k/space/colon:
  "iSTS chunks: sentence one" came out as "entence one", silently losing the
  first letter of every chunked sentence. Now removeprefix. ruff found it as
  B005 + PLE1310.
- `is_numbered_line_format` had `for string in string` in its list branch,
  which raises NameError the moment a list is passed (F821).
- `processing.test_XML()` read a module-level `alignments_data` that does not
  exist at module scope; it only ever ran when pasted into a live session. It
  takes the data as an argument now and is renamed `log_first_alignment` so
  pytest stops collecting a non-test as a test.

Also real rather than cosmetic:

- The OpenAI key was a placeholder string literal in three files, one of them
  carrying a "Replace me with os.environ['API_KEY']" comment. All three read
  OPENAI_API_KEY now and say so when it is missing -- as committed, none of
  these scripts could actually run.
- `rating.rate_similarity` was submitted unfinished: it built a client, never
  touched its two arguments and returned None despite `-> str`. It now makes
  the same call the rest of the package makes.
- The two 2 kB alignment prompts and one 344-character chunking prompt moved
  to prompts/*.txt. Wrapping them in source would have put newlines into the
  middle of the prompt.
- `format_alignments` parsed GPT's replies with `eval()`; the file holds one
  repr()'d string per line, so ast.literal_eval is both sufficient and safe.
- NLP/__init__.py deleted -- it made the course directory a package named
  "NLP", which is an invalid module name (N999) and which nothing imports;
  the scripts use plain `import processing`.

INP001 is settled the same way throughout: a coursework file run as
`python x.py` gets a shebang and the executable bit, which is what it is,
rather than an __init__.py that would make a course code into a module name.

Verified: every module compiles and `./run.sh run Programming/NLP` is clean.
The scripts themselves need the SemEval corpus and a paid API key, so they
are not executed here.

Repo-wide: 3,159 findings -> 2,775.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE
2026-08-28 20:13:19 +02:00

43 lines
1.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""Ask the model to rate how similar two chunks are."""
import os
from openai import OpenAI
def _api_key() -> str:
"""Return OPENAI_API_KEY, or explain that it is missing."""
key = os.environ.get("OPENAI_API_KEY")
if not key:
msg = "set OPENAI_API_KEY to run the rating script"
raise RuntimeError(msg)
return key
def rate_similarity(c1: list[str], c2: list[str]) -> str:
"""Rate the similarity of two chunk lists on the course's 0-5 scale.
This was submitted unfinished: it built a client and stopped, so ``c1``
and ``c2`` were never used and the function returned None despite being
annotated ``-> str``. The call below is the one the rest of this package
already makes (see gpt_alignment.call_api); nothing else about the
original is changed.
"""
client = OpenAI(api_key=_api_key())
response = client.chat.completions.create(
model="gpt-3.5-turbo-1106",
messages=[
{
"role": "user",
"content": (
"Rate on a 0-5 scale how similar these two chunk lists are, "
"where 0 is unrelated and 5 is the same meaning. Answer with "
"the number alone.\n"
f"1: {c1}\n2: {c2}"
),
}
],
)
return str(response.choices[0].message.content).strip()