Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,425 changes: 436 additions & 989 deletions front/common.js

Large diffs are not rendered by default.

1,049 changes: 364 additions & 685 deletions front/control_panel.html

Large diffs are not rendered by default.

1,064 changes: 373 additions & 691 deletions front/control_panel_mobile.html

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions src/converter/fake_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def safe_get_nested(obj: Any, *keys: str, default: Any = None) -> Any:
return obj

def parse_response_for_fake_stream(response_data: Dict[str, Any]) -> tuple:
"""从完整响应中提取内容和推理内容(用于假流式)
"""从完整响应中提取内容和推理内容(用于fake-stream)

Args:
response_data: Gemini API 响应数据
Expand Down Expand Up @@ -55,7 +55,7 @@ def parse_response_for_fake_stream(response_data: Dict[str, Any]) -> tuple:

def extract_fake_stream_content(response: Any) -> Tuple[str, str, Dict[str, int]]:
"""
从 Gemini 非流式响应中提取内容,用于假流式处理
从 Gemini 非流式响应中提取内容,用于fake-stream处理

Args:
response: Gemini API 响应对象
Expand Down Expand Up @@ -144,7 +144,7 @@ def _build_candidate(parts: List[Dict[str, Any]], finish_reason: str = "STOP") -

def create_openai_heartbeat_chunk() -> Dict[str, Any]:
"""
创建 OpenAI 格式的心跳块(用于假流式
创建 OpenAI 格式的心跳块(用于fake-stream

Returns:
心跳响应块字典
Expand All @@ -160,7 +160,7 @@ def create_openai_heartbeat_chunk() -> Dict[str, Any]:
}

def build_gemini_fake_stream_chunks(content: str, reasoning_content: str, finish_reason: str, images: List[Dict[str, Any]] = None, chunk_size: int = 50) -> List[Dict[str, Any]]:
"""构建假流式响应的数据块
"""构建fake-stream响应的数据块

Args:
content: 主要内容
Expand Down Expand Up @@ -240,7 +240,7 @@ def create_gemini_heartbeat_chunk() -> Dict[str, Any]:


def build_openai_fake_stream_chunks(content: str, reasoning_content: str, finish_reason: str, model: str, images: List[Dict[str, Any]] = None, chunk_size: int = 50) -> List[Dict[str, Any]]:
"""构建 OpenAI 格式的假流式响应数据块
"""构建 OpenAI 格式的fake-stream响应数据块

Args:
content: 主要内容
Expand Down Expand Up @@ -343,7 +343,7 @@ def build_openai_fake_stream_chunks(content: str, reasoning_content: str, finish

def create_anthropic_heartbeat_chunk() -> Dict[str, Any]:
"""
创建 Anthropic 格式的心跳块(用于假流式
创建 Anthropic 格式的心跳块(用于fake-stream

Returns:
心跳响应块字典
Expand All @@ -354,7 +354,7 @@ def create_anthropic_heartbeat_chunk() -> Dict[str, Any]:


def build_anthropic_fake_stream_chunks(content: str, reasoning_content: str, finish_reason: str, model: str, images: List[Dict[str, Any]] = None, chunk_size: int = 50) -> List[Dict[str, Any]]:
"""构建 Anthropic 格式的假流式响应数据块
"""构建 Anthropic 格式的fake-stream响应数据块

Args:
content: 主要内容
Expand Down
18 changes: 9 additions & 9 deletions src/router/antigravity/anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
authenticate_bearer,
)

# 本地模块 - 转换器(假流式需要
# 本地模块 - 转换器(fake-stream需要
from src.converter.fake_stream import (
parse_response_for_fake_stream,
build_anthropic_fake_stream_chunks,
Expand Down Expand Up @@ -152,7 +152,7 @@ async def messages(

# ========== 流式请求 ==========

# ========== 假流式生成器 ==========
# ========== fake-stream生成器 ==========
async def fake_stream_generator():
from src.api.antigravity import non_stream_request

Expand Down Expand Up @@ -218,7 +218,7 @@ async def fake_stream_generator():

yield "data: [DONE]\n\n".encode()

# ========== 流式抗截断生成器 ==========
# ========== anti-truncate生成器 ==========
async def anti_truncation_generator():
from src.converter.anti_truncation import AntiTruncationStreamProcessor
from src.api.antigravity import stream_request
Expand Down Expand Up @@ -335,7 +335,7 @@ async def gemini_chunk_wrapper():
if use_fake_streaming:
return await build_streaming_response_or_error(fake_stream_generator())
elif use_anti_truncation:
log.info("启用流式抗截断功能")
log.info("启用anti-truncate功能")
return await build_streaming_response_or_error(anti_truncation_generator())
else:
return await build_streaming_response_or_error(normal_stream_generator())
Expand Down Expand Up @@ -537,18 +537,18 @@ def test_stream_request():
print(f"\n总共收到 {chunk_count} 个chunk")

def test_fake_stream_request():
"""测试假流式请求"""
"""测试fake-stream请求"""
print("\n" + "=" * 80)
print("【测试3】假流式请求 (POST /antigravity/v1/messages with 假流式 prefix)")
print("【测试3】fake-stream请求 (POST /antigravity/v1/messages with fake-stream prefix)")
print("=" * 80)

fake_stream_request_body = test_request_body.copy()
fake_stream_request_body["model"] = "假流式/gemini-2.5-flash"
fake_stream_request_body["model"] = "fake-stream/gemini-2.5-flash"
fake_stream_request_body["stream"] = True

print(f"请求体: {json.dumps(fake_stream_request_body, indent=2, ensure_ascii=False)}\n")

print("假流式响应数据 (每个chunk):")
print("fake-stream响应数据 (每个chunk):")
print("-" * 80)

with client.stream(
Expand Down Expand Up @@ -601,7 +601,7 @@ def test_fake_stream_request():
# 测试流式请求
test_stream_request()

# 测试假流式请求
# 测试fake-stream请求
test_fake_stream_request()

print("\n" + "=" * 80)
Expand Down
31 changes: 17 additions & 14 deletions src/router/antigravity/gemini.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
is_fake_streaming_model
)

# 本地模块 - 转换器(假流式需要
# 本地模块 - 转换器(fake-stream需要
from src.converter.fake_stream import (
parse_response_for_fake_stream,
build_gemini_fake_stream_chunks,
Expand Down Expand Up @@ -62,6 +62,7 @@

@router.post("/antigravity/v1beta/models/{model:path}:generateContent")
@router.post("/antigravity/v1/models/{model:path}:generateContent")
@router.post("/antigravity/models/{model:path}:generateContent")
async def generate_content(
gemini_request: "GeminiRequest",
model: str = Path(..., description="Model name"),
Expand Down Expand Up @@ -128,6 +129,7 @@ async def generate_content(

@router.post("/antigravity/v1beta/models/{model:path}:streamGenerateContent")
@router.post("/antigravity/v1/models/{model:path}:streamGenerateContent")
@router.post("/antigravity/models/{model:path}:streamGenerateContent")
async def stream_generate_content(
gemini_request: GeminiRequest,
model: str = Path(..., description="Model name"),
Expand All @@ -154,7 +156,7 @@ async def stream_generate_content(
# 更新模型名为真实模型名
normalized_dict["model"] = real_model

# ========== 假流式生成器 ==========
# ========== fake-stream生成器 ==========
async def fake_stream_generator():
from src.converter.antigravity_fix import normalize_antigravity_request
from src.api.antigravity import non_stream_request
Expand Down Expand Up @@ -215,7 +217,7 @@ async def fake_stream_generator():

yield "data: [DONE]\n\n".encode()

# ========== 流式抗截断生成器 ==========
# ========== anti-truncate生成器 ==========
async def anti_truncation_generator():
from src.converter.antigravity_fix import normalize_antigravity_request
from src.converter.anti_truncation import AntiTruncationStreamProcessor
Expand Down Expand Up @@ -382,13 +384,14 @@ async def normal_stream_generator():
if use_fake_streaming:
return await build_streaming_response_or_error(fake_stream_generator())
elif use_anti_truncation:
log.info("启用流式抗截断功能")
log.info("启用anti-truncate功能")
return await build_streaming_response_or_error(anti_truncation_generator())
else:
return await build_streaming_response_or_error(normal_stream_generator())

@router.post("/antigravity/v1beta/models/{model:path}:countTokens")
@router.post("/antigravity/v1/models/{model:path}:countTokens")
@router.post("/antigravity/models/{model:path}:countTokens")
async def count_tokens(
request: Request = None,
api_key: str = Depends(authenticate_gemini_flexible),
Expand Down Expand Up @@ -554,18 +557,18 @@ def test_stream_request():
print(f"\n总共收到 {chunk_count} 个chunk")

def test_fake_stream_request():
"""测试假流式请求"""
"""测试fake-stream请求"""
print("\n" + "=" * 80)
print("【测试4】假流式请求 (POST /antigravity/v1/models/假流式/gemini-2.5-flash:streamGenerateContent)")
print("【测试4】fake-stream请求 (POST /antigravity/v1/models/fake-stream/gemini-2.5-flash:streamGenerateContent)")
print("=" * 80)
print(f"请求体: {json.dumps(test_request_body, indent=2, ensure_ascii=False)}\n")

print("假流式响应数据 (每个chunk):")
print("fake-stream响应数据 (每个chunk):")
print("-" * 80)

with client.stream(
"POST",
"/antigravity/v1/models/假流式/gemini-2.5-flash:streamGenerateContent",
"/antigravity/v1/models/fake-stream/gemini-2.5-flash:streamGenerateContent",
json=test_request_body,
params={"key": test_api_key}
) as response:
Expand Down Expand Up @@ -608,18 +611,18 @@ def test_fake_stream_request():
print(f"\n总共收到 {chunk_count} 个HTTP chunk")

def test_anti_truncation_stream_request():
"""测试流式抗截断请求"""
"""测试anti-truncate请求"""
print("\n" + "=" * 80)
print("【测试5】流式抗截断请求 (POST /antigravity/v1/models/流式抗截断/gemini-2.5-flash:streamGenerateContent)")
print("【测试5】anti-truncate请求 (POST /antigravity/v1/models/anti-truncate/gemini-2.5-flash:streamGenerateContent)")
print("=" * 80)
print(f"请求体: {json.dumps(test_request_body, indent=2, ensure_ascii=False)}\n")

print("流式抗截断响应数据 (每个chunk):")
print("anti-truncate响应数据 (每个chunk):")
print("-" * 80)

with client.stream(
"POST",
"/antigravity/v1/models/流式抗截断/gemini-2.5-flash:streamGenerateContent",
"/antigravity/v1/models/anti-truncate/gemini-2.5-flash:streamGenerateContent",
json=test_request_body,
params={"key": test_api_key}
) as response:
Expand Down Expand Up @@ -669,10 +672,10 @@ def test_anti_truncation_stream_request():
# 测试流式请求
test_stream_request()

# 测试假流式请求
# 测试fake-stream请求
test_fake_stream_request()

# 测试流式抗截断请求
# 测试anti-truncate请求
test_anti_truncation_stream_request()

print("\n" + "=" * 80)
Expand Down
14 changes: 8 additions & 6 deletions src/router/antigravity/model_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ async def get_antigravity_models_with_features():
# 基础模型
models.append(base_model)

# 假流式模型 (前缀格式)
models.append(f"假流式/{base_model}")
# fake-stream模型 (前缀格式)
models.append(f"fake-stream/{base_model}")

# 流式抗截断模型 (仅在流式传输时有效,前缀格式)
models.append(f"流式抗截断/{base_model}")
# anti-truncate模型 (仅在流式传输时有效,前缀格式)
models.append(f"anti-truncate/{base_model}")

log.info(f"[ANTIGRAVITY MODEL LIST] 生成了 {len(models)} 个模型(包含功能前缀)")
return models
Expand All @@ -73,12 +73,13 @@ async def get_antigravity_models_with_features():
# ==================== API 路由 ====================

@router.get("/antigravity/v1beta/models")
@router.get("/antigravity/models")
async def list_gemini_models(token: str = Depends(authenticate_flexible)):
"""
返回 Gemini 格式的模型列表

从 src.api.antigravity.fetch_available_models 动态获取模型列表
并添加假流式和流式抗截断前缀
并添加fake-stream和anti-truncate前缀
"""
models = await get_antigravity_models_with_features()
log.info("[ANTIGRAVITY MODEL LIST] 返回 Gemini 格式")
Expand All @@ -89,12 +90,13 @@ async def list_gemini_models(token: str = Depends(authenticate_flexible)):


@router.get("/antigravity/v1/models")
@router.get("/antigravity/v1/models/openai")
async def list_openai_models(token: str = Depends(authenticate_flexible)):
"""
返回 OpenAI 格式的模型列表

从 src.api.antigravity.fetch_available_models 动态获取模型列表
并添加假流式和流式抗截断前缀
并添加fake-stream和anti-truncate前缀
"""
models = await get_antigravity_models_with_features()
log.info("[ANTIGRAVITY MODEL LIST] 返回 OpenAI 格式")
Expand Down
18 changes: 9 additions & 9 deletions src/router/antigravity/openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
authenticate_bearer,
)

# 本地模块 - 转换器(假流式需要
# 本地模块 - 转换器(fake-stream需要
from src.converter.fake_stream import (
parse_response_for_fake_stream,
build_openai_fake_stream_chunks,
Expand Down Expand Up @@ -149,7 +149,7 @@ async def chat_completions(

# ========== 流式请求 ==========

# ========== 假流式生成器 ==========
# ========== fake-stream生成器 ==========
async def fake_stream_generator():
from src.api.antigravity import non_stream_request

Expand Down Expand Up @@ -219,7 +219,7 @@ async def fake_stream_generator():

yield "data: [DONE]\n\n".encode()

# ========== 流式抗截断生成器 ==========
# ========== anti-truncate生成器 ==========
async def anti_truncation_generator():
from src.converter.anti_truncation import AntiTruncationStreamProcessor
from src.api.antigravity import stream_request
Expand Down Expand Up @@ -381,7 +381,7 @@ async def normal_stream_generator():
if use_fake_streaming:
return await build_streaming_response_or_error(fake_stream_generator())
elif use_anti_truncation:
log.info("启用流式抗截断功能")
log.info("启用anti-truncate功能")
return await build_streaming_response_or_error(anti_truncation_generator())
else:
return await build_streaming_response_or_error(normal_stream_generator())
Expand Down Expand Up @@ -511,18 +511,18 @@ def test_stream_request():
print(f"\n总共收到 {chunk_count} 个chunk")

def test_fake_stream_request():
"""测试假流式请求"""
"""测试fake-stream请求"""
print("\n" + "=" * 80)
print("【测试3】假流式请求 (POST /antigravity/v1/chat/completions with 假流式 prefix)")
print("【测试3】fake-stream请求 (POST /antigravity/v1/chat/completions with fake-stream prefix)")
print("=" * 80)

fake_stream_request_body = test_request_body.copy()
fake_stream_request_body["model"] = "假流式/gemini-2.5-flash"
fake_stream_request_body["model"] = "fake-stream/gemini-2.5-flash"
fake_stream_request_body["stream"] = True

print(f"请求体: {json.dumps(fake_stream_request_body, indent=2, ensure_ascii=False)}\n")

print("假流式响应数据 (每个chunk):")
print("fake-stream响应数据 (每个chunk):")
print("-" * 80)

with client.stream(
Expand Down Expand Up @@ -577,7 +577,7 @@ def test_fake_stream_request():
# 测试流式请求
test_stream_request()

# 测试假流式请求
# 测试fake-stream请求
test_fake_stream_request()

print("\n" + "=" * 80)
Expand Down
Loading