Skip to content

Extract BaseAPIDescriptionScorer shared by LLMDescriptionScorer and TypeSafeDescriptionScorer #357

Open

Description

@voorhs

After #350, LLMDescriptionScorer (llm_encoder.py, 319 lines) and TypeSafeDescriptionScorer (typesafe.py, 416 lines) carry the same machinery side by side:

concern LLMDescriptionScorer TypeSafeDescriptionScorer
max_concurrent / max_per_second params, sync client when max_concurrent is None :111-136 :160-209
_init_event_loop + run_until_complete(aiometer.run_all(...)) fan-out :247-252, :282-291 :331-340, :259-270
per-utterance sync/async ask with failure → uniform row :202-224, :264-268 :342-362, :303-307
clear_cache dropping clients + loop :274-280 :384-388
dump / load with exclude=[asyncio.BaseEventLoop, dict] and a JSON sidecar for the config :293-318 :390-416

They differ only in what one request is (an OpenAI structured-output prompt vs a TypeSafe Choice/Noul question), how its answer maps to a similarity row, and the cache key.

Proposed

BaseAPIDescriptionScorer(DescriptionScorer) owning the shared part: the request fan-out (_ask_many), the event-loop helper, cache-first lookup, the fatal/transient error policy, clear_cache, dump/load. Subclasses implement _ask_one_async(utterance) -> row, _cache_key(utterance), client construction, and the similarity mapping. description_bi / description_cross stay on DescriptionScorer as they are.

Deliberately left out of #350 to keep it reviewable. Best done after the three behavioural fixes so each policy is written once, in the base: #351 (error policy), #353 (event loop), #354 (cache before limiter).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions