Repository navigation
Analyze: full_report and moment descriptions in one batch each - #1233
sidneyswift wants to merge 4 commits into
Conversation
full_report sent its 13 sections as 13 separate model calls: 13 audio downloads and 13 base fees ($0.65 before GPU time). Song moments described each moment with its own call: up to 7 downloads and 7 base fees. Both now go through generate_batch: one download, one base fee. - Modal generate_batch: a prompt may carry clip_start/clip_end (cut fresh from the one download) and its own temperature/top_p/do_sample. Clipped answers echo the window. Validation moved into pure, locally tested helpers (modal/test_serve_music_flamingo.py). - executeFullReport: one batch with each preset's own settings; charges base + the seconds of sections that parsed; failed sections cost nothing. - describeMoments replaces describeMoment: one batch, one clip per moment; an answer without the clip echo is dropped, so words never come from the whole song. - Credit gates: analyze is one base fee for every request (the per-request helper is gone); moments is measurement + one base fee. - The ten presets whose answers are stored as data decode greedily, so the same song gets the same answer; the three prose presets keep sampling. - maxDuration 800 on /api/songs/analyze and /mcp: the sections now run one after another on one container. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
There was a problem hiding this comment.
1 issue found across 44 files
Confidence score: 4/5
modal/serve_music_flamingo.pyhas grown to 551 lines with the new helpers, well beyond the 100-line guideline. Split the helpers into focused modules to keep the code maintainable.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="modal/serve_music_flamingo.py">
<violation number="1" location="modal/serve_music_flamingo.py:87">
P2: Custom agent: **Enforce Clear Code Style and Maintainability Practices**
This adds clip-processing and batch-validation helpers to a 551-line module, far beyond the guideline’s 100-line limit. Split the helpers into focused modules to keep this service module maintainable.</violation>
</file>
Architecture diagram
sequenceDiagram
participant Client as Client / MCP
participant API as Recoup API Route
participant Credits as Credit Gate
participant Batch as callFlamingoGenerateBatch
participant Modal as Modal App (Music Flamingo)
participant Billing as chargeForBatchAnswers
participant DB as Usage Database
Note over Client,DB: full_report and Moment Descriptions: Single Batch Flow
Client->>API: POST /api/songs/analyze (full_report) or /mcp
API->>Credits: Check FLAMINGO_BASE_CREDITS (fixed gate)
Credits-->>API: Sufficient credits
API->>Batch: Generate batch (13 prompts, one per section)
Batch->>Modal: POST /generate_batch
Note over Modal: Download audio ONCE, run prompts sequentially
Modal->>Modal: Validate prompts (per-prompt clip/settings)
Modal-->>Batch: Answers with elapsed_seconds (and clip echo)
alt All sections answered
Batch-->>API: Complete answers
API->>API: Parse responses per preset
API->>Billing: Charge for used answers (one row)
Billing->>DB: Insert usage record (base + sum of seconds)
else Some sections missing/failed
Modal-->>Batch: Partial answers / batch error
Batch-->>API: Missing answers flagged
API->>API: Mark failed sections as { error }, not charged
API->>Billing: Charge only for usable answers
end
API-->>Client: Report (successful + failed sections)
Note over Client,DB: Moment Descriptions
Client->>API: POST /api/songs/moments (with describe)
API->>Credits: Check SONG_MEASURE_CREDITS + FLAMINGO_BASE_CREDITS
Credits-->>API: Sufficient credits
API->>Batch: Generate batch (one prompt per moment, each with clip window)
Batch->>Modal: POST /generate_batch (with clip_start/clip_end per prompt)
Modal-->>Batch: Answers echoing their clip windows
alt Answer matches its clip window
API->>API: Accept description
API->>Billing: Charge for accepted descriptions
Billing->>DB: Insert usage record
else Answer does not match clip (no echo)
API->>API: Drop answer (no words, not charged)
end
API-->>Client: Moments with descriptions (or without, if dropped)
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| @@ -84,28 +84,125 @@ def download_model_weights(): | |||
| print(f"Model weights saved to {MODEL_CACHE_DIR}/model") | |||
There was a problem hiding this comment.
P2: Custom agent: Enforce Clear Code Style and Maintainability Practices
This adds clip-processing and batch-validation helpers to a 551-line module, far beyond the guideline’s 100-line limit. Split the helpers into focused modules to keep this service module maintainable.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modal/serve_music_flamingo.py, line 87:
<comment>This adds clip-processing and batch-validation helpers to a 551-line module, far beyond the guideline’s 100-line limit. Split the helpers into focused modules to keep this service module maintainable.</comment>
<file context>
@@ -84,28 +84,125 @@ def download_model_weights():
print(f"Model weights saved to {MODEL_CACHE_DIR}/model")
+def extract_clip(path, start, end):
+ """
+ Cut start..end seconds of `path` into a new 16 kHz mono WAV and return its
</file context>
There was a problem hiding this comment.
Not splitting this here: a second module would have to be mounted into the 16 GB model image (add_local_file after the weights layer), which is deploy risk for a style rule this repo doesn't have. The new helpers are pure, module-level and covered by modal/test_serve_music_flamingo.py.
🤖 Addressed by Claude Code
…tch loop
- describeMoments drops a reply that parses to nothing usable, so it is
neither merged into the moment nor billed.
- executeFullReport treats a parsed {"error": ...} answer as a failed
section (listed in failed, not billed).
- isFlamingoGenerateBatchResult requires both clip ends as numbers or
neither.
- Modal: is_number rejects NaN, infinity and ints too large for a float, so
a huge clip_end is a 422 instead of an OverflowError; the batch loop moves
into run_batch, tested with a fake model for per-prompt settings, clip
echoes and clip cleanup (also on failure).
- Greedy presets use the neutral temperature 1.0, so transformers stops
logging an ignored-flag notice on every call.
- Docs and test names: processAnalyzeMusicRequest billing note, the moments
gate test name, the exact billed answer in the partial-drop test, and the
ffmpeg/ffprobe prerequisite for the Modal tests.
Not changed: splitting serve_music_flamingo.py into modules would mean
mounting extra files into the 16 GB model image; the helpers stay in the
module, pure and tested.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 24 files (changes from recent commits).
Confidence score: 4/5
lib/flamingo/executeFullReport.tsnow exceeds the 100-line maintainability limit. Refactor or split the module to bring it back under the limit.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="lib/flamingo/executeFullReport.ts">
<violation number="1" location="lib/flamingo/executeFullReport.ts:81">
P2: Custom agent: **Enforce Clear Code Style and Maintainability Practices**
This change expands `executeFullReport.ts` from 105 to 121 lines, exceeding Rule 3's under-100-line limit. Refactor or split the module so it stays below that limit.</violation>
</file>
Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.
View guided diff | Turn on auto-fix | Re-trigger cubic
| } | ||
| try { | ||
| const data = preset.parseResponse ? preset.parseResponse(answer.response) : answer.response; | ||
| if (isErrorShape(data)) { |
There was a problem hiding this comment.
P2: Custom agent: Enforce Clear Code Style and Maintainability Practices
This change expands executeFullReport.ts from 105 to 121 lines, exceeding Rule 3's under-100-line limit. Refactor or split the module so it stays below that limit.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At lib/flamingo/executeFullReport.ts, line 81:
<comment>This change expands `executeFullReport.ts` from 105 to 121 lines, exceeding Rule 3's under-100-line limit. Refactor or split the module so it stays below that limit.</comment>
<file context>
@@ -77,9 +77,15 @@ export async function executeFullReport(
- ? preset.parseResponse(answer.response)
- : answer.response;
+ const data = preset.parseResponse ? preset.parseResponse(answer.response) : answer.response;
+ if (isErrorShape(data)) {
+ // A reply of {"error": "..."} would read as a failed section in the
+ // report, so it is one: listed in `failed` and not billed.
</file context>
There was a problem hiding this comment.
Leaving this as one file: the 100-line limit isn't one of this repo's rules (CLAUDE.md asks for one exported function per file, which this keeps), and the extra lines are the failed-section handling plus two small private helpers in the same flow.
🤖 Addressed by Claude Code
recoupable/docs#36 rewrites the analyze/moments pricing and credits text; the shared fixture records those source hashes. Contract tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Generated with build-contract-examples.py against recoupable/api#1233, which carries the matching API fixture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pins recoupable/api#1233 head (83b330fe). Re-pin to its merge commit after it merges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Asserts the charged answer ids are every section but the failed one, and fixes the test comment: that section is reported as failed and not billed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Requires human review: Batches full_report and moment descriptions into one Modal call and switches ten presets to greedy decoding, with billing, credit-gate, and timeout changes the author says were not verified on a GPU/production run.
View guided diff | Turn on auto-fix | Re-trigger cubic
What this changes
full_reportand song-moment descriptions each used one model call per question. Every call downloaded the song again and paid the $0.05 base fee. Both now go throughgenerate_batch, so each downloads once and pays one base fee.full_reportfull_report$0.65; moments $0.36Modal (
modal/serve_music_flamingo.py)generate_batchprompt can now carryclip_start/clip_end. The clip is cut fresh from the single download for each prompt.temperature/top_p/do_sample, overriding the batch's settings for that prompt only.modal/test_serve_music_flamingo.py(21 tests). The existing 44 measurement tests still pass.cut_clip(used by/generate) now reuses the newextract_clip.API
executeFullReport: one batch. Each section keeps its preset's prompt, token limit, temperature and sampling choice.{ error }, is listed infailed, and isn't charged.processAnalyzeMusicRequeststill returns 502 in that case.describeMomentsreplacesdescribeMoment: one batch with one clip per moment.chargeForBatchAnswers(new): one usage row, priced at base + the seconds of the answers that were used.minimumCreditsForAnalyzeRequestis removed; its four callers now check forFLAMINGO_BASE_CREDITS. The moments gate is the measurement price + one base fee when anything will be described.do_sample: false), so the same song gets the same answer on every run. The three prose presets (song_description,playlist_pitch,artist_development_notes) keep sampling.transformers==5.16.1: setting a temperature alongside greedy decoding only logs a notice, it doesn't raise.maxDurationraised to 800 s on/api/songs/analyzeand/mcp. The 13 sections now run one after another on one container, so a report takes the sum of the section times, not the time of the longest one. 800 s stays above Modal's 600 s timeout.Deploy order
A merge deploys Modal (Actions) and the API (Vercel) at the same time. The changes are safe in either order:
generate_batchignores the new per-prompt fields.full_reportstill works, all greedy.Not verified
full_reportand/api/songs/moments(describe on):Follow-up
The docs still describe the old pricing:
credits.mdx: "full_reportis the sum of its 13 calls"$0.65forfull_report"That needs a docs PR plus the published-docs fixture refresh after this merges.
Tests
pnpm test: 1453 files, 9283 tests passing.typecheck:response-contractsclean.tscreports no errors in the changed files. The 214 remaining errors already exist onmain, which has 215.🤖 Generated with Claude Code
Summary by cubic
full_reportand song-moment descriptions each ran one model call per question, downloading the song and paying the $0.05 base fee per call. Both now run as a singlegenerate_batch, so each downloads the audio once and pays one base fee per request.Behavior
generate_batchaccepts per-promptclip_start/clip_end(clips are cut fresh from the one download) and per-prompttemperature/top_p/do_sampleoverrides; clipped answers echo their window. Clip bounds must be finite numbers — NaN, infinity, or a value too large for a float is a 422.full_reportsends all 13 sections in one batch, each with its preset's prompt and settings; a section that is missing or returns a parsed{ error }is listed infailedand isn't charged. A failed batch fails every section and charges nothing.describeMomentsreplacesdescribeMoment: one batch with one clip per moment; an answer that doesn't echo its clip or parses to nothing usable is dropped, and an undescribed moment comes back without words and isn't charged.chargeForBatchAnswers: base price plus the seconds of the answers that were used, billing only the answers that parsed into usable results.maxDurationis 800 s on/api/songs/analyzeand/mcpsince sections now run sequentially on one container.published-docsfixture is refreshed.Deploy order
Written for commit 2a3d988. Summary will update on new commits.