Files
maritime-logistics/src/retrieval/reference_extractor.rs
T
msjidandClaude Sonnet 5 771280cde6 Add Maritime/Logistics support assistant with safety/eval layer
RAG + multi-agent (retrieval, policy-compliance, drafting) support
assistant for a fictional shipping company, built in Rust with Qdrant
for vector storage and a hand-rolled Anthropic tool-calling client
(no Rust pydantic-ai equivalent exists). A deterministic supervisor
orchestrates the agents and runs every response through a rule-based
guardrail pipeline with an append-only audit log.

Includes a 44-example golden dataset (normal/injection/policy-
violation/hallucination-bait/out-of-scope) and a regression harness
that scores retrieval, generation, and guardrail correctness
separately, plus a write-up of the failure modes and trade-offs.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-18 21:04:09 +02:00

66 lines
1.8 KiB
Rust

//! Deterministic extraction of shipment identifiers from free text.
//!
//! Pulled out as its own unit (rather than a method on `DocumentRetriever`)
//! purely so it's testable without spinning up a Qdrant connection.
use regex::Regex;
pub struct ReferenceExtractor {
booking_reference_re: Regex,
container_number_re: Regex,
}
impl ReferenceExtractor {
pub fn new() -> Self {
Self {
booking_reference_re: Regex::new(r"\bMSL-[A-Z0-9]{7}\b").expect("valid regex"),
container_number_re: Regex::new(r"\b[A-Z]{4}\d{7}\b").expect("valid regex"),
}
}
/// Preferred over asking the LLM to do this: it's cheap, exact, and
/// never hallucinates a reference that wasn't actually typed.
pub fn extract(&self, query: &str) -> Option<String> {
let upper = query.to_uppercase();
self.booking_reference_re
.find(&upper)
.or_else(|| self.container_number_re.find(&upper))
.map(|m| m.as_str().to_string())
}
}
impl Default for ReferenceExtractor {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn extracts_booking_reference_case_insensitively() {
let r = ReferenceExtractor::new();
assert_eq!(
r.extract("where is msl-4b7k921 right now?"),
Some("MSL-4B7K921".to_string())
);
}
#[test]
fn extracts_container_number() {
let r = ReferenceExtractor::new();
assert_eq!(
r.extract("container MSCU1234567 status please"),
Some("MSCU1234567".to_string())
);
}
#[test]
fn returns_none_when_no_reference_present() {
let r = ReferenceExtractor::new();
assert_eq!(r.extract("what are your office hours?"), None);
}
}