Repository navigation
Conversation
There was a problem hiding this comment.
Pull request overview
Adds AI-based moderation metadata and an asynchronous moderation workflow for issue comments, storing model evaluation results and auto-hiding comments that exceed a configurable threshold.
Changes:
- Add
ai_evaluation(jsonb) column toissues_comments. - Enqueue moderation for newly created user comments (
after_create_commit) and persist evaluation results. - Introduce
Issues::ModerateCommentJobto call Gemini with a structured schema and auto-hide comments aboveCOMMENT_AUTO_HIDE_THRESHOLD.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| db/structure.sql | Adds ai_evaluation column to the issues_comments table and records the new migration version. |
| db/migrate/20260813133737_add_ai_evaluation_to_issues_comments.rb | Migration adding the new jsonb column with a default value. |
| app/models/issues/comment.rb | Adds moderate helper to enqueue the moderation job. |
| app/models/issues/user_comment.rb | Triggers moderation after user comment creation (non-legacy/non-imported). |
| app/models/issues/user_private_comment.rb | Updates schema annotation to include ai_evaluation. |
| app/models/issues/responsible_subject_comment.rb | Updates schema annotation to include ai_evaluation. |
| app/models/issues/duplicate_issue_comment.rb | Updates schema annotation to include ai_evaluation. |
| app/models/issues/agent_private_comment.rb | Updates schema annotation to include ai_evaluation. |
| app/models/issues/agent_comment.rb | Updates schema annotation to include ai_evaluation. |
| app/jobs/issues/moderate_comment_job.rb | New background job that calls Gemini, stores the evaluation, and auto-hides the comment based on the score threshold. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
mirrec
left a comment
There was a problem hiding this comment.
Looks good to me, but I haven't test it.
| page.slug = "moderate-comments" | ||
| page.text = "-" | ||
| page.raw = File.read(Rails.root + 'db/seeds/fixtures/ai_prompt_moderatecomments.md') | ||
| end.save! |
There was a problem hiding this comment.
Maybe a dump question, but will this get auto-created after the deploy?
Or let me ask this differently. Do we run seed after every deployment?
| Description: The comment insults specific individuals, public officials, or municipal employees. | ||
|
|
||
| Category: sarcastic | ||
| Description: The comment contains heavy sarcasm, irony, or mocking that hinders constructive dialogue. |
There was a problem hiding this comment.
OT the mocking part reminded me of this video 😄
| system_prompt: Ai::Prompt.get("moderatecomments"), | ||
| messages: [ prompt ], | ||
| response_schema: { | ||
| type: "OBJECT", |
There was a problem hiding this comment.
Out of the scope of this PR, but I do find it a bit weird, that part of the prompt is in seeds and the rest is set up here. I would expected it to be on a single place (or at least collocated in some file or folder)
There was a problem hiding this comment.
I think we could refactor this after we merge, since we use this exact same pattern elsewhere in the app
| "content": { | ||
| "parts": [ | ||
| { | ||
| "text": "{\n \"irrelevant\": 0.1,\n \"vulgar\": 0.0,\n \"insulting\": 0.0,\n \"sarcastic\": 0.0,\n \"political\": 0.0,\n \"overall_score\": 0.1,\n \"reason\": \"Slušná otázka na doplnenie detailov.\"\n}" |
There was a problem hiding this comment.
Out of the scope of the PR. I do understand the endpoint returns encoded json, but the readability is hard. Maybe there's a way how to have a simple json that will be encoded eventually.
|
@xhyrom tu ma este zaujima ze co ked nezbehne ten job (z akehokolvek dovodu) a odosle sa to do triaze. Nemalo by sa tu pockat na to kym tato validacia zbehne a az potom to posielat do triaze? Zaroven skusili sme toto pustit na nejakych realistickych datach? Lebo toto moze zacat schovavat komenty a zacnu nam pisat ludia ze kde su. |
No momentálne sa to pošle do triáže. Chápem tvoj point ale chceme naozaj v podstate znemožniť posielať komentáre v prípade, že tento job bude zlyhávať napr. z dôvodu nejakého výpadku externých APIs?
Nejaké staré/reálne dáta som až tak neskúšal, toto PR nezasahuje vôbec do historických dát. Skúšal som iba tak pár nejakých vzoriek a dal tú hranicu na 90% a v prípade veľa false-positives môžeme threshold modifikovať. A keď už to tu spomínaš, mali by sme asi spraviť nejakú notifikáciu pre autora komentáru a informovať ho o tom, že sme jeho komentár skryli. |
ok, ak to pristane len tam tak sme asi safe, ale teda o tom ze to je spam/schovane sa triaznici/plantaznici nedozvedia hej? |
no ak sa ten job spustí, tak v triáži sa to potom zobrazuje takto: ops-portal/app/models/issues/comment.rb Lines 43 to 47 in 6fbdfee |
|
tu by sa ešte hodilo porozmýšľať či chceme s moderáciou počkať kým skončí editing window alebo validovať aj pri každej úprave (to by pri zaspamovaní úprav mohol byť trochu problém), mne dáva zmysel asi skôr počkať tých cca. 5min a až potom kontrolovať. cc @jsuchal |
|
@xhyrom toto, ked sa bude mergovat, tak podla mna seedy nezbehnu. tak ma potom pingni, a ja mozem dat merge, ked to bude hotove. |
urcite ano. zaroven by som este zvazil ci ten koment do triaze predsa len neposlat ale ho oznacit na zaciatku nejako. @BarboraMel tu by sme mali vymysliet ako sa pouzivatel dozvie ze jeho koment bol schovany - toto by malo byt transparentne. cc @mirrec |
|
On ten komentár sa do triáže pošle, ale bude tam body ako "Zmazaný komentár: {body}". |
|
@xhyrom potom uz len ostava ta cast na portali. napriklad diskusie na sme.sk napisu, ze "komentar bol odstraneny"... |
|
Tak môžeme upraviť, že sa hidden komentáe budú zobrazovať ale teda namiesto reálneho textu tam bude, že bol odstránený. Prípadne chceme to mať ako špeciálnu aktivitu (#70)? |
|
@xhyrom za mna tak, pokym @BarboraMel nepovie inak. Specialnu aktivitu by som nerobil - je mozne ze tie komenty sem tam "flipneme" aj manualne. |
Tu ešte je otázne, či chceme ukazovať, že bol komentár odstránený/skrytý pri všetkých typoch komentárov, alebo iba pri user komentároch a pri ostatných ich ani ukazovať nebudeme. |
Co-authored-by: xhyrom <56601352+xhyrom@users.noreply.github.com>

https://github.com/slovensko-digital/ops/issues/764