You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ModelService.cs 7.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using LLama.Web.Async;
  2. using LLama.Web.Common;
  3. using LLama.Web.Models;
  4. using System.Collections.Concurrent;
  5. namespace LLama.Web.Services
  6. {
  7. /// <summary>
  8. /// Sercive for handling Models,Weights & Contexts
  9. /// </summary>
  10. public class ModelService : IModelService
  11. {
  12. private readonly AsyncLock _modelLock;
  13. private readonly AsyncLock _contextLock;
  14. private readonly LLamaOptions _configuration;
  15. private readonly ConcurrentDictionary<string, LLamaModel> _modelInstances;
  16. /// <summary>
  17. /// Initializes a new instance of the <see cref="ModelService"/> class.
  18. /// </summary>
  19. /// <param name="logger">The logger.</param>
  20. /// <param name="options">The options.</param>
  21. public ModelService(LLamaOptions configuration)
  22. {
  23. _modelLock = new AsyncLock();
  24. _contextLock = new AsyncLock();
  25. _configuration = configuration;
  26. _modelInstances = new ConcurrentDictionary<string, LLamaModel>();
  27. }
  28. /// <summary>
  29. /// Loads a model with the provided configuration.
  30. /// </summary>
  31. /// <param name="modelOptions">The model configuration.</param>
  32. /// <returns></returns>
  33. public async Task<LLamaModel> LoadModel(ModelOptions modelOptions)
  34. {
  35. if (_modelInstances.TryGetValue(modelOptions.Name, out var existingModel))
  36. return existingModel;
  37. using (await _modelLock.LockAsync())
  38. {
  39. if (_modelInstances.TryGetValue(modelOptions.Name, out var model))
  40. return model;
  41. // If in single mode unload any other models
  42. if (_configuration.ModelLoadType == ModelLoadType.Single
  43. || _configuration.ModelLoadType == ModelLoadType.PreloadSingle)
  44. await UnloadModels();
  45. model = new LLamaModel(modelOptions);
  46. _modelInstances.TryAdd(modelOptions.Name, model);
  47. return model;
  48. }
  49. }
  50. /// <summary>
  51. /// Loads the models.
  52. /// </summary>
  53. public async Task LoadModels()
  54. {
  55. if (_configuration.ModelLoadType == ModelLoadType.Single
  56. || _configuration.ModelLoadType == ModelLoadType.Multiple)
  57. return;
  58. foreach (var modelConfig in _configuration.Models)
  59. {
  60. await LoadModel(modelConfig);
  61. //Only preload first model if in SinglePreload mode
  62. if (_configuration.ModelLoadType == ModelLoadType.PreloadSingle)
  63. break;
  64. }
  65. }
  66. /// <summary>
  67. /// Unloads the model.
  68. /// </summary>
  69. /// <param name="modelName">Name of the model.</param>
  70. /// <returns></returns>
  71. public Task UnloadModel(string modelName)
  72. {
  73. if (_modelInstances.TryRemove(modelName, out var model))
  74. {
  75. model?.Dispose();
  76. return Task.FromResult(true);
  77. }
  78. return Task.FromResult(false);
  79. }
  80. /// <summary>
  81. /// Unloads all models.
  82. /// </summary>
  83. public async Task UnloadModels()
  84. {
  85. foreach (var modelName in _modelInstances.Keys)
  86. {
  87. await UnloadModel(modelName);
  88. }
  89. }
  90. /// <summary>
  91. /// Gets a model ny name.
  92. /// </summary>
  93. /// <param name="modelName">Name of the model.</param>
  94. /// <returns></returns>
  95. public Task<LLamaModel> GetModel(string modelName)
  96. {
  97. _modelInstances.TryGetValue(modelName, out var model);
  98. return Task.FromResult(model);
  99. }
  100. /// <summary>
  101. /// Gets a context from the specified model.
  102. /// </summary>
  103. /// <param name="modelName">Name of the model.</param>
  104. /// <param name="contextName">The contextName.</param>
  105. /// <returns></returns>
  106. /// <exception cref="System.Exception">Model not found</exception>
  107. public async Task<LLamaContext> GetContext(string modelName, string contextName)
  108. {
  109. if (!_modelInstances.TryGetValue(modelName, out var model))
  110. throw new Exception("Model not found");
  111. return await model.GetContext(contextName);
  112. }
  113. /// <summary>
  114. /// Creates a context on the specified model.
  115. /// </summary>
  116. /// <param name="modelName">Name of the model.</param>
  117. /// <param name="contextName">The contextName.</param>
  118. /// <returns></returns>
  119. /// <exception cref="System.Exception">Model not found</exception>
  120. public async Task<LLamaContext> CreateContext(string modelName, string contextName)
  121. {
  122. if (!_modelInstances.TryGetValue(modelName, out var model))
  123. throw new Exception("Model not found");
  124. using (await _contextLock.LockAsync())
  125. {
  126. return await model.CreateContext(contextName);
  127. }
  128. }
  129. /// <summary>
  130. /// Removes a context from the specified model.
  131. /// </summary>
  132. /// <param name="modelName">Name of the model.</param>
  133. /// <param name="contextName">The contextName.</param>
  134. /// <returns></returns>
  135. /// <exception cref="System.Exception">Model not found</exception>
  136. public async Task<bool> RemoveContext(string modelName, string contextName)
  137. {
  138. if (!_modelInstances.TryGetValue(modelName, out var model))
  139. throw new Exception("Model not found");
  140. using (await _contextLock.LockAsync())
  141. {
  142. return await model.RemoveContext(contextName);
  143. }
  144. }
  145. /// <summary>
  146. /// Loads, Gets,Creates a Model and a Context
  147. /// </summary>
  148. /// <param name="modelName">Name of the model.</param>
  149. /// <param name="contextName">The contextName.</param>
  150. /// <returns></returns>
  151. /// <exception cref="System.Exception">Model option '{modelName}' not found</exception>
  152. public async Task<(LLamaModel, LLamaContext)> GetOrCreateModelAndContext(string modelName, string contextName)
  153. {
  154. if (_modelInstances.TryGetValue(modelName, out var model))
  155. return (model, await model.GetContext(contextName) ?? await model.CreateContext(contextName));
  156. // Get model configuration
  157. var modelConfig = _configuration.Models.FirstOrDefault(x => x.Name == modelName);
  158. if (modelConfig is null)
  159. throw new Exception($"Model option '{modelName}' not found");
  160. // Load Model
  161. model = await LoadModel(modelConfig);
  162. // Get or Create Context
  163. return (model, await model.GetContext(contextName) ?? await model.CreateContext(contextName));
  164. }
  165. }
  166. }