Improve AI module comments and README
This commit is contained in:
@@ -69,6 +69,9 @@ _PROVIDER_ALIASES = {
|
||||
"zai": "zai",
|
||||
}
|
||||
|
||||
# В реальном .env у пользователя должен быть активен только один AI-ключ.
|
||||
# Поэтому настройки храним в одном словаре, а ниже отдельно проверяем конфликт
|
||||
# конфигурации, чтобы ассистент не делал "лучшее предположение" молча.
|
||||
_PROVIDER_SETTINGS = {
|
||||
"perplexity": {
|
||||
"provider": "perplexity",
|
||||
@@ -137,6 +140,8 @@ def _normalize_provider_name(provider_name: str) -> str:
|
||||
|
||||
|
||||
def _get_provider_settings():
|
||||
# Сначала ищем реально активные ключи. Это главный источник истины:
|
||||
# если ключ один, используем именно его, даже если AI_PROVIDER указан иначе.
|
||||
configured = [
|
||||
cfg
|
||||
for cfg in _PROVIDER_SETTINGS.values()
|
||||
@@ -233,11 +238,13 @@ def _split_system_messages(messages):
|
||||
role = "user"
|
||||
chat_messages.append({"role": role, "content": content})
|
||||
|
||||
# Anthropic хранит системную инструкцию отдельно от обычной истории чата.
|
||||
return "\n\n".join(system_parts), chat_messages
|
||||
|
||||
|
||||
def _build_payload(cfg, messages, max_tokens, temperature, stream):
|
||||
if cfg["protocol"] == "anthropic":
|
||||
# У Claude схема чуть отличается: system не живет внутри messages.
|
||||
system_prompt, chat_messages = _split_system_messages(messages)
|
||||
payload = {
|
||||
"model": cfg["model"],
|
||||
@@ -303,6 +310,7 @@ def _iter_openai_compatible_stream(response):
|
||||
yield content
|
||||
continue
|
||||
|
||||
# Некоторые OpenAI-compatible API присылают контент кусками-объектами.
|
||||
if isinstance(content, list):
|
||||
for item in content:
|
||||
if isinstance(item, dict):
|
||||
@@ -326,6 +334,7 @@ def _iter_anthropic_stream(response):
|
||||
continue
|
||||
|
||||
chunk_type = data_json.get("type")
|
||||
# Claude отдает поток событиями разных типов, нас интересует только текст.
|
||||
if chunk_type == "content_block_start":
|
||||
content_block = data_json.get("content_block") or {}
|
||||
text = content_block.get("text")
|
||||
@@ -374,6 +383,7 @@ def _send_request(messages, max_tokens, temperature, error_text):
|
||||
return config_error
|
||||
|
||||
try:
|
||||
# Обычный запрос нужен для перевода и мест, где стриминг не требуется.
|
||||
response = _HTTP.post(
|
||||
cfg["api_url"],
|
||||
headers=_build_headers(cfg),
|
||||
@@ -454,6 +464,7 @@ def ask_ai_stream(messages_history: list):
|
||||
messages = [{"role": "system", "content": SYSTEM_PROMPT}] + list(messages_history)
|
||||
|
||||
try:
|
||||
# В голосовом режиме удобнее говорить частями, как только они приходят от API.
|
||||
response = _HTTP.post(
|
||||
cfg["api_url"],
|
||||
headers=_build_headers(cfg),
|
||||
|
||||
Reference in New Issue
Block a user