@@ -85,6 +85,25 @@ func runDev(ctx context.Context, options *DevStartOptions) error {
8585 return err
8686 }
8787
88+ // Detect and collect lora-adapter parts
89+ var loraPaths []string
90+ for _ , part := range kitfile .Model .Parts {
91+ if strings .EqualFold (part .Type , "lora-adapter" ) {
92+ partAbsPath , _ , err := filesystem .VerifySubpath (options .contextDir , part .Path )
93+ if err != nil {
94+ output .Debugf ("Failed to verify lora-adapter path %s: %v" , part .Path , err )
95+ continue
96+ }
97+ loraPath , err := findLoraAdapterFile (partAbsPath )
98+ if err != nil {
99+ output .Debugf ("Failed to find lora-adapter file in %s: %v" , partAbsPath , err )
100+ continue
101+ }
102+ output .Infof ("Found lora-adapter: %s" , loraPath )
103+ loraPaths = append (loraPaths , loraPath )
104+ }
105+ }
106+
88107 llmHarness := & harness.LLMHarness {}
89108 llmHarness .Host = options .host
90109 llmHarness .Port = options .port
@@ -93,7 +112,7 @@ func runDev(ctx context.Context, options *DevStartOptions) error {
93112 return err
94113 }
95114
96- if err := llmHarness .Start (modelPath ); err != nil {
115+ if err := llmHarness .Start (modelPath , loraPaths ); err != nil {
97116 return err
98117 }
99118
@@ -170,6 +189,43 @@ func findModelFile(absPath string) (string, error) {
170189 return modelPath , nil
171190}
172191
192+ // findLoraAdapterFile finds a lora adapter file (.gguf) within a path.
193+ // If the path is a regular file, it returns that file.
194+ // If the path is a directory, it searches for .gguf files within it.
195+ func findLoraAdapterFile (absPath string ) (string , error ) {
196+ stat , err := os .Lstat (absPath )
197+ if err != nil {
198+ return "" , err
199+ }
200+ if stat .Mode ().IsRegular () {
201+ // lora adapter path refers to a regular file; assume it's fine to use
202+ return absPath , nil
203+ } else if ! stat .IsDir () {
204+ return "" , fmt .Errorf ("could not find lora adapter file in %s: path is not regular file or directory" , absPath )
205+ }
206+
207+ loraPath := ""
208+ if err := filepath .WalkDir (absPath , func (path string , d fs.DirEntry , err error ) error {
209+ if err != nil {
210+ return err
211+ }
212+ if strings .HasSuffix (path , ".gguf" ) && d .Type ().IsRegular () {
213+ if loraPath == "" {
214+ loraPath = path
215+ } else {
216+ return fmt .Errorf ("multiple lora adapter files found: %s and %s" , loraPath , path )
217+ }
218+ }
219+ return nil
220+ }); err != nil {
221+ return "" , fmt .Errorf ("error searching for lora adapter file in %s: %w" , absPath , err )
222+ } else if loraPath == "" {
223+ return "" , fmt .Errorf ("could not find lora adapter file in %s" , absPath )
224+ }
225+ output .Debugf ("Found lora adapter path in directory %s at %s" , absPath , loraPath )
226+ return loraPath , nil
227+ }
228+
173229// extractModelKitToCache extracts a ModelKit reference to a cache directory
174230// using the unpack library with model filter
175231func extractModelKitToCache (ctx context.Context , options * DevStartOptions ) error {
0 commit comments