mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-07-16 17:47:22 +00:00
295 lines
9.4 KiB
Plaintext
295 lines
9.4 KiB
Plaintext
@startuml
|
|
skinparam style strictuml
|
|
skinparam defaultFontName "DM Sans"
|
|
skinparam defaultFontSize 14
|
|
skinparam titleFontName "Volkhov"
|
|
skinparam titleFontSize 20
|
|
skinparam backgroundColor #FAFCF9
|
|
skinparam defaultFontColor #28342A
|
|
skinparam titleFontColor #28342A
|
|
skinparam ArrowColor #628A5B
|
|
|
|
skinparam class {
|
|
BackgroundColor #FAFCF9
|
|
HeaderBackgroundColor #EAF0E8
|
|
BorderColor #547461
|
|
ArrowColor #628A5B
|
|
FontColor #28342A
|
|
}
|
|
|
|
skinparam note {
|
|
BackgroundColor #EAF0E8
|
|
BorderColor #547461
|
|
FontColor #28342A
|
|
}
|
|
|
|
title The Biergarten Data Pipeline - Class Diagram
|
|
|
|
class BiergartenPipelineOrchestrator {
|
|
- logger_ : std::shared_ptr<ILogger>
|
|
- context_service_ : std::unique_ptr<IEnrichmentService>
|
|
- generator_ : std::unique_ptr<DataGenerator>
|
|
- exporter_ : std::unique_ptr<IExportService>
|
|
- curated_data_service_ : std::unique_ptr<ICuratedDataService>
|
|
- postal_code_service_ : std::unique_ptr<IPostalCodeService>
|
|
- application_options_ : ApplicationOptions
|
|
- generated_breweries_ : std::vector<BreweryRecord>
|
|
- generated_users_ : std::vector<UserRecord>
|
|
+ Run() : bool
|
|
- QueryCitiesWithCountries() : std::vector<City>
|
|
- GenerateBreweries(cities : std::span<const EnrichedCity>) : void
|
|
- GenerateUsers(cities : std::span<const EnrichedCity>) : void
|
|
- LogResults() : void
|
|
}
|
|
|
|
class LogLevel <<enumeration>> {
|
|
Debug
|
|
Info
|
|
Warn
|
|
Error
|
|
}
|
|
|
|
class PipelinePhase <<enumeration>> {
|
|
Startup
|
|
UserGeneration
|
|
BreweryAndBeerGeneration
|
|
CheckinGeneration
|
|
RatingGeneration
|
|
FollowGeneration
|
|
Teardown
|
|
}
|
|
|
|
struct LogDTO {
|
|
+ level : LogLevel
|
|
+ phase : PipelinePhase
|
|
+ message : std::string
|
|
}
|
|
|
|
struct LogEntry {
|
|
+ timestamp : std::chrono::system_clock::time_point
|
|
+ origin : std::source_location
|
|
+ thread_id : std::thread::id
|
|
+ level : LogLevel
|
|
+ phase : PipelinePhase
|
|
+ message : std::string
|
|
}
|
|
|
|
interface ILogger <<interface>> {
|
|
+ Log(payload : LogDTO) : void
|
|
- {abstract} DoLog(entry : LogEntry) : void
|
|
}
|
|
|
|
class LogProducer {
|
|
- channel_ : BoundedChannel<LogEntry>&
|
|
- DoLog(entry : LogEntry) : void
|
|
}
|
|
|
|
class LogDispatcher {
|
|
- channel_ : BoundedChannel<LogEntry>&
|
|
+ Run() : void
|
|
- ToSpdlogLevel(level) : spdlog::level::level_enum
|
|
}
|
|
|
|
interface IEnrichmentService <<interface>> {
|
|
+ GetLocationContext(loc : const City&) : std::string
|
|
}
|
|
|
|
class MockEnrichmentService {
|
|
+ GetLocationContext(loc : const City&) : std::string
|
|
}
|
|
|
|
class WikipediaEnrichmentService {
|
|
- client_ : std::unique_ptr<WebClient>
|
|
- extract_cache_ : std::unordered_map<std::string, std::string>
|
|
+ GetLocationContext(loc : const City&) : std::string
|
|
- FetchExtract(query : std::string_view) : std::string
|
|
}
|
|
|
|
interface WebClient <<interface>> {
|
|
+ Get(url : const std::string&) : std::string
|
|
+ UrlEncode(value : const std::string&) : std::string
|
|
}
|
|
|
|
class HttpWebClient {
|
|
+ Get(url : const std::string&) : std::string
|
|
+ UrlEncode(value : const std::string&) : std::string
|
|
}
|
|
|
|
interface DataGenerator <<interface>> {
|
|
+ GenerateBrewery(location : const City&, region_context : const std::string&) : BreweryResult
|
|
+ GenerateUser(city : const EnrichedCity&, persona : const UserPersona&, name : const Name&) : UserResult
|
|
}
|
|
|
|
class MockGenerator {
|
|
+ GenerateBrewery(location : const City&, region_context : const std::string&) : BreweryResult
|
|
+ GenerateUser(city : const EnrichedCity&, persona : const UserPersona&, name : const Name&) : UserResult
|
|
- DeterministicHash(location : const City&) : size_t
|
|
- DeterministicHash(location : const City&, persona : const UserPersona&, name : const Name&) : size_t
|
|
}
|
|
|
|
class LlamaGenerator {
|
|
- model_ : ModelHandle
|
|
- context_ : ContextHandle
|
|
- prompt_formatter_ : std::unique_ptr<IPromptFormatter>
|
|
- prompt_directory_ : std::unique_ptr<IPromptDirectory>
|
|
- rng_ : std::mt19937
|
|
+ GenerateBrewery(...) : BreweryResult
|
|
+ GenerateUser(...) : UserResult
|
|
- Load(model_path : const std::string&) : void
|
|
- Infer(...) : std::string
|
|
- InferFormatted(...) : std::string
|
|
}
|
|
|
|
interface IPromptFormatter <<interface>> {
|
|
+ Format(system_prompt : std::string_view, user_prompt : std::string_view) : std::string
|
|
}
|
|
|
|
class Gemma4JinjaPromptFormatter {
|
|
+ Format(system_prompt : std::string_view, user_prompt : std::string_view) : std::string
|
|
}
|
|
|
|
interface IPromptDirectory <<interface>> {
|
|
+ Load(key : std::string_view) : std::string
|
|
}
|
|
|
|
class PromptDirectory {
|
|
- prompt_dir_ : std::filesystem::path
|
|
- cache_ : std::unordered_map<std::string, std::string>
|
|
+ Load(key : std::string_view) : std::string
|
|
}
|
|
|
|
interface ICuratedDataService <<interface>> {
|
|
+ LoadCities(filepath : const std::filesystem::path&) : const std::vector<City>&
|
|
+ LoadPersonas(filepath : const std::filesystem::path&) : const std::vector<UserPersona>&
|
|
+ LoadForenamesByCountry(filepath : const std::filesystem::path&) : const std::unordered_map<std::string, forename_list>&
|
|
+ LoadSurnamesByCountry(filepath : const std::filesystem::path&) : const std::unordered_map<std::string, surname_list>&
|
|
}
|
|
|
|
class JsonLoader {
|
|
- cache_ : cache
|
|
+ LoadCities(filepath : const std::filesystem::path&) : const std::vector<City>&
|
|
+ LoadPersonas(filepath : const std::filesystem::path&) : const std::vector<UserPersona>&
|
|
+ LoadForenamesByCountry(filepath : const std::filesystem::path&) : const std::unordered_map<std::string, forename_list>&
|
|
+ LoadSurnamesByCountry(filepath : const std::filesystem::path&) : const std::unordered_map<std::string, surname_list>&
|
|
}
|
|
|
|
note right of JsonLoader
|
|
Each Load* method memoizes its result in
|
|
cache_ on first call; later calls on the
|
|
same instance return the cached value
|
|
without re-parsing.
|
|
end note
|
|
|
|
class MockCuratedDataService {
|
|
- locations_ : std::vector<City>
|
|
- personas_ : std::vector<UserPersona>
|
|
- forenames_by_country_ : std::unordered_map<std::string, forename_list>
|
|
- surnames_by_country_ : std::unordered_map<std::string, surname_list>
|
|
+ LoadCities(filepath : const std::filesystem::path&) : const std::vector<City>&
|
|
+ LoadPersonas(filepath : const std::filesystem::path&) : const std::vector<UserPersona>&
|
|
+ LoadForenamesByCountry(filepath : const std::filesystem::path&) : const std::unordered_map<std::string, forename_list>&
|
|
+ LoadSurnamesByCountry(filepath : const std::filesystem::path&) : const std::unordered_map<std::string, surname_list>&
|
|
}
|
|
|
|
note right of MockCuratedDataService
|
|
Fixed 4-location / 3-persona dataset
|
|
(US, DE, FR, BE) used in --mocked runs;
|
|
filepath arguments are ignored.
|
|
end note
|
|
|
|
interface IPostalCodeService <<interface>> {
|
|
+ GeneratePostalCode(location : const City&) : std::string
|
|
}
|
|
|
|
class MockPostalCodeService {
|
|
+ GeneratePostalCode(location : const City&) : std::string
|
|
}
|
|
|
|
note right of MockPostalCodeService
|
|
Ignores location.postal_regex and returns
|
|
location.postal_code_examples.front(). Bound
|
|
unconditionally in main.cc's DI graph (no
|
|
--mocked branch yet -- no real implementation
|
|
exists to switch to) and called from
|
|
GenerateBreweries() per brewery, stored on
|
|
BreweryRecord::address. A real implementation
|
|
needs a xeger-style generator to turn
|
|
postal_regex into a synthesized matching
|
|
string. See ROADMAP.md §9.
|
|
end note
|
|
|
|
interface IExportService <<interface>> {
|
|
+ Initialize() : void
|
|
+ ProcessRecord(brewery : const BreweryRecord&) : uint64_t
|
|
+ ProcessRecord(user : const UserRecord&) : uint64_t
|
|
+ Finalize() : void
|
|
}
|
|
|
|
class SqliteExportService {
|
|
- date_time_provider_ : std::unique_ptr<IDateTimeProvider>
|
|
- run_timestamp_utc_ : std::string
|
|
- database_path_ : std::filesystem::path
|
|
- db_handle_ : SqliteDatabaseHandle
|
|
- insert_city_stmt_ : SqliteStatementHandle
|
|
- insert_brewery_stmt_ : SqliteStatementHandle
|
|
- insert_user_stmt_ : SqliteStatementHandle
|
|
- transaction_open_ : bool
|
|
- city_cache_ : std::unordered_map<std::string, sqlite3_int64>
|
|
+ Initialize() : void
|
|
+ ProcessRecord(brewery : const BreweryRecord&) : uint64_t
|
|
+ ProcessRecord(user : const UserRecord&) : uint64_t
|
|
+ Finalize() : void
|
|
- InitializeSchema() : void
|
|
- ResolveCityId(location : const City&) : sqlite3_int64
|
|
}
|
|
|
|
interface IDateTimeProvider <<interface>> {
|
|
+ GetUtcTimestamp() : std::string
|
|
}
|
|
|
|
class SystemDateTimeProvider {
|
|
+ GetUtcTimestamp() : std::string
|
|
}
|
|
|
|
' Structural Relationships / Dependency Injection
|
|
BiergartenPipelineOrchestrator *-- ILogger : owns
|
|
BiergartenPipelineOrchestrator *-- IEnrichmentService : owns
|
|
BiergartenPipelineOrchestrator *-- DataGenerator : owns
|
|
BiergartenPipelineOrchestrator *-- IExportService : owns
|
|
BiergartenPipelineOrchestrator *-- ICuratedDataService : owns
|
|
BiergartenPipelineOrchestrator *-- IPostalCodeService : owns
|
|
|
|
LogEntry *-- LogLevel
|
|
LogEntry *-- PipelinePhase
|
|
LogDTO *-- LogLevel
|
|
LogDTO *-- PipelinePhase
|
|
ILogger <|.. LogProducer : implements
|
|
LogProducer ..> LogEntry : emits
|
|
LogDispatcher ..> LogEntry : consumes
|
|
|
|
IEnrichmentService <|.. WikipediaEnrichmentService : implements
|
|
IEnrichmentService <|.. MockEnrichmentService : implements
|
|
WikipediaEnrichmentService *-- WebClient : owns
|
|
|
|
WebClient <|.. HttpWebClient : implements
|
|
|
|
DataGenerator <|.. MockGenerator : implements
|
|
DataGenerator <|.. LlamaGenerator : implements
|
|
|
|
LlamaGenerator *-- IPromptFormatter : uses
|
|
LlamaGenerator *-- IPromptDirectory : uses
|
|
|
|
IPromptFormatter <|.. Gemma4JinjaPromptFormatter : implements
|
|
IPromptDirectory <|.. PromptDirectory : implements
|
|
|
|
ICuratedDataService <|.. JsonLoader : implements
|
|
ICuratedDataService <|.. MockCuratedDataService : implements
|
|
|
|
IPostalCodeService <|.. MockPostalCodeService : implements
|
|
|
|
IExportService <|.. SqliteExportService : implements
|
|
SqliteExportService *-- IDateTimeProvider : owns
|
|
IDateTimeProvider <|.. SystemDateTimeProvider : implements
|
|
|
|
@enduml
|