187 lines
6.5 KiB
Go
187 lines
6.5 KiB
Go
package cli
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"gitea.maximumdirect.net/eric/notarius/internal/core/artifacts"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/core/config"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/llm"
|
|
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
|
|
dndregister "gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/register"
|
|
genericregister "gitea.maximumdirect.net/eric/notarius/internal/modules/generic/register"
|
|
seriatimregister "gitea.maximumdirect.net/eric/notarius/internal/modules/seriatim/register"
|
|
)
|
|
|
|
type productionComponents struct {
|
|
registries pipeline.Registries
|
|
assets *llm.AssetRegistry
|
|
}
|
|
|
|
func newProductionComponents() (productionComponents, error) {
|
|
registries := pipeline.Registries{
|
|
Inputs: pipeline.NewInputAdapterRegistry(),
|
|
Chunkers: pipeline.NewChunkerRegistry(),
|
|
ArtifactCodecs: pipeline.NewArtifactCodecRegistry(),
|
|
ArtifactEvidence: pipeline.NewArtifactEvidenceRegistry(),
|
|
Extractors: pipeline.NewExtractorRegistry(),
|
|
Mergers: pipeline.NewMergerRegistry(),
|
|
Normalizers: pipeline.NewNormalizerRegistry(),
|
|
Validators: pipeline.NewValidatorRegistry(),
|
|
ValidatorChains: pipeline.NewValidatorChainRegistry(),
|
|
Outputs: pipeline.NewOutputEncoderRegistry(),
|
|
}
|
|
assets := llm.NewAssetRegistry()
|
|
registrars := []struct {
|
|
name string
|
|
register func(pipeline.Registries, *llm.AssetRegistry) error
|
|
}{
|
|
{name: "generic", register: genericregister.Register},
|
|
{name: "seriatim", register: seriatimregister.Register},
|
|
{name: "dnd", register: dndregister.Register},
|
|
}
|
|
for _, registrar := range registrars {
|
|
if err := registrar.register(registries, assets); err != nil {
|
|
return productionComponents{}, fmt.Errorf("register %s module family: %w", registrar.name, err)
|
|
}
|
|
}
|
|
return productionComponents{registries: registries, assets: assets}, nil
|
|
}
|
|
|
|
func productionRegistries() (pipeline.Registries, error) {
|
|
components, err := newProductionComponents()
|
|
return components.registries, err
|
|
}
|
|
|
|
func productionCatalog() (pipeline.ModuleCatalog, error) {
|
|
registries, err := productionRegistries()
|
|
if err != nil {
|
|
return pipeline.ModuleCatalog{}, err
|
|
}
|
|
return catalogFromRegistries(registries), nil
|
|
}
|
|
|
|
func productionPromptAssets() (*llm.AssetRegistry, error) {
|
|
components, err := newProductionComponents()
|
|
return components.assets, err
|
|
}
|
|
|
|
func effectiveCatalog(opts Options) (pipeline.ModuleCatalog, error) {
|
|
if !isEmptyCatalog(opts.Catalog) {
|
|
return opts.Catalog, nil
|
|
}
|
|
if !isEmptyRegistries(opts.Registries) {
|
|
return catalogFromRegistries(opts.Registries), nil
|
|
}
|
|
return productionCatalog()
|
|
}
|
|
|
|
func effectiveRegistries(opts Options) (pipeline.Registries, error) {
|
|
if !isEmptyRegistries(opts.Registries) {
|
|
return opts.Registries, nil
|
|
}
|
|
if !isEmptyCatalog(opts.Catalog) {
|
|
return registriesFromCatalog(opts.Catalog), nil
|
|
}
|
|
return productionRegistries()
|
|
}
|
|
|
|
func catalogFromRegistries(registries pipeline.Registries) pipeline.ModuleCatalog {
|
|
return pipeline.ModuleCatalog{
|
|
Inputs: registries.Inputs,
|
|
Chunkers: registries.Chunkers,
|
|
ArtifactCodecs: registries.ArtifactCodecs,
|
|
ArtifactEvidence: registries.ArtifactEvidence,
|
|
Extractors: registries.Extractors,
|
|
Mergers: registries.Mergers,
|
|
Normalizers: registries.Normalizers,
|
|
Validators: registries.Validators,
|
|
ValidatorChains: registries.ValidatorChains,
|
|
Outputs: registries.Outputs,
|
|
}
|
|
}
|
|
|
|
func registriesFromCatalog(catalog pipeline.ModuleCatalog) pipeline.Registries {
|
|
return pipeline.Registries{
|
|
Inputs: catalog.Inputs,
|
|
Chunkers: catalog.Chunkers,
|
|
ArtifactCodecs: catalog.ArtifactCodecs,
|
|
ArtifactEvidence: catalog.ArtifactEvidence,
|
|
Extractors: catalog.Extractors,
|
|
Mergers: catalog.Mergers,
|
|
Normalizers: catalog.Normalizers,
|
|
Validators: catalog.Validators,
|
|
ValidatorChains: catalog.ValidatorChains,
|
|
Outputs: catalog.Outputs,
|
|
}
|
|
}
|
|
|
|
func isEmptyCatalog(catalog pipeline.ModuleCatalog) bool {
|
|
return catalog.Inputs == nil &&
|
|
catalog.Chunkers == nil &&
|
|
catalog.ArtifactCodecs == nil &&
|
|
catalog.ArtifactEvidence == nil &&
|
|
catalog.Extractors == nil &&
|
|
catalog.Mergers == nil &&
|
|
catalog.Normalizers == nil &&
|
|
catalog.Validators == nil &&
|
|
catalog.ValidatorChains == nil &&
|
|
catalog.Outputs == nil
|
|
}
|
|
|
|
func isEmptyRegistries(registries pipeline.Registries) bool {
|
|
return registries.Inputs == nil &&
|
|
registries.Chunkers == nil &&
|
|
registries.ArtifactCodecs == nil &&
|
|
registries.ArtifactEvidence == nil &&
|
|
registries.Extractors == nil &&
|
|
registries.Mergers == nil &&
|
|
registries.Normalizers == nil &&
|
|
registries.Validators == nil &&
|
|
registries.ValidatorChains == nil &&
|
|
registries.Outputs == nil
|
|
}
|
|
|
|
func productionLLMClientFactory(ctx context.Context, cfg config.Config, profileID string, overrides LLMRuntimeOverrides) (contracts.StructuredLLMClient, []artifacts.LLMProfileManifest, error) {
|
|
if err := ctx.Err(); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
assets, err := productionPromptAssets()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return buildProductionLLMClient(ctx, cfg, profileID, overrides, assets)
|
|
}
|
|
|
|
func productionLLMClientFactoryWithAssets(assets *llm.AssetRegistry) LLMClientFactory {
|
|
return func(ctx context.Context, cfg config.Config, profileID string, overrides LLMRuntimeOverrides) (contracts.StructuredLLMClient, []artifacts.LLMProfileManifest, error) {
|
|
return buildProductionLLMClient(ctx, cfg, profileID, overrides, assets)
|
|
}
|
|
}
|
|
|
|
func buildProductionLLMClient(ctx context.Context, cfg config.Config, profileID string, overrides LLMRuntimeOverrides, assets *llm.AssetRegistry) (contracts.StructuredLLMClient, []artifacts.LLMProfileManifest, error) {
|
|
if err := ctx.Err(); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if assets == nil {
|
|
return nil, nil, fmt.Errorf("production asset registry must not be nil")
|
|
}
|
|
recorder := llm.NewLLMProfileRecorder()
|
|
client, err := llm.NewPromptKitClient(llm.PromptKitClientConfig{
|
|
ProfileDir: cfg.PromptKit.ProfileDir,
|
|
ProfileFile: cfg.PromptKit.ProfileFile,
|
|
Assets: assets,
|
|
Recorder: recorder,
|
|
ReasoningEffort: overrides.ReasoningEffort,
|
|
})
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("create PromptKit-backed LLM client: %w", err)
|
|
}
|
|
scheduler, err := llm.NewScheduler(cfg.Concurrency.TotalLLM)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("create LLM scheduler: %w", err)
|
|
}
|
|
return llm.NewScheduledClient(client, scheduler), nil, nil
|
|
}
|