Feat 514: add comment value score - #681
Conversation
…in admin dashboard
…y logic on JS to update te status
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Unlinked AccountsThe following contributors have not linked their GitHub and WordPress.org accounts: @priyanshuhaldar007. Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases. If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
dkotter
left a comment
There was a problem hiding this comment.
Left a number of comments and also seeing quite a few lint failures that need fixed here. In addition, we should look to add both unit tests and update our E2E tests to ensure these changes are covered
| $post = get_post( $post_id ); | ||
|
|
||
| // 1. Use excerpt if available (human-written, most reliable) | ||
| $excerpt = trim( $post->post_excerpt ); |
There was a problem hiding this comment.
Any benefit to using the excerpt or summary over just using the full post content?
| return null; | ||
| } | ||
|
|
||
| return mb_substr( $content, 0, 650 ); |
There was a problem hiding this comment.
Not sure we need to trim this. I understand it will save tokens but likely gives us worse results
…st_id to int type
|
I have implemented changes based on the reviews. For the value score generation fallback, I'd like to know your preference on the method, whether to keep this implementation or simply pass the entire post content and not the excerpt or summary. |
|
@priyanshuhaldar007 FYI a merge conflict to resolve to help keep this moving along |
I would suggest testing both approaches and seeing what results you get. If you get more or less the same results by using the excerpt/summary, I'd say we're fine to keep that as-is to save tokens. But if you get more accurate / better results by passing in the full content, we should switch to that |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #681 +/- ##
=============================================
- Coverage 78.44% 78.38% -0.06%
- Complexity 2454 2469 +15
=============================================
Files 104 104
Lines 9925 10041 +116
=============================================
+ Hits 7786 7871 +85
- Misses 2139 2170 +31
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
I set up a testing framework to measure whether using a post's excerpt/summary or its full content actually changes the quality of the generated value scores. Test setupCreated three sample posts covering common scenarios:
Added 18 comments across these posts to reflect realistic user interactions:
Testing frameworkBuilt a browser-based test harness that:
Handling API limitationsTo avoid quota and rate-limit issues with OpenAI and Gemini Pro, the test runner:
Decision criteria
This approach replaces assumptions with measurable results, making it easier to decide which context provides the best balance of accuracy and efficiency. ResultsExcerpt-based generation performed almost as well as full-content generation, with accuracy ranging from 80–100% compared to 80–87.5% for full content. This suggests we can reduce token usage without a noticeable drop in generation quality. A significant number of test cases returned null responses (8–11 per test cycle). However, these were not due to poor model performance. They were caused by external API issues from AI providers, such as rate limits and temporary server errors (e.g., HTTP 502), which prevented responses from being generated. While these failures should be accounted for when evaluating overall system reliability, they do not reflect the quality of the underlying prompts or generation logic. Excerpt mode offers better token efficiency, while full-content mode occasionally produces more consistent results. However, these findings are based on a relatively small number of tests (around 8–21 comment generations per cycle), so additional testing is needed before making a final recommendation. I'm continuing to expand the test dataset, refine the prompts, and evaluate both excerpt and full-content generation across a wider range of scenarios. I'm also investigating retry and fallback strategies to handle transient API failures (such as rate limits and 502 errors) so the comparison reflects model performance rather than external provider issues. This should lead to a more reliable evaluation and a more stable content generation pipeline. |
|
@dkotter, shall I upload the browser-end test script and all the necessary details(post content and comments) here so that you can have a look at them on your end as well? |
|
@priyanshuhaldar007 Thanks for the detailed testing, that's super helpful! Based on the results you're seeing, I think we're fine sticking with the excerpt only for now. I know there's some failing tests here that need fixed up but is there anything else you're tracking that needs done before this is ready for another review? |
What?
Closes #514
Adds a Value Score column to the comment moderation list table. Comments are now analyzed for how relevant and valuable they are to the article they're posted on, in addition to the existing toxicity and sentiment signals.
Why?
Toxicity and sentiment alone don't tell the full story of a comment's quality. A comment can be perfectly polite but still be spam, a generic "+1", or completely off-topic. This PR introduces a value score (0–1) so moderators can quickly identify substantive, on-topic contributions versus low-effort noise — making triage faster and more informed.
How?
The implementation follows the exact same pattern as the existing
toxicity_scorefield end-to-end:AI / Prompt layer
system-instruction.phpto instruct the model to return a third field,value_score, scored 0–1 with clear band definitions (low/medium/high). The prompt now also passes post context (excerpt → AI summary → trimmed content fallback) so the model can actually assess relevance against the article.get_post_context()toComment_Analysis.phpto fetch and prepare that context, with a graceful 650-char truncation fallback on raw content.analyze_comment()now accepts and passes$post_idthrough to the prompt builder.Schema & storage
output_schema()andresponse_schema()both declarevalue_scoreas a nullable float (0–1). It's nullable for cases where the post content is unavailable or too sparse to judge relevance.sanitize_analysis_result()clamps the value to [0, 1] and preservesnull.META_VALUE_SCORE(_wpai_value_score) and returned in the ability response payload.Comment Moderation UI (PHP)
VALUE_SCORE_LOW / MEDIUM / HIGHconstants andget_value_score_config()with the same range-bucket shape used by toxicity, so the frontend JS can resolve badges identically.wpai_value_scorecolumn registered inadd_columns()andadd_sortable_columns().render_value_score_column()andrender_value_score_badge()added, mirroring the toxicity equivalents.handle_sorting_and_filtering()extended to supportwpai_value_scoreordering via a meta query, same pattern as toxicity sorting.enqueue_assets()now passesvalue_scorelabel config intowindow.aiCommentModerationData.labels.ai-badge--high-value,ai-badge--medium-value, andai-badge--low-valueto the existing selectors — no new colour definitions needed.Frontend JS / TSX
AnalysisResulttype extended withvalue_score: number.Windowdeclaration extended with thevalue_scorelabels shape.PendingCommenttype extended withvalueScoreBadge: HTMLElement.getValueScoreDisplay()helper added alongsidegetToxicityDisplay(), using the same range-bucket lookup.updateBadges(),findPendingComments(),analyzeComment()all updated to handle the third badge — detection, processing state, result rendering, and failure state.Use of AI Tools
AI assistance: Yes
Tool(s): Claude
Model(s): Claude Sonnet 4.6
Used for: Drafting this PR description from the git diff. All code was written and reviewed by me, with some contributions from the copilot for updating and generating doc blocks
Testing Instructions
Screenshots or screencast
Changelog Entry