feat: LLM based prose format conistency workflow - #140
Open
hpnyaggerman wants to merge 20 commits into
Open
Conversation
…ing location based on per-fragment choice
build_direction_note_prompt opens an [OOC: aside (DIRECTION_NOTE_PREAMBLE) but never closed it, unlike the other pass builders. Adopt the same close-with-] convention ahead of merging main's cf6cad7, which adds it to the four pre-existing OOC builders, so the merged tree stays consistent.
Main upstreamed the inherited direction-notes feature as OrbFrontend#104 (dab5ad2) and added the Gemma-4 native tool-call parser (ef05ba0). The direction-notes surface is resolved wholesale to main's OrbFrontend#104: its upstreamed form is ahead of the dev version this branch inherited (per-fragment director calls, the characterization seed replacing story_direction, rewritten preambles), so no branch-side direction-notes is kept. The prose-format workflow is untouched -- main never references it -- and test_tool_registry keeps both sides' additive edits.
Both sides independently rewrote the same two assertions in TestBuiltinToolNames and TestStandaloneToolsBaseline once a workflow started contributing standalone tools, reaching the same set equation by different spellings. Adopting main's text makes the hunks identical, so the upcoming merge sees no conflict here at all.
Main replaced the ad-hoc plugin surface with a single facade, frontend/workflow_api.js, and added scripts/check_frontend_layers.py to lint.sh to enforce it. A module under frontend/workflows/ may now import only that facade plus its own relative files, so the deep imports of state.js, api.js, utils.js and modal.js all become hard errors. The same check ratchets the number of inline on*= attributes across the frontend and refuses to let it grow. Twelve of them here move to the facade's delegated dispatcher: markup carries data-wf-action, and initConfigPanel registers the handlers through registerAction instead of planting window.pf* globals. The global state object S is deliberately absent from the facade, so the two reads of S.activeConvId go through its getActiveConvId accessor.
Main split off-turn LLM work into a writer lane and an agent lane, gave OnDemandCtx and RegenCtx an agent_client plus agent_model_name, and added a model_name argument to forced_tool_call. image_gen's off-turn hooks already route their tool calls that way; the manual Analyze button now does the same. run_analyzer takes the client and model as arguments rather than reading ctx.client, because only the off-turn contexts resolve a second lane. PreCtx does not, so the automatic pre-pipeline attempt keeps passing its single client -- see the note at the on-demand call site for what that asymmetry costs.
The only conflict is the workflow registry in backend/workflows, where main registers image_gen and this branch registers prose_format_llm. Both additions stay: main's block keeps its place and prose_format_llm appends after it, so the manifest order main established is unchanged. Hook order is unaffected either way, since the post-pipeline fan-out sorts on the explicit priority rather than on registration order.
Main raised the Python floor to 3.11 and added ruff's UP rules, which reject the deprecated typing aliases for Mapping, Sequence and Iterable. These three modules were written before that and fail ruff as merged.
Owner
|
@hpnyaggerman I'll give this a spin later. I actually trained a very small pov/tense classifier here as I said I would - miliseconds on a CPU for 256 tokens: https://huggingface.co/chartreuse-verte/ettin-povtense-17m, it's already being used for auto POV in image gen workflow. I'll see if it can be integrated into the workflow to assist the agent model. |
# Conflicts: # backend/workflows/__init__.py
Main now withholds tools and tool_choice from every chat request to an endpoint whose profile sets structured_tool_calls, deriving a strict response_format from the forced tool's parameters and rebuilding the reply from a synthesized tool-call message. Every path in this workflow is a forced tool call, so all three of its schemas ride that rewrite and none of them was exercised through it. The cases assert what the rewrite can quietly break: strictify_schema closes each array's item object, and every item property has to stay a plain string, because a leaf widened to ["string", "null"] decodes as None and is then dropped by the string guards in violations.py and patching.py -- an empty result rather than a visible failure. They sit in this workflow's own suite because the schemas are its own; test_structured_tool_calls.py already covers the transport itself.
Owner
Contributor
Author
|
@OrbFrontend Will look into it tomorrow or slightly later. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

This workflow is an implementation of an idea I described in #55. It is not perfect but it works and it has a shape I believe is viable. Up to you @OrbFrontend whether you want to merge it but I believe no one will be at a loss with this workflow in the default Orb selection.