1+ # Standard library imports
2+ import logging
3+ import os
4+
5+ from config .settings .base import (
6+ LLAMA_ENABLED ,
7+ LLAMA_MODEL_DIR ,
8+ )
9+
10+ # Third-party imports
11+ import google .generativeai as genai
12+
13+ # Local application imports
14+ from model_ai import messages
15+ from model_ai .exceptions import (
16+ LlamaDisabledError ,
17+ LlamaModelNotFoundError ,
18+ LlamaNotInstalledError ,
19+ )
20+ from model_ai .models import LlamaModel
21+
22+
23+ class LlamaService :
24+ # Singleton pattern to cache the LLaMA model instance
25+ _cached_llm = None
26+
27+ def __init__ (self , messages = None , response_format = None , max_tokens = 4000 , temperature = 0.1 , top_p = 0.1 , mode = 'chat' , nthreads = 2 ):
28+ self .messages = messages
29+ self .response_format = response_format
30+ self .max_tokens = max_tokens
31+ self .temperature = temperature
32+ self .top_p = top_p
33+ self .mode = mode
34+
35+ model_ai = LlamaModel .objects .first ()
36+
37+ # Try to use Gemini if configured
38+ if not model_ai and model_ai .api_key_gemini :
39+
40+ if not LLAMA_ENABLED :
41+ raise LlamaDisabledError ("LLaMA is disabled in settings." )
42+
43+ if LlamaService ._cached_llm is None :
44+ try :
45+ from llama_cpp import Llama
46+ except ImportError as e :
47+ raise LlamaNotInstalledError ("The 'llama-cpp-python' package is not installed. Please use the llama-activated Docker image (Dockerfile.llama)." ) from e
48+
49+ model_ai = LlamaModel .objects .first ()
50+ if not model_ai :
51+ raise LlamaModelNotFoundError ("No LLaMA model configured in the database. Please add a LLaMA model entry." )
52+
53+ model_path = os .path .join (LLAMA_MODEL_DIR , model_ai .name_file )
54+ if not os .path .isfile (model_path ):
55+ raise LlamaModelNotFoundError (f"LLaMA model file not found at { model_path } . Please ensure the model is downloaded and the path is correct." )
56+
57+ try :
58+ LlamaService ._cached_llm = Llama (model_path = model_path , n_ctx = max_tokens , n_threads = nthreads )
59+ except Exception as e :
60+ raise RuntimeError (f"Failed to initialize LLaMA model: { e } " ) from e
61+
62+ self .llm = LlamaService ._cached_llm
63+
64+ def run (self , user_input ):
65+ if self .mode == 'chat' :
66+ return self ._run_as_chat (user_input )
67+ elif self .mode == 'prompt' :
68+ return self ._run_as_content_generation (user_input )
69+
70+ def _run_as_chat (self , user_input ):
71+ """ Run LLaMA in chat mode."""
72+ input = self .messages .copy ()
73+ input .append ({
74+ 'role' : 'user' ,
75+ 'content' : user_input
76+ })
77+ return self .llm .create_chat_completion (
78+ messages = input ,
79+ response_format = self .response_format ,
80+ max_tokens = self .max_tokens ,
81+ temperature = self .temperature ,
82+ top_p = self .top_p
83+ )
84+
85+ def _run_as_content_generation (self , user_input ):
86+ """ Run LLaMA in completion mode."""
87+ model_ai = LlamaModel .objects .first ()
88+
89+ # Try to use Gemini if configured
90+ if model_ai and model_ai .api_key_gemini :
91+
92+ # Setup Gemini API key
93+ genai .configure (api_key = model_ai .api_key_gemini )
94+
95+ # Fetch the Gemini model
96+ # FIXME: Hardcoded model name
97+ model = genai .GenerativeModel ('models/gemini-3.1-flash-lite-preview' )
98+
99+ # Generate content using Gemini
100+ return model .generate_content (user_input ).text
101+
102+ # Gemini not configured, fallback to LLaMA
103+ else :
104+ return self .llm (
105+ user_input ,
106+ max_tokens = self .max_tokens ,
107+ temperature = self .temperature ,
108+ stop = ["\n \n " ]
109+ )
110+
111+ class LlamaInputSettings :
112+ @staticmethod
113+ def get_first_metadata (text ):
114+ logging .debug (messages .ALL_FIRST_BLOCK .format (text = text ))
115+ return messages .ALL_FIRST_BLOCK .format (text = text )
116+
117+ @staticmethod
118+ def get_doi_and_section ():
119+ return messages .DOI_AND_SECTION_MESSAGES , messages .DOI_AND_SECTION_FORMAT
120+
121+ @staticmethod
122+ def get_titles ():
123+ return messages .TITLE_MESSAGES , messages .TITLE_RESPONSE_FORMAT
124+
125+ @staticmethod
126+ def get_author_config ():
127+ return messages .AUTHOR_MESSAGES , messages .AUTHOR_RESPONSE_FORMAT
128+
129+ @staticmethod
130+ def get_affiliations ():
131+ return messages .AFFILIATION_MESSAGES , messages .AFFILIATION_RESPONSE_FORMAT
132+
133+ @staticmethod
134+ def get_reference ():
135+ return messages .REFERENCE_MESSAGES , messages .REFERENCE_RESPONSE_FORMAT
136+
0 commit comments