Skip to content

Basic Usage

A simple introduction to FactDb's core functionality.

Setup

require 'fact_db'

# Configure
FactDb.configure do |config|
  config.database.url = ENV['DATABASE_URL']
  config.llm.provider = :openai
  config.llm.api_key = ENV['OPENAI_API_KEY']
end

# Create facts instance
facts = FactDb.new

Ingest Content

# Ingest an email
email = facts.ingest(
  <<~TEXT,
    Hi team,

    I'm excited to announce that Paula Chen has accepted our offer
    to join Microsoft as Principal Engineer starting January 10, 2024.

    She'll be part of the Platform team reporting to Sarah Johnson.

    Best,
    HR
  TEXT
  type: :email,
  title: "New Hire Announcement - Paula Chen",
  captured_at: Time.current
)

puts "Ingested content ID: #{email.id}"

Create Entities

# Create people
paula = facts.entity_service.create(
  "Paula Chen",
  type: :person,
  aliases: ["Paula"]
)

sarah = facts.entity_service.create(
  "Sarah Johnson",
  type: :person,
  aliases: ["Sarah"]
)

# Create organization
microsoft = facts.entity_service.create(
  "Microsoft",
  type: :organization,
  aliases: ["MS", "MSFT"]
)

platform_team = facts.entity_service.create(
  "Platform Team",
  type: :organization
)

puts "Created entities: Paula, Sarah, Microsoft, Platform Team"

Extract Facts Manually

# Create facts with explicit links
fact1 = facts.fact_service.create(
  "Paula Chen joined Microsoft as Principal Engineer",
  valid_at: Date.parse("2024-01-10"),
  mentions: [
    { entity: paula, role: "subject", text: "Paula Chen" },
    { entity: microsoft, role: "organization", text: "Microsoft" }
  ],
  sources: [
    { source: email, type: "primary" }
  ]
)

fact2 = facts.fact_service.create(
  "Paula Chen reports to Sarah Johnson",
  valid_at: Date.parse("2024-01-10"),
  mentions: [
    { entity: paula, role: "subject", text: "Paula Chen" },
    { entity: sarah, role: "object", text: "Sarah Johnson" }
  ],
  sources: [
    { source: email, type: "primary" }
  ]
)

fact3 = facts.fact_service.create(
  "Paula Chen is on the Platform Team",
  valid_at: Date.parse("2024-01-10"),
  mentions: [
    { entity: paula, role: "subject", text: "Paula Chen" },
    { entity: platform_team, role: "organization", text: "Platform Team" }
  ],
  sources: [
    { source: email, type: "primary" }
  ]
)

puts "Created #{3} facts"

Extract Facts with LLM

# Alternative: let LLM extract facts
extracted = facts.extract_facts(email.id, extractor: :llm)

puts "LLM extracted #{extracted.count} facts:"
extracted.each do |fact|
  puts "  - #{fact.text}"
end

Query Facts

# Current facts about Paula
puts "\nCurrent facts about Paula:"
facts.current_facts_for(paula.id).each do |fact|
  puts "  - #{fact.text}"
end

# Facts about Microsoft
puts "\nFacts about Microsoft:"
facts.query_facts(entity: microsoft.id).each do |fact|
  puts "  - #{fact.text}"
end

Resolve Entity

# Resolve a name
resolved = facts.resolve_entity("Paula")
puts "\n'Paula' resolves to: #{resolved&.name}"

# Type-constrained resolution
person = facts.resolve_entity("Paula", type: :person)
puts "'Paula' as person: #{person&.name}"

Update Facts (Supersession)

# Paula gets promoted
new_fact = facts.fact_service.resolver.supersede(
  fact1.id,
  "Paula Chen is Senior Principal Engineer at Microsoft",
  valid_at: Date.parse("2024-06-01")
)

puts "\nSuperseded fact:"
puts "  Old: #{fact1.reload.text} (#{fact1.status})"
puts "  New: #{new_fact.text} (#{new_fact.status})"

Timeline

# Build timeline
puts "\nPaula's timeline:"
facts.timeline_for(paula.id).each do |fact|
  valid = fact.invalid_at ? "#{fact.valid_at} - #{fact.invalid_at}" : "#{fact.valid_at} - present"
  puts "  #{valid}: #{fact.text}"
end

Historical Query

# What did we know before promotion?
puts "\nFacts about Paula on March 1, 2024:"
facts.facts_at(Date.parse("2024-03-01"), entity: paula.id).each do |fact|
  puts "  - #{fact.text}"
end

# What do we know after promotion?
puts "\nFacts about Paula on July 1, 2024:"
facts.facts_at(Date.parse("2024-07-01"), entity: paula.id).each do |fact|
  puts "  - #{fact.text}"
end

Complete Script

#!/usr/bin/env ruby
require 'fact_db'

# Setup
FactDb.configure do |config|
  config.database.url = ENV['DATABASE_URL'] || 'postgresql://localhost/fact_db'
end

facts = FactDb.new

# Ingest
source = facts.ingest("Paula joined Microsoft on Jan 10, 2024", type: :note)

# Create entities
paula = facts.entity_service.create("Paula", type: :person)
microsoft = facts.entity_service.create("Microsoft", type: :organization)

# Create fact
fact = facts.fact_service.create(
  "Paula joined Microsoft",
  valid_at: Date.parse("2024-01-10"),
  mentions: [
    { entity: paula, role: "subject", text: "Paula" },
    { entity: microsoft, role: "organization", text: "Microsoft" }
  ],
  sources: [{ source: source, type: "primary" }]
)

# Query
puts "Current facts about Paula:"
facts.current_facts_for(paula.id).each { |f| puts "  - #{f.text}" }