Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,21 @@ Always check the package-level `AGENTS.md` for file-specific rules
- Formatting/linting: no repo-wide formatter is configured; follow existing
file style and do not add new lint tools unless requested.

## LLM structured-output schemas (Literal vs Enum)
- In Pydantic models used for LLM structured output, use `Literal["a", "b"]`
instead of an `Enum` type for field annotations.
- Reason: `Enum` fields cause `model_json_schema()` to emit `$defs`/`$ref`
indirection. Some structured-output backends (e.g. MLX Outlines for local
inference) cannot resolve `$defs`/`$ref` and fail silently or error out.
`Literal` produces a flat schema with an inline `enum` array, which is
universally supported.
- Keep the canonical `str(Enum)` class in the same module as the single source
of truth for valid values; the `Literal` duplicates those values in the
schema annotation only.
- A CI parity test (`test_enum_literal_parity.py`) asserts that every `Literal`
field stays in sync with its corresponding `Enum`. If you add or rename an
Enum member, update the matching `Literal` and vice versa.

## Python version
- Canonical version is defined in each package `pyproject.toml`.

Expand Down
18 changes: 18 additions & 0 deletions presets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Presets

LM Studio preset files that configure local models for use with PlanExe.

## What are LM Studio presets?

LM Studio presets are JSON configs that tune model parameters (temperature, context length, max tokens, system prompt, thinking mode, etc.) for a specific use case. They can be published to the LM Studio Hub so users can apply them with one click.

## lmstudio-planexe.json

Optimizes any local LM Studio model for PlanExe's structured JSON pipeline:

- **Temperature 0.2** — deterministic, schema-compliant output.
- **Context window 32768 / max tokens 4096** — avoids llama_index's low defaults that silently truncate prompts.
- **System prompt** — instructs the model to return only valid JSON matching the requested schema, with no markdown fences or filler.
- **Thinking disabled** — turns off thinking/reasoning mode for models that support it (e.g. Qwen 3, GLM-4), since PlanExe needs raw JSON, not chain-of-thought.

This preset complements the `llm_config/local.json` config, which tells PlanExe *how to call* LM Studio (via `OpenAILike` with `should_use_structured_outputs: true` for grammar-enforced JSON). The preset tells LM Studio *how to run* the model.
97 changes: 0 additions & 97 deletions worker_plan/tests/test_json_repair_util.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def execute(cls, llm: LLM, user_prompt: str) -> 'IdentifyPurpose':
if plan_purpose_instance is None:
raise ValueError("LLM returned empty structured response (chat_response.raw is None).")
json_response = plan_purpose_instance.model_dump()
purpose_value = plan_purpose_instance.purpose.value
purpose_value = plan_purpose_instance.purpose
json_response['purpose'] = purpose_value

metadata = dict(llm.metadata)
Expand Down
84 changes: 0 additions & 84 deletions worker_plan/worker_plan_internal/llm_util/json_repair_util.py

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""
r"""
Escape special markdown characters to prevent syntax interference.

This module provides functionality to escape markdown special characters that
Expand Down
2 changes: 1 addition & 1 deletion worker_plan/worker_plan_internal/plan/data_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ def convert_to_markdown(document_details: DocumentDetails) -> str:
responsible_parties = DataCollection._format_bullet_list(data_collection_item.responsible_parties)
rows.append(f"\n### Responsible Parties\n\n{responsible_parties}")

assumption_list = [f"**{item.sensitivity_score.human_readable()}:** {item.assumption}" for item in data_collection_item.assumptions]
assumption_list = [f"**{item.sensitivity_score.capitalize()}:** {item.assumption}" for item in data_collection_item.assumptions]
assumptions = DataCollection._format_bullet_list(assumption_list)
rows.append(f"\n### Assumptions\n\n{assumptions}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def cleanup_and_merge_with_team_members(document_details: DocumentDetails, team_
id = team_member['id']
enriched_team_member = id_to_enriched_team_member.get(id)
if enriched_team_member:
team_member['contract_type'] = enriched_team_member.contract_type.value
team_member['contract_type'] = enriched_team_member.contract_type
team_member['contract_type_justification'] = enriched_team_member.justification
return result_team_member_list

Expand Down