///|
/// A reasoned admission decision for a query arriving from an application.
pub(all) struct QueryAdmission {
accepted : Bool
normalized : String
token_count : Int
known_token_count : Int
reason : String
}
///|
pub fn QueryAdmission::accepted(self : QueryAdmission) -> Bool {
self.accepted
}
///|
pub fn QueryAdmission::known_ratio(self : QueryAdmission) -> Double {
if self.token_count <= 0 {
0.0
} else {
self.known_token_count.to_double() / self.token_count.to_double()
}
}
///|
pub fn QueryAdmission::describe(self : QueryAdmission) -> String {
"accepted=\{self.accepted}, tokens=\{self.token_count}, known=\{self.known_token_count}, ratio=\{self.known_ratio()}, reason=\{self.reason}"
}
///|
/// A compact, stable summary used by document inventory screens.
pub(all) struct ApplicationDocumentSummary {
id : String
category : String
token_count : Int
known_token_count : Int
vector_ready : Bool
}
///|
pub fn ApplicationDocumentSummary::describe(
self : ApplicationDocumentSummary,
) -> String {
"id=\{self.id}, category=\{self.category}, tokens=\{self.token_count}, known=\{self.known_token_count}, vector_ready=\{self.vector_ready}"
}
///|
/// The outcome of a batch ingestion operation, including every diagnostic.
pub(all) struct IngestionBatchReport {
attempted : Int
accepted : Int
rejected : Int
skipped : Int
diagnostics : Array[IngestionIssue]
}
///|
pub fn IngestionBatchReport::complete(self : IngestionBatchReport) -> Bool {
self.attempted > 0 &&
self.accepted == self.attempted &&
self.rejected == 0 &&
self.skipped == 0
}
///|
pub fn IngestionBatchReport::acceptance_rate(
self : IngestionBatchReport,
) -> Double {
if self.attempted <= 0 {
0.0
} else {
self.accepted.to_double() / self.attempted.to_double()
}
}
///|
pub fn IngestionBatchReport::describe(self : IngestionBatchReport) -> String {
"attempted=\{self.attempted}, accepted=\{self.accepted}, rejected=\{self.rejected}, skipped=\{self.skipped}, diagnostics=\{self.diagnostics.length()}, rate=\{self.acceptance_rate()}, complete=\{self.complete()}"
}
///|
/// A top-hit response suitable for a command-line or embedded UI preview.
pub(all) struct ApplicationAnswer {
found : Bool
query : String
document_id : String
text : String
category : String
score : Double
}
///|
pub fn ApplicationAnswer::found(self : ApplicationAnswer) -> Bool {
self.found
}
///|
pub fn ApplicationAnswer::describe(self : ApplicationAnswer) -> String {
if self.found {
"found=true, query=\"\{self.query}\", id=\{self.document_id}, category=\{self.category}, score=\{self.score}, text=\"\{self.text}\""
} else {
"found=false, query=\"\{self.query}\", reason=no-matching-document"
}
}
///|
/// Decide whether a query has enough known vocabulary to enter retrieval.
pub fn ApplicationKnowledgeBase::admit_query(
self : ApplicationKnowledgeBase,
query : ApplicationQuery,
) -> QueryAdmission {
let tokens = self.tokenizer.tokens(query.text)
let mut known = 0
for token in tokens {
if self.corpus.has_token(token) {
known = known + 1
}
}
let normalized = query.text.trim().to_owned()
if !query.valid() {
{
accepted: false,
normalized,
token_count: tokens.length(),
known_token_count: known,
reason: "invalid-query",
}
} else if tokens.is_empty() {
{
accepted: false,
normalized,
token_count: 0,
known_token_count: 0,
reason: "no-retained-token",
}
} else if known == 0 {
{
accepted: false,
normalized,
token_count: tokens.length(),
known_token_count: 0,
reason: "no-known-token",
}
} else {
{
accepted: true,
normalized,
token_count: tokens.length(),
known_token_count: known,
reason: "accepted",
}
}
}
///|
/// Produce a top-document answer while preserving the full search API.
pub fn ApplicationKnowledgeBase::answer(
self : ApplicationKnowledgeBase,
query : ApplicationQuery,
) -> ApplicationAnswer {
let query_text = query.text
let report = self.search(query)
match report.top() {
Some(hit) =>
{
found: true,
query: query_text,
document_id: hit.id(),
text: hit.text(),
category: hit.category(),
score: hit.score(),
}
None =>
{
found: false,
query: query_text,
document_id: "",
text: "",
category: "",
score: 0.0,
}
}
}
///|
/// Ingest a batch and aggregate per-document operator diagnostics.
pub fn ApplicationKnowledgeBase::ingest_with_report(
self : ApplicationKnowledgeBase,
documents : Array[Document],
) -> IngestionBatchReport {
let results = self.ingest_many(documents)
let diagnostics = []
let mut accepted = 0
let mut rejected = 0
let mut skipped = 0
for result in results {
match result.status {
Accepted => accepted = accepted + 1
Rejected => rejected = rejected + 1
Skipped => skipped = skipped + 1
}
for issue in result.issues {
diagnostics.push(issue)
}
}
{ attempted: results.length(), accepted, rejected, skipped, diagnostics }
}
///|
/// Return whether an id is currently present in the application store.
pub fn ApplicationKnowledgeBase::has_document(
self : ApplicationKnowledgeBase,
id : String,
) -> Bool {
self.store.get(id) is Some(_)
}
///|
/// Remove an accepted document without touching the embedding corpus.
pub fn ApplicationKnowledgeBase::remove_document(
self : ApplicationKnowledgeBase,
id : String,
) -> Bool {
self.store.remove(id)
}
///|
/// Return the documents in one category in insertion order.
pub fn ApplicationKnowledgeBase::documents_for_category(
self : ApplicationKnowledgeBase,
category : String,
) -> Array[Document] {
let result = []
for document in self.store.docs {
if document.metadata.get("category") == Some(category) {
result.push(document)
}
}
result
}
///|
/// Count documents by category, retaining deterministic insertion order.
pub fn ApplicationKnowledgeBase::category_counts(
self : ApplicationKnowledgeBase,
) -> Map[String, Int] {
let counts : Map[String, Int] = Map([])
for document in self.store.docs {
let category = match document.metadata.get("category") {
Some(value) => value
None => "uncategorized"
}
let next = match counts.get(category) {
Some(value) => value + 1
None => 1
}
counts.set(category, next)
}
counts
}
///|
/// Return one-line inventory summaries for operational inspection.
pub fn ApplicationKnowledgeBase::document_summaries(
self : ApplicationKnowledgeBase,
) -> Array[ApplicationDocumentSummary] {
let result = []
for document in self.store.docs {
let category = match document.metadata.get("category") {
Some(value) => value
None => "uncategorized"
}
let counts = count_known_tokens(self.corpus, self.tokenizer, document.text)
result.push({
id: document.id,
category,
token_count: counts.0,
known_token_count: counts.1,
vector_ready: document.vector is Some(_),
})
}
result
}
///|
/// Export only one category for handoff to a downstream offline tool.
pub fn ApplicationKnowledgeBase::export_category(
self : ApplicationKnowledgeBase,
category : String,
) -> String {
let mut output = "id\tcategory\ttext\n"
for document in self.documents_for_category(category) {
output = output +
document.id +
"\t" +
category +
"\t" +
document.text +
"\n"
}
output
}
///|
/// Search one category without requiring callers to construct a filter.
pub fn ApplicationKnowledgeBase::search_category(
self : ApplicationKnowledgeBase,
category : String,
text : String,
k? : Int = 5,
) -> ApplicationSearchReport {
let query = ApplicationQuery::new(
text,
k~,
filter=DocumentFilter::empty().with_category(category),
)
self.search(query)
}
///|
/// Return a stable operational snapshot for a readiness endpoint or CLI.
pub fn ApplicationKnowledgeBase::snapshot(
self : ApplicationKnowledgeBase,
) -> String {
let admission = self.admit_query(ApplicationQuery::new("king", k=1))
"ready=\{self.ready()}\n" +
"documents=\{self.document_count()}\n" +
"categories=\{self.categories().length()}\n" +
"history=\{self.history().length()}\n" +
"query_probe=\{admission.describe()}\n" +
"usage=\{self.usage().describe()}"
}
///|
/// Verify the application lifecycle invariants used by the examples.
pub fn ApplicationKnowledgeBase::workflow_ready(
self : ApplicationKnowledgeBase,
) -> Bool {
if !self.ready() {
return false
}
for summary in self.document_summaries() {
if !summary.vector_ready || summary.known_token_count <= 0 {
return false
}
}
true
}
///|
/// Return a query report plus an explicit admission decision for diagnostics.
pub(all) struct ApplicationQueryTrace {
admission : QueryAdmission
report : ApplicationSearchReport
}
///|
pub fn ApplicationQueryTrace::describe(self : ApplicationQueryTrace) -> String {
"admission=\{self.admission.describe()}\n\{self.report.describe()}"
}
///|
pub fn ApplicationKnowledgeBase::trace_query(
self : ApplicationKnowledgeBase,
query : ApplicationQuery,
) -> ApplicationQueryTrace {
let admission = self.admit_query(query)
let report = self.search(query)
{ admission, report }
}
///|
/// Build an operator-facing summary for a completed scenario.
pub fn scenario_operations_summary(
knowledge : ApplicationKnowledgeBase,
) -> String {
"workflow_ready=\{knowledge.workflow_ready()}\n" +
"documents=\{knowledge.document_count()}\n" +
"categories=\{knowledge.categories().length()}\n" +
"export_bytes=\{knowledge.export_documents().length()}\n" +
"snapshot=\n\{knowledge.snapshot()}"
}
///|
/// Use the application operations as a deterministic smoke path.
pub fn application_operations_smoke() -> Bool {
let knowledge = support_knowledge_base()
let report = knowledge.ingest_with_report([
Document::new(
"ops-smoke",
"king queen",
metadata=Map([("category", "support")]),
),
])
report.complete() &&
knowledge.workflow_ready() &&
knowledge.answer(ApplicationQuery::new("king", k=1)).found()
}
///|
test "application operations smoke" {
let knowledge = support_knowledge_base()
let batch = knowledge.ingest_with_report([
Document::new(
"ops-one",
"king queen",
metadata=Map([("category", "support")]),
),
Document::new(
"ops-two",
"apple orange",
metadata=Map([("category", "billing")]),
),
])
inspect(batch.complete(), content="true")
inspect(batch.acceptance_rate(), content="1")
inspect(knowledge.has_document("ops-one"), content="true")
inspect(knowledge.documents_for_category("billing").length(), content="1")
inspect(knowledge.document_summaries().length(), content="2")
inspect(
knowledge.answer(ApplicationQuery::new("king", k=1)).found(),
content="true",
)
}
///|
test "application operations rejection and administration" {
let knowledge = ApplicationKnowledgeBase::new(demo_corpus(), policy={
..IngestionPolicy::conservative(),
require_category: true,
})
let batch = knowledge.ingest_with_report([
Document::new("valid", "king queen", metadata=Map([("category", "ok")])),
Document::new("missing", "king queen"),
Document::new(
"unknown",
"not-in-corpus",
metadata=Map([("category", "ok")]),
),
])
inspect(batch.accepted, content="1")
inspect(batch.rejected, content="2")
inspect(batch.diagnostics.length(), content="2")
inspect(knowledge.category_counts().get("ok") is Some(1), content="true")
inspect(knowledge.remove_document("valid"), content="true")
inspect(knowledge.has_document("valid"), content="false")
}
///|
test "application query admission and trace" {
let knowledge = support_knowledge_base()
let accepted = knowledge.admit_query(ApplicationQuery::new("king", k=1))
let unknown = knowledge.admit_query(
ApplicationQuery::new("not-in-corpus", k=1),
)
inspect(accepted.accepted(), content="true")
inspect(unknown.accepted(), content="false")
inspect(unknown.reason, content="no-known-token")
let trace = knowledge.trace_query(ApplicationQuery::new("king", k=1))
inspect(trace.report.is_empty(), content="true")
}