EOL: Final release

This commit is contained in:
zin
2026-06-28 18:51:32 +00:00
parent 934a4cbff4
commit 14c2bc2da7
3 changed files with 34 additions and 24 deletions
+24 -14
View File
@@ -2,16 +2,16 @@ import os
import json
import re
import requests
from typing import List, Dict
class LLMAcousticBridge:
def __init__(self, model_name="dolphin-llama3:8b"):
def __init__(self, model_name: str = "dolphin-llama3:8b"):
self.model_name = model_name
base_url = os.getenv("OLLAMA_API_URL", "http://emom_ollama:11434")
self.api_url = f"{base_url}/api/generate"
def get_acoustic_profile(self, valence, arousal, semantics):
def get_acoustic_profile(self, valence: float, arousal: float, semantics: List[str]) -> Dict[str, float]:
context_str = ", ".join(semantics) if semantics else "abstract scene"
prompt = f"""
Analyze the visual context and emotions to determine the ideal background music properties.
Emotions: Valence {valence:.1f}/9.0 (Positivity), Arousal {arousal:.1f}/9.0 (Energy).
@@ -34,32 +34,42 @@ class LLMAcousticBridge:
"model": self.model_name,
"prompt": prompt,
"stream": False,
"format": "json" # Принудительный JSON-режим Ollama
"format": "json",
"options": {
"temperature": 0.7,
"top_p": 0.9
}
}
print(f"Запрос акустического профиля к Ollama...")
response = requests.post(self.api_url, json=payload, timeout=120)
response.raise_for_status()
if response.status_code == 200:
data = response.json()
response_text = data.get("response", "")
profile = {}
try:
# 1. Попытка прямой десериализации
profile = json.loads(response_text)
return profile
except json.JSONDecodeError:
# 2. Аварийное извлечение JSON из текста с помощью регулярного выражения
match = re.search(r'\{.*\}', response_text, re.DOTALL)
if match:
return json.loads(match.group(0))
print(f"Ошибка парсинга LLM ответа: {response_text}")
return {}
profile = json.loads(match.group(0))
else:
print(f"Ollama вернула ошибку HTTP: {response.status_code}")
print(f"[ERROR] Ошибка парсинга LLM ответа: {response_text}")
return {}
# 3. Жесткая валидация ключей (чтобы matcher.py не упал на демо)
required_keys = ['energy', 'flux', 'centroid', 'pitch', 'hnr', 'zcr']
if profile and all(k in profile for k in required_keys):
return profile
else:
print(f"[WARN] LLM вернула неполный JSON, активирован fallback: {profile}")
return {}
except requests.exceptions.RequestException as e:
print(f"[ERROR] Ошибка соединения с Ollama: {str(e)}")
return {}
except Exception as e:
print(f"Ошибка соединения с Ollama: {str(e)}")
print(f"[ERROR] Внутренняя ошибка семантического моста: {str(e)}")
return {}
+1 -1
View File
@@ -78,6 +78,6 @@ class MusicMatcher:
self.norm_db['acoustic_distance'] = acoustic_penalty / len(self.acoustic_features)
# Вычисление интегральной метрики соответствия (мультимодальный скоринг)
self.norm_db['final_score'] = self.norm_db['emo_distance'] + (self.norm_db['acoustic_distance'] * 4.0)
self.norm_db['final_score'] = self.norm_db['emo_distance'] + (self.norm_db['acoustic_distance'] * 2.0)
return self.norm_db.sort_values(by='final_score').head(top_k)
+2 -2
View File
@@ -264,9 +264,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python (thesis)",
"display_name": "Python (my-python-project)",
"language": "python",
"name": "thesis"
"name": "my-python-project"
},
"language_info": {
"codemirror_mode": {