chenpei d0dc94e36d feat: 将弹幕功能替换为AI聊天助手
新功能:
- 创建AI聊天助手组件(AIChatWidget)
- 支持文字+图片多模态对话
- 集成Gemini AI API
- 支持图片编辑和内容生成
- 实时对话历史管理
- 优雅的UI设计,支持黑夜模式

技术实现:
- 后端API代理Gemini API(/api/ai-chat)
- 支持最多5张图片上传
- 流式响应处理
- 对话历史管理
- Base64图片处理

配置:
- 在.env中添加Gemini API配置
- GEMINI_API_KEY
- GEMINI_API_BASE_URL
- GEMINI_MODEL

替换原弹幕功能,提供更强大的AI助手体验!
2025-10-27 17:45:37 +08:00

79 lines
3.4 KiB
Python
Executable File

# coding=utf-8
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from enum import Enum
from typing import List
from volcengine.tls.const import *
from volcengine.tls.data import ConsumeShard
from volcengine.tls.tls_exception import TLSException
def check_empty_string(value: str, field: str):
if value is None or len(value) == 0:
raise TLSException(error_code="InvalidArgument", error_message="{} should not be empty.".format(field))
def check_int_value_range(value: int, lower: int, upper: int, field: str):
if value < lower or value > upper:
raise TLSException(error_code="InvalidArgument",
error_message="{} value should between {} and {}.".format(field, lower, upper))
class ConsumerConfig:
def __init__(self, project_id: str, consumer_group_name: str, topic_id_list: List[str], consumer_name: str,
consume_from: str = "begin", heartbeat_interval_in_second: int = 20,
data_fetch_interval_in_millisecond: int = 200, flush_checkpoint_interval_in_second: int = 5,
max_fetch_log_group_count: int = 100, ordered_consume: bool = False, stop_timeout: int = 15,
compression: str = LZ4):
self.project_id = project_id
self.consumer_group_name = consumer_group_name
self.topic_id_list = topic_id_list
self.consumer_name = consumer_name
self.consume_from = consume_from
self.heartbeat_interval_in_second = heartbeat_interval_in_second
self.data_fetch_interval_in_millisecond = data_fetch_interval_in_millisecond
self.flush_checkpoint_interval_in_second = flush_checkpoint_interval_in_second
self.max_fetch_log_group_count = max_fetch_log_group_count
self.ordered_consume = ordered_consume
self.stop_timeout = stop_timeout
self.compression = compression
def validate(self):
check_empty_string(self.project_id, PROJECT_ID_UPPERCASE)
check_empty_string(self.consumer_group_name, CONSUMER_GROUP_NAME)
check_empty_string(self.consumer_name, CONSUMER_NAME)
if self.topic_id_list is None or len(self.topic_id_list) == 0:
raise TLSException(error_code="InvalidArgument", error_message="TopicIDList should not be empty.")
for topic_id in self.topic_id_list:
check_empty_string(topic_id, TOPIC_ID_UPPERCASE)
check_empty_string(self.consumer_name, CONSUME_FROM)
check_int_value_range(self.heartbeat_interval_in_second, 1, 300, HEARTBEAT_INTERVAL_IN_SECOND)
check_int_value_range(self.data_fetch_interval_in_millisecond, 1, 300000, DATA_FETCH_INTERVAL_IN_MILLISECOND)
check_int_value_range(self.flush_checkpoint_interval_in_second, 1, 300, FLUSH_CHECKPOINT_INTERVAL_IN_SECOND)
check_int_value_range(self.max_fetch_log_group_count, 1, 1000, MAX_FETCH_LOG_GROUP_COUNT)
check_int_value_range(self.stop_timeout, 1, 300, STOP_TIMEOUT)
class CheckpointInfo:
def __init__(self, checkpoint: str, shard_info: ConsumeShard):
self.checkpoint = checkpoint
self.shard_info = shard_info
class ConsumerStatus(Enum):
PENDING = "pending"
INITIALIZING = "Initializing"
READY_TO_FETCH = "ready_to_fetch"
FETCHING = "fetching"
READY_TO_CONSUME = "ready_to_consume"
CONSUMING = "consuming"
BACKOFF = "backoff"
WAIT_FOR_RESTART = "wait_for_restart"