feat(auto-naming): AI-generated document titles - #1400
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds configurable AI-powered document auto-naming for newly ingested documents, including organization settings persistence, background task scheduling, title generation and validation, guarded renaming, client controls, and release metadata. ChangesAI document auto-naming
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant DocumentIngestion
participant TaskQueue
participant AutoNameDocument
participant OrganizationSettings
participant AiServices
participant DocumentRepository
DocumentIngestion->>TaskQueue: schedule auto-name-document
TaskQueue->>AutoNameDocument: execute documentId and organizationId
AutoNameDocument->>OrganizationSettings: resolve autoNaming settings
AutoNameDocument->>AiServices: generate structured title
AiServices-->>AutoNameDocument: return title
AutoNameDocument->>DocumentRepository: conditionally update document name
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
7c370a3 to
9fa726d
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/brave-titles-arrive.md:
- Around line 1-5: Update the changeset description to clarify that AI-powered
auto-naming applies only to newly ingested documents with non-descriptive names,
rather than promising renames for every upload. Preserve the existing
organization setting and environment variable configuration details.
In
`@apps/papra-client/src/modules/organizations/pages/organizations-auto-tagging-settings.page.tsx`:
- Line 243: Update the conditional page content around
getIsAiAutomationAvailableForOrganization() so the auto-naming-only state uses
generic AI-automation settings copy rather than “Auto Tagging” title,
description, and navigation labels. Preserve the existing auto-tagging-specific
copy when tagging is enabled, or route auto-naming-only users to a dedicated
auto-naming page if that established path exists.
In `@apps/papra-server/src/modules/auto-naming/auto-naming.models.ts`:
- Around line 38-60: Update the title sanitization in getTitleAction so quote,
apostrophe, and period characters are removed from both the beginning and end of
the title, including model responses wrapped in surrounding quotes. Preserve the
existing non-string guard, control-character cleanup, trimming, length limit,
and rename decision behavior.
- Around line 18-26: Update buildAutoNamingUserPrompt to cap document.content
before composing the prompt, using a separate configurable maximum and
truncating oversized content while preserving shorter content unchanged. Ensure
autoNameDocument’s generated prompt always respects this limit.
In `@apps/papra-server/src/modules/auto-naming/auto-naming.usecases.ts`:
- Around line 103-123: Update the auto-naming write after the currentDocument
check to use an atomic conditional update guarded by the expected document
state, such as the original name (and any supported version or timestamp token),
in addition to documentId and organizationId. Ensure the rename is applied only
when that state still matches, and handle a failed conditional update without
overwriting a concurrent rename.
In
`@apps/papra-server/src/modules/organizations/organization-settings/organization-settings.models.ts`:
- Line 16: Update formatOrganizationSettingsForApiResponse so the autoNaming
mapping includes both isEnabled and modelId, preserving the persisted
ai.autoNaming.modelId in the settings GET response.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: be442e19-afbd-45ec-aecd-c3a6f58fce1d
📒 Files selected for processing (27)
.changeset/brave-titles-arrive.mdapps/papra-client/src/locales/en.dictionary.tsapps/papra-client/src/modules/config/config.tsapps/papra-client/src/modules/demo/demo-api-mock.tsapps/papra-client/src/modules/organizations/organizations.services.tsapps/papra-client/src/modules/organizations/pages/organizations-auto-tagging-settings.page.tsxapps/papra-server/src/migrations/list/0028-auto-naming-organization-settings.migration.tsapps/papra-server/src/migrations/migrations.registry.tsapps/papra-server/src/modules/ai-credits/ai-credits.types.tsapps/papra-server/src/modules/auto-naming/auto-naming.config.tsapps/papra-server/src/modules/auto-naming/auto-naming.models.test.tsapps/papra-server/src/modules/auto-naming/auto-naming.models.tsapps/papra-server/src/modules/auto-naming/auto-naming.usecases.test.tsapps/papra-server/src/modules/auto-naming/auto-naming.usecases.tsapps/papra-server/src/modules/auto-naming/tasks/auto-name-document.task.tsapps/papra-server/src/modules/auto-tagging/auto-tagging.usecases.test.tsapps/papra-server/src/modules/config/config.models.test.tsapps/papra-server/src/modules/config/config.models.tsapps/papra-server/src/modules/config/config.tsapps/papra-server/src/modules/documents/tasks/extract-document-file-content.task.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.models.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.repository.test.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.routes.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.tables.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.types.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.usecases.tsapps/papra-server/src/modules/tasks/tasks.definitions.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/papra-client/src/locales/en.dictionary.ts`:
- Around line 279-281: Update the
organization.settings.auto-naming.enabled.description locale string to state
that AI automatically renames added documents only when their existing names are
non-descriptive; leave the setting label and surrounding localization keys
unchanged.
In
`@apps/papra-server/src/modules/documents/tasks/extract-document-file-content.task.ts`:
- Around line 61-72: Update the auto-name and auto-tag scheduling blocks in the
document extraction task so each scheduleJob call has its own try/catch. Ensure
a rejection from auto-name-document is handled without preventing
auto-tag-document from being attempted, and handle each enqueue failure
independently using the task’s existing error-reporting mechanism.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 11a91afd-1959-4fdf-a4eb-6ddf904a9d30
📒 Files selected for processing (27)
.changeset/brave-titles-arrive.mdapps/papra-client/src/locales/en.dictionary.tsapps/papra-client/src/modules/config/config.tsapps/papra-client/src/modules/demo/demo-api-mock.tsapps/papra-client/src/modules/organizations/organizations.services.tsapps/papra-client/src/modules/organizations/pages/organizations-auto-tagging-settings.page.tsxapps/papra-server/src/migrations/list/0028-auto-naming-organization-settings.migration.tsapps/papra-server/src/migrations/migrations.registry.tsapps/papra-server/src/modules/ai-credits/ai-credits.types.tsapps/papra-server/src/modules/auto-naming/auto-naming.config.tsapps/papra-server/src/modules/auto-naming/auto-naming.models.test.tsapps/papra-server/src/modules/auto-naming/auto-naming.models.tsapps/papra-server/src/modules/auto-naming/auto-naming.usecases.test.tsapps/papra-server/src/modules/auto-naming/auto-naming.usecases.tsapps/papra-server/src/modules/auto-naming/tasks/auto-name-document.task.tsapps/papra-server/src/modules/auto-tagging/auto-tagging.usecases.test.tsapps/papra-server/src/modules/config/config.models.test.tsapps/papra-server/src/modules/config/config.models.tsapps/papra-server/src/modules/config/config.tsapps/papra-server/src/modules/documents/tasks/extract-document-file-content.task.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.models.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.repository.test.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.routes.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.tables.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.types.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.usecases.tsapps/papra-server/src/modules/tasks/tasks.definitions.ts
- cap document content length in the naming prompt (AUTO_NAMING_MAX_CONTENT_LENGTH) - make the rename atomic with a conditional update to avoid overwriting concurrent renames - round-trip the org-set auto-naming model id without exposing server defaults - schedule auto-name and auto-tag jobs independently so one enqueue failure cannot drop the other - strip leading quotes from generated titles - clarify settings copy and changeset wording
|
Addressed all 8 review comments in 78606cb: content-length cap for the naming prompt ( |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/papra-client/src/modules/organizations/pages/organizations-auto-tagging-settings.page.tsx (1)
242-243: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse generic unavailable copy for the combined AI automation gate.
When both automations are unavailable, this gate renders the fallback saying that auto-tagging is unavailable, even though the page now represents both auto-tagging and auto-naming. Use a generic AI-automation unavailable translation key/message.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/papra-client/src/modules/organizations/pages/organizations-auto-tagging-settings.page.tsx` around lines 242 - 243, Update the fallback content for the combined AI automation gate in the Show component using getIsAiAutomationAvailableForOrganization so it references the generic AI-automation-unavailable translation key/message instead of auto-tagging-specific copy.
♻️ Duplicate comments (1)
apps/papra-server/src/modules/auto-naming/auto-naming.models.ts (1)
57-57: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winTrim before stripping leading quotes.
Whitespace-prefixed model output such as
"Invoice"keeps its leading quote because this replacement runs before.trim().Proposed fix
const title = rawTitle // eslint-disable-next-line no-control-regex .replace(/[\u0000-\u001F]+/g, ' ') + .trim() .replace(/^["']+/g, '') .replace(/["'.]+$/g, '') .trim()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/papra-server/src/modules/auto-naming/auto-naming.models.ts` at line 57, Update the auto-naming output normalization chain around the leading-quote replacement so whitespace is trimmed before stripping quotes. Preserve the existing quote-removal behavior and ensure inputs such as whitespace-prefixed quoted names produce an unquoted, trimmed result.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In
`@apps/papra-client/src/modules/organizations/pages/organizations-auto-tagging-settings.page.tsx`:
- Around line 242-243: Update the fallback content for the combined AI
automation gate in the Show component using
getIsAiAutomationAvailableForOrganization so it references the generic
AI-automation-unavailable translation key/message instead of
auto-tagging-specific copy.
---
Duplicate comments:
In `@apps/papra-server/src/modules/auto-naming/auto-naming.models.ts`:
- Line 57: Update the auto-naming output normalization chain around the
leading-quote replacement so whitespace is trimmed before stripping quotes.
Preserve the existing quote-removal behavior and ensure inputs such as
whitespace-prefixed quoted names produce an unquoted, trimmed result.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 1f49deda-46a8-42ef-8112-6d0081fff6ef
📒 Files selected for processing (16)
.changeset/brave-titles-arrive.mdapps/papra-client/src/locales/en.dictionary.tsapps/papra-client/src/modules/demo/demo-api-mock.tsapps/papra-client/src/modules/organizations/organizations.services.tsapps/papra-client/src/modules/organizations/pages/organizations-auto-tagging-settings.page.tsxapps/papra-server/src/modules/auto-naming/auto-naming.config.tsapps/papra-server/src/modules/auto-naming/auto-naming.models.test.tsapps/papra-server/src/modules/auto-naming/auto-naming.models.tsapps/papra-server/src/modules/auto-naming/auto-naming.usecases.test.tsapps/papra-server/src/modules/auto-naming/auto-naming.usecases.tsapps/papra-server/src/modules/documents/documents.repository.tsapps/papra-server/src/modules/documents/tasks/extract-document-file-content.task.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.models.test.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.models.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.types.tsapps/papra-server/src/modules/organizations/organization-settings/organization-settings.usecases.ts
|
Note on model quality: Tested the auto-naming prompts against multiple providers. Capable models (7B+ / API-hosted, e.g. Qwen-3.8-Max-Preview) produce correct titles with proper language matching and preserve already-meaningful document names. Small local models (≤3B, e.g. llama3.2) may violate the language instruction and degrade well-named documents. The content-length cap ( |
Contributor License AgreementThanks for the contribution! Before this pull request can be merged, everyone who contributed to it has to sign the Papra CLA for it. The agreement should be signed per contributions, so signing for earlier work does not cover this one. Still to sign: @doomio -> Sign the CLA This check re-runs on its own once you have signed. |
Summary
Implements #1368 — AI-generated document titles, so documents ingested with meaningless names (e.g. scanner output like
SCAN_20260728_0001.pdf) are automatically renamed with a concise, descriptive title based on their content.The implementation mirrors the existing auto-tagging architecture:
auto-namingmodule (config, prompt/schema models, usecase, task) inapps/papra-serverAI_IS_ENABLED+AUTO_NAMING_ENABLEDai.autoNaming.isEnabled, default off) with migration0028, exposed via the org settings API and a toggle in the AI settings page (en locale; other locales fall back per CONTRIBUTING)updateDocumentusecase, sodocument.updatedevents, webhooks, and search indexing behave as for a manual rename;originalNameis preservedAUTO_NAMING_ENABLED,AUTO_NAMING_MODEL(falls back toAI_DEFAULT_MODEL),AUTO_NAMING_MAX_TITLE_LENGTH(default 120, capped at 255 to respect the document name contract)Safety details:
auto-namingAI credits usage sourceTest plan
getTitleAction), and the usecase (disabled setting, deleted document, rename, no-op title, concurrent-rename race) — 12 testspnpm typecheckclean forpapra-serverandpapra-client;oxlint/oxfmtclean on changed filesllama3.2), org setting enabled, uploaded a contract asimg_004_merged.txt→ renamed to "Employment Agreement - Jane Doe - April 1, 2026",originalNamepreserved, webhook + search-index handlers firedNote on model quality: Tested the auto-naming prompts against multiple providers. Capable models (7B+ / API-hosted, e.g. Qwen-3.8-Max-Preview) produce correct titles with proper language matching and preserve already-meaningful document names. Small local models (≤3B, e.g. llama3.2) may violate the language instruction and degrade well-named documents. The content-length cap (AUTO_NAMING_MAX_CONTENT_LENGTH) and non-string title guard are defense-in-depth — they did not trigger in 40 test calls across two providers, but protect against edge cases with less capable models.