Skip to content

Replace GPTR content generation with custom flow#141

Merged
gregagi merged 1 commit intomainfrom
feat/replace-gptr-custom-content-flow
Feb 24, 2026
Merged

Replace GPTR content generation with custom flow#141
gregagi merged 1 commit intomainfrom
feat/replace-gptr-custom-content-flow

Conversation

@gregagi
Copy link
Copy Markdown
Collaborator

@gregagi gregagi commented Feb 23, 2026

Summary

  • replace GPTR-based blog post generation in BlogPostTitleSuggestion.generate_content with the existing PydanticAI content generation agent
  • add validation + retry logic to reject placeholder language (for example: "insert image here") and incomplete/cut-off endings
  • keep post-generation link insertion flow intact so link exchange backlinks are still injected for Pro projects
  • tighten SEO content prompt guidance to avoid placeholder directives

Notes

  • no new tests were added (repo guidance says avoid adding/running tests unless explicitly requested)
  • syntax sanity check executed: uv run python -m py_compile core/models.py core/prompts.py

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 23, 2026

Warning

Rate limit exceeded

@gregagi has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 24 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 4e1e270 and 52c4968.

📒 Files selected for processing (2)
  • core/models.py
  • core/prompts.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/replace-gptr-custom-content-flow

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Worth considering though. View full project report here.

Comment thread core/models.py
Comment on lines +940 to +947
logger.warning(
"[Generate Content Custom Flow] Generated content failed validation",
title_suggestion_id=self.id,
project_id=self.project.id,
generation_attempt_number=generation_attempt_number,
maximum_generation_attempts=maximum_generation_attempts,
validation_error=validation_error,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logger.warning(
"[Generate Content Custom Flow] Generated content failed validation",
title_suggestion_id=self.id,
project_id=self.project.id,
generation_attempt_number=generation_attempt_number,
maximum_generation_attempts=maximum_generation_attempts,
validation_error=validation_error,
)
logger.warning(
"[Generate Content Custom Flow] Generated content failed validation",
title_suggestion_id=self.id,
project_id=self.project_id,
generation_attempt_number=generation_attempt_number,
maximum_generation_attempts=maximum_generation_attempts,
validation_error=validation_error,
)

Comment thread core/models.py
logger.warning(
"[Generate Content Custom Flow] Generated content failed validation",
title_suggestion_id=self.id,
project_id=self.project.id,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.project.id performs a database read when id is evaluated. You could take advantage of Django's caching of related fields by using self.project_id, which does not do a database read. Explained here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 23, 2026

Greptile Summary

Replaced GPTR-based blog generation with custom PydanticAI agent flow, adding validation and retry logic to prevent placeholder language and incomplete content.

Major changes:

  • Removed GPTResearcher dependency and run_gptr_synchronously utility import
  • Added create_generate_blog_post_content_agent for structured content generation using existing PydanticAI agent
  • Implemented contains_placeholder_language() to detect editorial placeholders (e.g., "insert image here", "[TODO]")
  • Implemented has_incomplete_ending() to validate content ends with complete sentences
  • Added retry loop (up to 3 attempts) with validation feedback to agent
  • Improved get_internal_links() to deduplicate pages by URL
  • Updated prompts to emphasize direct inline links instead of placeholder suggestions
  • Preserved post-generation link insertion flow for Pro projects

Confidence Score: 4/5

  • This PR is safe to merge with minor issues
  • The refactoring is well-structured with comprehensive validation logic and proper error handling. The migration from GPTResearcher to PydanticAI is clean, but there's a minor regex issue and redundant validation check that should be addressed.
  • Check core/models.py:866 for the regex pattern fix

Important Files Changed

Filename Overview
core/models.py Replaced GPTResearcher with custom PydanticAI flow, added validation/retry logic for placeholder detection and incomplete endings, improved link deduplication
core/prompts.py Updated SEO content prompts to remove placeholder suggestions and emphasize direct inline links instead of editorial notes

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Start: generate_content] --> B[Create PydanticAI Agent]
    B --> C[Build Generation Context]
    C --> D{Attempt Loop<br/>Max 3 attempts}
    D --> E[Build Prompt with<br/>Previous Error]
    E --> F[Run Agent Synchronously]
    F --> G[Get Generated Schema]
    G --> H{Validate Content}
    H -->|Empty| I[Set Error: Empty]
    H -->|Has Placeholders| J[Set Error: Placeholders]
    H -->|Incomplete Ending| K[Set Error: Incomplete]
    H -->|Valid| L[Return Schema]
    I --> M{More Attempts?}
    J --> M
    K --> M
    M -->|Yes| D
    M -->|No| N[Raise ValueError]
    L --> O[Create Blog Post]
    O --> P[Insert Links]
    P --> Q[Process Content]
    Q --> R[Update Title & Slug]
    R --> S[Save Blog Post]
Loading

Last reviewed commit: 52c4968

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread core/models.py

last_line = non_empty_lines[-1]

if re.search(r"[:;,\-(\[]$", last_line) or last_line.endswith("..."):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

regex pattern escapes hyphen - unnecessarily

Suggested change
if re.search(r"[:;,\-(\[]$", last_line) or last_line.endswith("..."):
if re.search(r"[:;,\-\([]$", last_line) or last_line.endswith("..."):

Comment thread core/models.py
Comment on lines +958 to +960
generated_content = (generated_blog_post_schema.content or "").strip()
if not generated_content:
raise ValueError("Generated blog post content is empty.")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant empty content check after validation

The validate_generated_blog_post_content method already checks for empty content on line 881-882, so this check is redundant and will never be reached.

@gregagi gregagi merged commit 2869fc8 into main Feb 24, 2026
4 checks passed
@gregagi gregagi deleted the feat/replace-gptr-custom-content-flow branch February 24, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants