Spaces:
Running
Running
| // Copyright 2026 The ODML Authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| namespace litert::lm { | |
| // Factory class to create Engine instances. | |
| // The factory is a singleton class that is used to create Engine instances. | |
| // It is used to decouple the engine creation logic from the engine | |
| // implementation. This allows us to register different engine types and create | |
| // them at runtime. | |
| // | |
| // Example usage: | |
| // // Create an engine instance of type kLiteRTCompiledModel. | |
| // auto engine = EngineFactory::Create( | |
| // EngineFactory::EngineType::kLiteRTCompiledModel, | |
| // std::move(engine_settings)); | |
| // CHECK_OK(engine); | |
| // | |
| // Note: | |
| // - Ensure the desired engine type is registered (i.e., add the | |
| // implementation library as a dependency) | |
| // | |
| class EngineFactory { | |
| public: | |
| // Function signature to create an Engine instance. | |
| using Creator = absl::AnyInvocable<absl::StatusOr<std::unique_ptr<Engine>>( | |
| EngineSettings settings, absl::string_view input_prompt_as_hint)>; | |
| // The type of engine to create. | |
| enum class EngineType { | |
| kAdvancedLiteRTCompiledModel, | |
| kLiteRTCompiledModel, | |
| }; | |
| // Returns the string representation of the engine type. | |
| static std::string EngineTypeToString(EngineType engine_type) { | |
| switch (engine_type) { | |
| case EngineType::kLiteRTCompiledModel: | |
| return "kLiteRTCompiledModel"; | |
| default: | |
| return "Unknown"; | |
| } | |
| } | |
| // Creates a default Engine instance of type kLiteRTCompiledModel. | |
| static absl::StatusOr<std::unique_ptr<Engine>> CreateDefault( | |
| EngineSettings settings, absl::string_view input_prompt_as_hint = "") { | |
| return Create(EngineType::kLiteRTCompiledModel, std::move(settings), | |
| input_prompt_as_hint); | |
| } | |
| // Creates an Engine instance of any registered type. | |
| // If multiple engine types are registered, the first one is used. | |
| // The ordering of the engine can be observed using ListEngineTypes(). | |
| static absl::StatusOr<std::unique_ptr<Engine>> CreateAny( | |
| EngineSettings settings, absl::string_view input_prompt_as_hint = "") { | |
| auto& instance = Instance(); | |
| if (instance.registry_.size() != 1) { | |
| ABSL_LOG(WARNING) << "Multiple engine types are registered. " | |
| << "Using the first one with type: " | |
| << EngineTypeToString( | |
| instance.registry_.begin()->first); | |
| } | |
| return Create(instance.registry_.begin()->first, std::move(settings), | |
| input_prompt_as_hint); | |
| } | |
| // Creates an Engine instance of the given type. | |
| static absl::StatusOr<std::unique_ptr<Engine>> Create( | |
| EngineType engine_type, EngineSettings settings, | |
| absl::string_view input_prompt_as_hint = "") { | |
| auto& instance = Instance(); | |
| auto it = instance.registry_.find(engine_type); | |
| if (it == instance.registry_.end()) { | |
| return absl::NotFoundError( | |
| absl::StrCat("Engine type not found: ", engine_type)); | |
| } | |
| return it->second(std::move(settings), input_prompt_as_hint); | |
| }; | |
| // Returns the singleton instance of the EngineFactory. | |
| static EngineFactory& Instance() { | |
| static EngineFactory* instance = new EngineFactory(); | |
| return *instance; | |
| } | |
| // Registers a creator for the given engine type. Please use the | |
| // LITERT_LM_REGISTER_ENGINE macro to register an engine type. | |
| absl::Status Register(EngineType engine_type, Creator creator) { | |
| if (registry_.contains(engine_type)) { | |
| return absl::AlreadyExistsError( | |
| absl::StrCat("Engine type already exists: ", engine_type)); | |
| } | |
| registry_[engine_type] = std::move(creator); | |
| return absl::OkStatus(); | |
| } | |
| // Unregisters the creator for the given engine type. | |
| absl::Status Unregister(EngineType engine_type) { | |
| if (!registry_.contains(engine_type)) { | |
| return absl::NotFoundError( | |
| absl::StrCat("Engine type not found: ", engine_type)); | |
| } | |
| registry_.erase(engine_type); | |
| return absl::OkStatus(); | |
| } | |
| // Lists all registered engine types. | |
| absl::StatusOr<std::vector<EngineType>> ListEngineTypes() const { | |
| std::vector<EngineType> engine_types; | |
| for (const auto& [engine_type, creator] : registry_) { | |
| engine_types.push_back(engine_type); | |
| } | |
| return engine_types; | |
| } | |
| private: | |
| absl::flat_hash_map<EngineType, Creator> registry_; | |
| }; | |
| // Helper struct to register an engine type with the EngineFactory. | |
| struct EngineRegisterer { | |
| EngineRegisterer(EngineFactory::EngineType engine_type, | |
| EngineFactory::Creator creator) { | |
| absl::Status status = | |
| EngineFactory::Instance().Register(engine_type, std::move(creator)); | |
| if (!status.ok()) { | |
| ABSL_LOG(ERROR) << "Failed to register engine: " << status; | |
| } | |
| } | |
| }; | |
| // Macro to register an engine type with the EngineFactory. | |
| } // namespace litert::lm | |