Built-in AI chatbot (no EE, uses Llm::Resolver) that answers in-scope chats
from a knowledge base and hands off to a human when needed. Selected per
inbox via an Integrations::Hook with app_id 'chatbot'.
- Integrations::Chatbot::ProcessorService (mirrors Dialogflow/Captain)
wired via HookListener + HookJob + apps.yml(chatbot, inbox)
- Chatbot::DecisionService: 1-call default ({in_scope/refuse/handoff}),
2-call option; thread-safe prompt threading
- Chatbot::KnowledgeRetriever: keyword top-k over KB (+ embedding reserved)
- KnowledgeBaseFaq + import service (md per-heading + front-matter tags)
- Chatbot::ConfigService + admin chatbot_config endpoint
- refs off-topic (e.g. fortune-telling); handoff = bot_handoff! (pending->open)
35 lines
1.1 KiB
Ruby
35 lines
1.1 KiB
Ruby
# == Schema Information
|
|
#
|
|
# Table name: knowledge_base_faqs
|
|
#
|
|
# id :bigint not null, primary key
|
|
# account_id :bigint not null
|
|
# title :string not null
|
|
# content :text not null
|
|
# topic_tags :jsonb default: [] not null
|
|
# source_filename :string
|
|
# embedding :vector(1536)
|
|
# created_at :datetime not null
|
|
# updated_at :datetime not null
|
|
#
|
|
class KnowledgeBaseFaq < ApplicationRecord
|
|
belongs_to :account
|
|
# pgvector KNN support (matches repo pattern: has_neighbors + nearest_neighbors)
|
|
has_neighbors :embedding, normalize: true
|
|
|
|
validates :title, presence: true
|
|
validates :content, presence: true
|
|
|
|
# topic_tags stored as jsonb array; expose string-list helpers for import/retrieval.
|
|
def topic_tag_list
|
|
Array(topic_tags)
|
|
end
|
|
|
|
def topic_tag_list=(value)
|
|
self.topic_tags = Array(value).map(&:strip).reject(&:blank?)
|
|
end
|
|
|
|
scope :for_account, ->(account) { where(account_id: account.id) }
|
|
scope :with_embedding, -> { where.not(embedding: nil) }
|
|
end
|