From 3c358355054ce405898c0d68e8e00eec08b4b702 Mon Sep 17 00:00:00 2001 From: NguyenND Date: Fri, 7 Aug 2026 17:32:43 -0400 Subject: [PATCH] Aug 7 - Update: knowledge base MT19 --- app/models/support.py | 5 + app/routes/support.py | 30 +++- app/templates/support/admin_knowledge.html | 7 + .../support/admin_knowledge_edit.html | 6 + .../versions/phase53_knowledge_sort_order.py | 69 ++++++++ tests/test_knowledge_sort_order.py | 161 ++++++++++++++++++ 6 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 migrations/versions/phase53_knowledge_sort_order.py create mode 100644 tests/test_knowledge_sort_order.py diff --git a/app/models/support.py b/app/models/support.py index cf694df..47fdaf5 100644 --- a/app/models/support.py +++ b/app/models/support.py @@ -69,6 +69,11 @@ class SupportKnowledge(db.Model): title = db.Column(db.String(200), nullable=False) body = db.Column(db.Text, nullable=False) active = db.Column(db.Boolean, default=True, nullable=False) + # MT-19 — admin-controlled ordering. Entries are injected into the support + # chat's system prompt in this order, so a low sort_order is how an admin + # promotes the guidance the assistant should reach for first. Ties break on + # id, keeping the order stable. + sort_order = db.Column(db.Integer, nullable=False, default=0) created_by = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='SET NULL'), nullable=True) created_at = db.Column(db.DateTime, default=now_eastern, nullable=False) updated_at = db.Column(db.DateTime, default=now_eastern, nullable=False) diff --git a/app/routes/support.py b/app/routes/support.py index 59c438b..50d91d1 100644 --- a/app/routes/support.py +++ b/app/routes/support.py @@ -91,7 +91,9 @@ FAQS = [ def _system_prompt_with_kb(): """Return the Groq system prompt, appending active knowledge base entries.""" try: - entries = SupportKnowledge.query.filter_by(active=True).order_by(SupportKnowledge.id).all() + entries = (SupportKnowledge.query.filter_by(active=True) + .order_by(SupportKnowledge.sort_order.asc(), + SupportKnowledge.id.asc()).all()) except Exception: return _SYSTEM_PROMPT if not entries: @@ -516,10 +518,31 @@ def admin_conversation_detail(session_id): @login_required @supervisor_required def admin_knowledge(): - entries = SupportKnowledge.query.order_by(SupportKnowledge.created_at.desc()).all() + # Same order the chat prompt uses, so the admin list shows the real + # priority rather than a different one. + entries = (SupportKnowledge.query + .order_by(SupportKnowledge.sort_order.asc(), + SupportKnowledge.id.asc()).all()) return render_template('support/admin_knowledge.html', entries=entries) +def _parse_sort_order(raw, fallback=0): + """Coerce a submitted sort_order to a sane int. + + The column is NOT NULL, so a blank or non-numeric field must not reach the + DB. Clamped to 0..9999 to match the range ST validates, and falls back to + the existing value on edit so a blank field means "leave it alone" rather + than silently resetting the entry to the top. + """ + raw = (raw or '').strip() + if not raw: + return fallback + try: + return max(0, min(9999, int(raw))) + except (TypeError, ValueError): + return fallback + + @bp.route('/admin/knowledge/add', methods=['POST']) @login_required @supervisor_required @@ -534,6 +557,7 @@ def admin_knowledge_add(): title = title, body = body, active = True, + sort_order = _parse_sort_order(request.form.get('sort_order')), created_by = current_user.id, created_at = now_eastern(), updated_at = now_eastern(), @@ -561,6 +585,8 @@ def admin_knowledge_edit(entry_id): return redirect(url_for('support.admin_knowledge_edit', entry_id=entry_id)) entry.title = title entry.body = body + entry.sort_order = _parse_sort_order(request.form.get('sort_order'), + entry.sort_order) entry.updated_at = now_eastern() db.session.commit() log_action(ACTION_UPDATE, 'SupportKnowledge', entry.id, title[:60], 'edited') diff --git a/app/templates/support/admin_knowledge.html b/app/templates/support/admin_knowledge.html index 16e9150..7a91f7a 100644 --- a/app/templates/support/admin_knowledge.html +++ b/app/templates/support/admin_knowledge.html @@ -34,6 +34,12 @@ placeholder="Add facts, FAQs, or instructions the AI should know about this customer's account…">
Keep entries focused and factual. Combined active entries are capped at 6,000 characters.
+
+ + +
Lower numbers are sent to the assistant first. Leave at 0 unless an entry should take priority.
+
@@ -54,6 +60,7 @@
+ #{{ entry.sort_order }} {{ entry.title }} {% if entry.active %} Active diff --git a/app/templates/support/admin_knowledge_edit.html b/app/templates/support/admin_knowledge_edit.html index d7addec..12ca0e9 100644 --- a/app/templates/support/admin_knowledge_edit.html +++ b/app/templates/support/admin_knowledge_edit.html @@ -23,6 +23,12 @@
Combined active entries are capped at 6,000 characters in the AI prompt.
+
+ + +
Lower numbers are sent to the assistant first. Leave at 0 unless an entry should take priority.
+