mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-07-16 17:47:22 +00:00
Update user generation
This commit is contained in:
69
tooling/pipeline/includes/biergarten_pipeline.h
Normal file
69
tooling/pipeline/includes/biergarten_pipeline.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_PIPELINE_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_PIPELINE_H_
|
||||
|
||||
/**
|
||||
* @file biergarten_pipeline.h
|
||||
* @brief Master umbrella header — includes every public header in the
|
||||
* Biergarten pipeline.
|
||||
*/
|
||||
|
||||
// --- orchestrator ---
|
||||
#include "biergarten_pipeline_orchestrator.h"
|
||||
|
||||
// --- concurrency ---
|
||||
#include "concurrency/bounded_channel.h"
|
||||
|
||||
// --- data_generation ---
|
||||
#include "data_generation/data_generator.h"
|
||||
#include "data_generation/json_grammars.h"
|
||||
#include "data_generation/llama_generator.h"
|
||||
#include "data_generation/llama_generator_helpers.h"
|
||||
#include "data_generation/mock_generator.h"
|
||||
#include "data_generation/prompt_formatting/gemma4_jinja_prompt_formatter.h"
|
||||
#include "data_generation/prompt_formatting/prompt_formatter.h"
|
||||
|
||||
// --- data_model ---
|
||||
#include "data_model/generated_models.h"
|
||||
#include "data_model/models.h"
|
||||
|
||||
// --- json_handling ---
|
||||
#include "json_handling/json_loader.h"
|
||||
#include "json_handling/pretty_print.h"
|
||||
|
||||
// --- llama backend ---
|
||||
#include "llama_backend_state.h"
|
||||
|
||||
// --- services: curated_data ---
|
||||
#include "services/curated_data/curated_data_service.h"
|
||||
|
||||
// --- services: database ---
|
||||
#include "services/database/export_service.h"
|
||||
#include "services/database/sqlite_connection_helpers.h"
|
||||
#include "services/database/sqlite_export_service.h"
|
||||
#include "services/database/sqlite_export_service_helpers.h"
|
||||
#include "services/database/sqlite_handle_types.h"
|
||||
#include "services/database/sqlite_statement_helpers.h"
|
||||
|
||||
// --- services: datetime ---
|
||||
#include "services/datetime/date_time_provider.h"
|
||||
#include "services/datetime/timer.h"
|
||||
|
||||
// --- services: enrichment ---
|
||||
#include "services/enrichment/enrichment_service.h"
|
||||
#include "services/enrichment/mock_enrichment.h"
|
||||
#include "services/enrichment/wikipedia_service.h"
|
||||
|
||||
// --- services: logging ---
|
||||
#include "services/logging/log_dispatcher.h"
|
||||
#include "services/logging/log_entry.h"
|
||||
#include "services/logging/log_producer.h"
|
||||
#include "services/logging/logger.h"
|
||||
|
||||
// --- services: prompting ---
|
||||
#include "services/prompting/prompt_directory.h"
|
||||
|
||||
// --- web_client ---
|
||||
#include "web_client/http_web_client.h"
|
||||
#include "web_client/web_client.h"
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_PIPELINE_H_
|
||||
@@ -1,12 +1,9 @@
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_DATA_GENERATOR_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_DATA_GENERATOR_H_
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_PIPELINE_ORCHESTRATOR_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_PIPELINE_ORCHESTRATOR_H_
|
||||
|
||||
/**
|
||||
* @file biergarten_pipeline_orchestrator.h
|
||||
* @brief Orchestration for end-to-end brewery and user data generation.
|
||||
*
|
||||
* Coordinates location loading, enrichment, and generation phases to produce
|
||||
* a complete dataset, wiring dependencies selected at the composition root.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
@@ -103,10 +100,6 @@ class BiergartenPipelineOrchestrator {
|
||||
* @brief Generate users grounded in sampled names and personas for
|
||||
* enriched cities.
|
||||
*
|
||||
* Loads personas.json / forenames-by-country.json /
|
||||
* surnames-by-country.json itself, mirroring how QueryCitiesWithCountries()
|
||||
* owns its own locations.json load.
|
||||
*
|
||||
* @param cities Span of enriched city data.
|
||||
*/
|
||||
void GenerateUsers(std::span<const EnrichedCity> cities);
|
||||
@@ -120,4 +113,4 @@ class BiergartenPipelineOrchestrator {
|
||||
std::vector<UserRecord> generated_users_;
|
||||
};
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_DATA_GENERATOR_H_
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_PIPELINE_ORCHESTRATOR_H_
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "bounded_channel.h"
|
||||
#include "concurrency/bounded_channel.h"
|
||||
|
||||
template <typename T>
|
||||
void BoundedChannel<T>::Send(T item) {
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_DATA_GENERATION_LLAMA_GENERATOR_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_DATA_GENERATION_LLAMA_GENERATOR_H_
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
/**
|
||||
* @file data_generation/llama_generator.h
|
||||
* @brief llama.cpp-backed implementation of DataGenerator.
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "../services/prompting/prompt_directory.h"
|
||||
#include "data_generation/data_generator.h"
|
||||
#include "data_generation/prompt_formatting/prompt_formatter.h"
|
||||
#include "data_model/models.h"
|
||||
#include "services/logging/logger.h"
|
||||
#include "services/prompting/prompt_directory.h"
|
||||
|
||||
struct llama_model;
|
||||
struct llama_context;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <boost/program_options.hpp>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
@@ -93,8 +94,23 @@ struct ForenameEntry {
|
||||
* dataset (e.g. "M", "F").
|
||||
*/
|
||||
std::string gender{};
|
||||
|
||||
bool operator==(const ForenameEntry& other) const {
|
||||
return name == other.name && gender == other.gender;
|
||||
}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<ForenameEntry> {
|
||||
size_t operator()(const ForenameEntry& entry) const noexcept {
|
||||
const size_t name_hash = std::hash<std::string>{}(entry.name);
|
||||
const size_t gender_hash = std::hash<std::string>{}(entry.gender);
|
||||
return name_hash ^ (gender_hash << 1);
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
/**
|
||||
* @brief A persona archetype used to ground LLM-generated user bios.
|
||||
*/
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_DATA_MODEL_NAMES_BY_COUNTRY_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_DATA_MODEL_NAMES_BY_COUNTRY_H_
|
||||
|
||||
/**
|
||||
* @file data_model/names_by_country.h
|
||||
* @brief Sampling over the names-by-country fixture data.
|
||||
*/
|
||||
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "data_model/models.h"
|
||||
|
||||
/**
|
||||
* @brief Samples locale-appropriate names from curated forename/surname
|
||||
* fixture data, keyed by ISO 3166-1 country code.
|
||||
*
|
||||
* Forenames and surnames are kept in separate maps (mirroring the source
|
||||
* dataset's own shape) so per-forename gender is preserved; pairing happens
|
||||
* at sample time rather than being precomputed, so no information from the
|
||||
* source dataset is discarded up front.
|
||||
*/
|
||||
class NamesByCountry {
|
||||
public:
|
||||
NamesByCountry(std::unordered_map<std::string, std::vector<ForenameEntry>>
|
||||
forenames_by_country,
|
||||
std::unordered_map<std::string, std::vector<std::string>>
|
||||
surnames_by_country);
|
||||
|
||||
/**
|
||||
* @brief Samples a first/last name pair for the given country.
|
||||
*
|
||||
* @param iso3166_1 ISO 3166-1 country code to sample for.
|
||||
* @param rng Random source used for sampling.
|
||||
* @return A sampled Name, or std::nullopt if the country has no forename
|
||||
* or no surname entries.
|
||||
*/
|
||||
[[nodiscard]] std::optional<Name> SampleName(const std::string& iso3166_1,
|
||||
std::mt19937& rng) const;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::vector<ForenameEntry>>
|
||||
forenames_by_country_;
|
||||
std::unordered_map<std::string, std::vector<std::string>>
|
||||
surnames_by_country_;
|
||||
};
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_DATA_MODEL_NAMES_BY_COUNTRY_H_
|
||||
@@ -7,41 +7,49 @@
|
||||
*/
|
||||
|
||||
#include <filesystem>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "data_model/models.h"
|
||||
#include "data_model/names_by_country.h"
|
||||
#include "services/curated_data/curated_data_service.h"
|
||||
|
||||
/**
|
||||
* @brief Loads curated location, persona, and name data from JSON files.
|
||||
*/
|
||||
class JsonLoader final : public ICuratedDataService {
|
||||
struct cache {
|
||||
std::vector<Location> locations;
|
||||
std::vector<UserPersona> personas;
|
||||
std::unordered_map<std::string, forename_list> forenames_by_country;
|
||||
std::unordered_map<std::string, surname_list> surnames_by_country;
|
||||
|
||||
cache() = default;
|
||||
~cache() = default;
|
||||
};
|
||||
|
||||
cache cache_;
|
||||
|
||||
public:
|
||||
JsonLoader() = default;
|
||||
|
||||
/**
|
||||
* @brief Parses a JSON array file and returns all location records.
|
||||
*/
|
||||
std::vector<Location> LoadLocations(
|
||||
const std::filesystem::path& filepath) override;
|
||||
std::vector<Location> LoadLocations(const std::filesystem::path&) override;
|
||||
|
||||
/**
|
||||
* @brief Parses a JSON array file and returns all persona records.
|
||||
*/
|
||||
std::vector<UserPersona> LoadPersonas(
|
||||
const std::filesystem::path& filepath) override;
|
||||
std::vector<UserPersona> LoadPersonas(const std::filesystem::path&) override;
|
||||
|
||||
std::unordered_map<std::string, forename_list> LoadForenamesByCountry(
|
||||
const std::filesystem::path&) override;
|
||||
|
||||
/**
|
||||
* @brief Parses the names-by-country fixture pair into a sampling-capable
|
||||
* NamesByCountry.
|
||||
*
|
||||
* @param forenames_filepath Path to forenames-by-country.json.
|
||||
* @param surnames_filepath Path to surnames-by-country.json.
|
||||
* @brief Parses a JSON file and returns all the forenames per country.
|
||||
*/
|
||||
NamesByCountry LoadNamesByCountry(
|
||||
const std::filesystem::path& forenames_filepath,
|
||||
const std::filesystem::path& surnames_filepath) override;
|
||||
std::unordered_map<std::string, surname_list> LoadSurnamesByCountry(
|
||||
const std::filesystem::path&) override;
|
||||
};
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_JSON_HANDLING_JSON_LOADER_H_
|
||||
|
||||
@@ -106,4 +106,4 @@ inline void PrettyPrint(std::ostream& outstream,
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_JSON_HANDLING_PRETTY_PRINT_H_
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
*/
|
||||
|
||||
#include <filesystem>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "data_model/models.h"
|
||||
#include "data_model/names_by_country.h"
|
||||
|
||||
using forename_list = std::unordered_set<ForenameEntry>;
|
||||
using surname_list = std::unordered_set<std::string>;
|
||||
/**
|
||||
* @brief Interface for services that load curated data used to seed
|
||||
* brewery/user generation.
|
||||
@@ -38,16 +40,10 @@ class ICuratedDataService {
|
||||
virtual std::vector<UserPersona> LoadPersonas(
|
||||
const std::filesystem::path& filepath) = 0;
|
||||
|
||||
/**
|
||||
* @brief Loads the names-by-country fixture pair into a sampling-capable
|
||||
* NamesByCountry.
|
||||
*
|
||||
* @param forenames_filepath Path to forenames-by-country.json.
|
||||
* @param surnames_filepath Path to surnames-by-country.json.
|
||||
*/
|
||||
virtual NamesByCountry LoadNamesByCountry(
|
||||
const std::filesystem::path& forenames_filepath,
|
||||
virtual std::unordered_map<std::string, forename_list> LoadForenamesByCountry(
|
||||
const std::filesystem::path& forenames_filepath) = 0;
|
||||
virtual std::unordered_map<std::string, surname_list> LoadSurnamesByCountry(
|
||||
const std::filesystem::path& surnames_filepath) = 0;
|
||||
};
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_CURATED_DATA_CURATED_DATA_SERVICE_H_
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_CURATED_DATA_CURATED_DATA_SERVICE_H_
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "sqlite_handle_types.h"
|
||||
#include "services/database/sqlite_handle_types.h"
|
||||
|
||||
namespace sqlite_export_service_internal {
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../datetime/date_time_provider.h"
|
||||
#include "data_model/models.h"
|
||||
#include "export_service.h"
|
||||
#include "sqlite_export_service_helpers.h"
|
||||
#include "services/database/export_service.h"
|
||||
#include "services/database/sqlite_export_service_helpers.h"
|
||||
#include "services/datetime/date_time_provider.h"
|
||||
|
||||
/**
|
||||
* @brief Persists generated brewery records into a fresh SQLite database.
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
/* Umbrella header for backward compatibility. */
|
||||
|
||||
#include "sqlite_connection_helpers.h"
|
||||
#include "sqlite_handle_types.h"
|
||||
#include "sqlite_statement_helpers.h"
|
||||
#include "services/database/sqlite_connection_helpers.h"
|
||||
#include "services/database/sqlite_handle_types.h"
|
||||
#include "services/database/sqlite_statement_helpers.h"
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_DATABASE_SQLITE_EXPORT_SERVICE_HELPERS_H_
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "sqlite_handle_types.h"
|
||||
#include "services/database/sqlite_handle_types.h"
|
||||
|
||||
namespace sqlite_export_service_internal {
|
||||
|
||||
@@ -109,30 +109,36 @@ INSERT INTO users (
|
||||
|
||||
// sqlite3_bind_*() parameter indices are 1-based, matching the "?"
|
||||
// placeholder order in the SQL above.
|
||||
inline constexpr int kLocationCityBindIndex = 1;
|
||||
inline constexpr int kLocationStateProvinceBindIndex = 2;
|
||||
inline constexpr int kLocationIso31662BindIndex = 3;
|
||||
inline constexpr int kLocationCountryBindIndex = 4;
|
||||
inline constexpr int kLocationIso31661BindIndex = 5;
|
||||
inline constexpr int kLocationLanguagesBindIndex = 6;
|
||||
inline constexpr int kLocationLatitudeBindIndex = 7;
|
||||
inline constexpr int kLocationLongitudeBindIndex = 8;
|
||||
enum eLocationBindIndex {
|
||||
kLocationCityBindIndex = 1,
|
||||
kLocationStateProvinceBindIndex,
|
||||
kLocationIso31662BindIndex,
|
||||
kLocationCountryBindIndex,
|
||||
kLocationIso31661BindIndex,
|
||||
kLocationLanguagesBindIndex,
|
||||
kLocationLatitudeBindIndex,
|
||||
kLocationLongitudeBindIndex,
|
||||
};
|
||||
|
||||
inline constexpr int kBreweryLocationIdBindIndex = 1;
|
||||
inline constexpr int kBreweryEnglishNameBindIndex = 2;
|
||||
inline constexpr int kBreweryEnglishDescriptionBindIndex = 3;
|
||||
inline constexpr int kBreweryLocalNameBindIndex = 4;
|
||||
inline constexpr int kBreweryLocalDescriptionBindIndex = 5;
|
||||
enum BreweryBindIndex {
|
||||
kBreweryLocationIdBindIndex = 1,
|
||||
kBreweryEnglishNameBindIndex,
|
||||
kBreweryEnglishDescriptionBindIndex,
|
||||
kBreweryLocalNameBindIndex,
|
||||
kBreweryLocalDescriptionBindIndex,
|
||||
};
|
||||
|
||||
inline constexpr int kUserLocationIdBindIndex = 1;
|
||||
inline constexpr int kUserFirstNameBindIndex = 2;
|
||||
inline constexpr int kUserLastNameBindIndex = 3;
|
||||
inline constexpr int kUserGenderBindIndex = 4;
|
||||
inline constexpr int kUserUsernameBindIndex = 5;
|
||||
inline constexpr int kUserBioBindIndex = 6;
|
||||
inline constexpr int kUserActivityWeightBindIndex = 7;
|
||||
inline constexpr int kUserEmailBindIndex = 8;
|
||||
inline constexpr int kUserDateOfBirthBindIndex = 9;
|
||||
enum UserBindIndex {
|
||||
kUserLocationIdBindIndex = 1,
|
||||
kUserFirstNameBindIndex,
|
||||
kUserLastNameBindIndex,
|
||||
kUserGenderBindIndex,
|
||||
kUserUsernameBindIndex,
|
||||
kUserBioBindIndex,
|
||||
kUserActivityWeightBindIndex,
|
||||
kUserEmailBindIndex,
|
||||
kUserDateOfBirthBindIndex,
|
||||
};
|
||||
|
||||
SqliteStatementHandle PrepareStatement(const SqliteDatabaseHandle& db_handle,
|
||||
std::string_view sql,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "enrichment_service.h"
|
||||
#include "services/enrichment/enrichment_service.h"
|
||||
|
||||
/**
|
||||
* @brief Enrichment service that returns no context for any location.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "enrichment_service.h"
|
||||
#include "services/enrichment/enrichment_service.h"
|
||||
#include "services/logging/logger.h"
|
||||
#include "web_client/web_client.h"
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
* a bounded channel for later processing by the dispatcher.
|
||||
*/
|
||||
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_CHANNEL_LOGGER_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_CHANNEL_LOGGER_H_
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOG_PRODUCER_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOG_PRODUCER_H_
|
||||
|
||||
#include <string_view>
|
||||
|
||||
@@ -50,4 +50,4 @@ class LogProducer final : public ILogger {
|
||||
BoundedChannel<LogEntry>& channel_;
|
||||
};
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_CHANNEL_LOGGER_H_
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOG_PRODUCER_H_
|
||||
|
||||
@@ -52,4 +52,4 @@ class HttpWebClient final : public WebClient {
|
||||
std::shared_ptr<ILogger> logger_;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_WEB_CLIENT_HTTP_WEB_CLIENT_H_
|
||||
|
||||
Reference in New Issue
Block a user