Enhance LLM functionality with PRO mode support and improved prompt handling
- Added support for PRO mode in LLM with specific instruction handling and context awareness. - Updated prompt building functions to include prefill options for better context management. - Introduced new inline examples for PRO mode in JSON format. - Enhanced system prompts to reflect PRO mode capabilities and rules. - Modified API endpoints to accommodate new parameters and ensure backward compatibility. - Improved test cases to validate new functionality and ensure comprehensive coverage.
This commit is contained in:
+21
-7
@@ -18,6 +18,9 @@ load_dotenv()
|
||||
LLM_BASE_URL = os.getenv('LLM_BASE_URL', 'http://localhost:11434/v1/')
|
||||
LLM_API_KEY = os.getenv('LLM_API_KEY', 'ollama')
|
||||
|
||||
# Auth headers for upstream LLM service (OpenAI-compatible Bearer token)
|
||||
LLM_HEADERS = {'Authorization': f'Bearer {LLM_API_KEY}'}
|
||||
|
||||
# Model names (backward compat: fall back to OLLAMA_MODEL if LLM_MODEL not set)
|
||||
_raw_model = os.getenv('LLM_MODEL') or os.getenv('OLLAMA_MODEL', 'gpt-oss:20b')
|
||||
LLM_MODEL = _raw_model.strip() if _raw_model else 'gpt-oss:20b'
|
||||
@@ -73,6 +76,7 @@ def _build_chat_payload(
|
||||
thinking: str | None = None,
|
||||
model: str | None = None,
|
||||
use_pro_model: bool = False,
|
||||
prefill: str | None = None,
|
||||
) -> dict:
|
||||
messages = []
|
||||
sys_prompt = _resolve_system_prompt(system_prompt)
|
||||
@@ -80,6 +84,9 @@ def _build_chat_payload(
|
||||
messages.append({'role': 'system', 'content': sys_prompt})
|
||||
messages.append({'role': 'user', 'content': prompt})
|
||||
|
||||
if prefill:
|
||||
messages.append({'role': 'assistant', 'content': prefill})
|
||||
|
||||
payload = {
|
||||
'model': _resolve_model_name(model, use_pro_model=use_pro_model),
|
||||
'messages': messages,
|
||||
@@ -101,6 +108,7 @@ def _build_chat_stream_payload(
|
||||
thinking: str | None = None,
|
||||
model: str | None = None,
|
||||
use_pro_model: bool = False,
|
||||
prefill: str | None = None,
|
||||
) -> dict:
|
||||
messages = []
|
||||
sys_prompt = _resolve_system_prompt(system_prompt)
|
||||
@@ -108,6 +116,9 @@ def _build_chat_stream_payload(
|
||||
messages.append({'role': 'system', 'content': sys_prompt})
|
||||
messages.append({'role': 'user', 'content': prompt})
|
||||
|
||||
if prefill:
|
||||
messages.append({'role': 'assistant', 'content': prefill})
|
||||
|
||||
payload = {
|
||||
'model': _resolve_model_name(model, use_pro_model=use_pro_model),
|
||||
'messages': messages,
|
||||
@@ -145,6 +156,7 @@ async def call_ollama(
|
||||
thinking: str | None = None,
|
||||
model: str | None = None,
|
||||
use_pro_model: bool = False,
|
||||
prefill: str | None = None,
|
||||
) -> dict:
|
||||
"""Call OpenAI-compatible chat completions (non-streaming) and return content/thinking."""
|
||||
start = time.perf_counter()
|
||||
@@ -161,13 +173,13 @@ async def call_ollama(
|
||||
|
||||
payload = _build_chat_payload(
|
||||
prompt=prompt, system_prompt=system_prompt, temperature=temperature,
|
||||
thinking=thinking, model=model, use_pro_model=use_pro_model,
|
||||
thinking=thinking, model=model, use_pro_model=use_pro_model, prefill=prefill,
|
||||
)
|
||||
|
||||
http_timeout = httpx.Timeout(connect=10.0, read=None, write=30.0, pool=30.0)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(base_url=LLM_BASE_URL, timeout=http_timeout) as client:
|
||||
async with httpx.AsyncClient(base_url=LLM_BASE_URL, headers=LLM_HEADERS, timeout=http_timeout) as client:
|
||||
resp = await asyncio.wait_for(
|
||||
client.post('/chat/completions', json=payload), timeout=COMPLETION_TIMEOUT,
|
||||
)
|
||||
@@ -229,6 +241,7 @@ async def stream_ollama(
|
||||
thinking: str | None = None,
|
||||
model: str | None = None,
|
||||
use_pro_model: bool = False,
|
||||
prefill: str | None = None,
|
||||
) -> AsyncIterator[str]:
|
||||
"""Stream text deltas from OpenAI-compatible chat completions."""
|
||||
start = time.perf_counter()
|
||||
@@ -246,13 +259,13 @@ async def stream_ollama(
|
||||
|
||||
payload = _build_chat_stream_payload(
|
||||
prompt=prompt, system_prompt=system_prompt, temperature=temperature,
|
||||
thinking=thinking, model=model, use_pro_model=use_pro_model,
|
||||
thinking=thinking, model=model, use_pro_model=use_pro_model, prefill=prefill,
|
||||
)
|
||||
|
||||
http_timeout = httpx.Timeout(connect=10.0, read=None, write=30.0, pool=30.0)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(base_url=LLM_BASE_URL, timeout=http_timeout) as client:
|
||||
async with httpx.AsyncClient(base_url=LLM_BASE_URL, headers=LLM_HEADERS, timeout=http_timeout) as client:
|
||||
try:
|
||||
async with client.stream('POST', '/chat/completions', json=payload) as response:
|
||||
response.raise_for_status()
|
||||
@@ -352,6 +365,7 @@ async def stream_ollama_events(
|
||||
model: str | None = None,
|
||||
use_pro_model: bool = False,
|
||||
enable_thinking: bool = True,
|
||||
prefill: str | None = None,
|
||||
timeout: float | None = None,
|
||||
) -> AsyncIterator[tuple[Literal['thinking', 'content'], str]]:
|
||||
"""Stream (event_type, payload) tuples from OpenAI-compatible chat completions."""
|
||||
@@ -370,7 +384,7 @@ async def stream_ollama_events(
|
||||
|
||||
payload = _build_chat_stream_payload(
|
||||
prompt=prompt, system_prompt=system_prompt, temperature=temperature,
|
||||
thinking=thinking if enable_thinking else None, model=model, use_pro_model=use_pro_model,
|
||||
thinking=thinking if enable_thinking else None, model=model, use_pro_model=use_pro_model, prefill=prefill,
|
||||
)
|
||||
|
||||
effective_timeout = timeout if timeout is not None else COMPLETION_TIMEOUT
|
||||
@@ -378,7 +392,7 @@ async def stream_ollama_events(
|
||||
sent_thinking = False
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(base_url=LLM_BASE_URL, timeout=http_timeout) as client:
|
||||
async with httpx.AsyncClient(base_url=LLM_BASE_URL, headers=LLM_HEADERS, timeout=http_timeout) as client:
|
||||
try:
|
||||
async with client.stream('POST', '/chat/completions', json=payload) as response:
|
||||
response.raise_for_status()
|
||||
@@ -507,7 +521,7 @@ async def call_vlm_ocr(image_bytes: bytes, language: str = 'auto') -> str:
|
||||
http_timeout = httpx.Timeout(connect=10.0, read=None, write=30.0, pool=30.0)
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(base_url=LLM_BASE_URL, timeout=http_timeout) as client:
|
||||
async with httpx.AsyncClient(base_url=LLM_BASE_URL, headers=LLM_HEADERS, timeout=http_timeout) as client:
|
||||
resp = await asyncio.wait_for(
|
||||
client.post('/chat/completions', json=payload), timeout=OCR_TIMEOUT,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user