release: bump version to 0.70.0
This commit is contained in:
@@ -7,9 +7,14 @@ from time import perf_counter
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy import func, select, update
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.enums import (
|
||||
PlaygroundMessageKind,
|
||||
PlaygroundMessageRole,
|
||||
PlaygroundMessageStatus,
|
||||
)
|
||||
from app.core.logging import get_logger
|
||||
from app.db.session import async_session_factory
|
||||
from app.models.playground_message import PlaygroundMessage
|
||||
@@ -21,7 +26,6 @@ from app.schemas.ai import (
|
||||
PlaygroundMessageRecord,
|
||||
PlaygroundMessageResendRequest,
|
||||
PlaygroundMessageStopRequest,
|
||||
PlaygroundSessionResponse,
|
||||
PlaygroundSessionState,
|
||||
PlaygroundSessionUpsertRequest,
|
||||
PlaygroundThreadResponse,
|
||||
@@ -37,6 +41,13 @@ STREAM_CHUNK_SIZE = 24
|
||||
STREAM_INTERVAL_SECONDS = 0.08
|
||||
THINKING_PREVIEW_SECONDS = 2.6
|
||||
ORPHANED_RUN_MESSAGE = "后台生成任务已中断,请点击上一条用户消息的重试按钮重新生成。"
|
||||
ACTIVE_MESSAGE_STATUSES = frozenset(
|
||||
{
|
||||
PlaygroundMessageStatus.PENDING.value,
|
||||
PlaygroundMessageStatus.THINKING.value,
|
||||
PlaygroundMessageStatus.ANSWERING.value,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class _ActiveRun:
|
||||
@@ -93,7 +104,11 @@ async def _require_visible_message(
|
||||
result = await db.execute(select(PlaygroundMessage).where(*conditions))
|
||||
message = result.scalar_one_or_none()
|
||||
if message is None:
|
||||
detail = "User message not found" if role == "user" else "Playground message not found"
|
||||
detail = (
|
||||
"User message not found"
|
||||
if role == PlaygroundMessageRole.USER.value
|
||||
else "Playground message not found"
|
||||
)
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=detail)
|
||||
return message
|
||||
|
||||
@@ -108,7 +123,7 @@ def _message_to_record(message: PlaygroundMessage, parent_public_id: str | None
|
||||
content=message.content or "",
|
||||
thinking_content=message.thinking_content or "",
|
||||
meta=list(message.meta or []),
|
||||
markdown=message.role != "system",
|
||||
markdown=message.role != PlaygroundMessageRole.SYSTEM.value,
|
||||
provider=message.provider,
|
||||
model=message.model,
|
||||
request_id=message.request_id,
|
||||
@@ -197,11 +212,11 @@ async def _reconcile_orphaned_active_messages(
|
||||
) -> list[PlaygroundMessage]:
|
||||
changed = False
|
||||
for item in messages:
|
||||
if item.status not in {"pending", "thinking", "answering"}:
|
||||
if item.status not in ACTIVE_MESSAGE_STATUSES:
|
||||
continue
|
||||
if item.public_id in _ACTIVE_RUNS:
|
||||
continue
|
||||
item.status = "error"
|
||||
item.status = PlaygroundMessageStatus.ERROR.value
|
||||
item.content = item.content or ORPHANED_RUN_MESSAGE
|
||||
orphan_meta = "错误: 后台任务已中断"
|
||||
if orphan_meta not in (item.meta or []):
|
||||
@@ -330,9 +345,9 @@ async def create_turn(
|
||||
public_id=uuid4().hex,
|
||||
session_id=session.id,
|
||||
user_id=user_id,
|
||||
role="user",
|
||||
kind="message",
|
||||
status="done",
|
||||
role=PlaygroundMessageRole.USER.value,
|
||||
kind=PlaygroundMessageKind.MESSAGE.value,
|
||||
status=PlaygroundMessageStatus.DONE.value,
|
||||
title=payload.selected_preset_key,
|
||||
content=payload.input,
|
||||
meta=[payload.title],
|
||||
@@ -343,9 +358,9 @@ async def create_turn(
|
||||
session_id=session.id,
|
||||
user_id=user_id,
|
||||
parent_message_id=None,
|
||||
role="assistant",
|
||||
kind="thinking",
|
||||
status="pending",
|
||||
role=PlaygroundMessageRole.ASSISTANT.value,
|
||||
kind=PlaygroundMessageKind.THINKING.value,
|
||||
status=PlaygroundMessageStatus.PENDING.value,
|
||||
title="AI 回应",
|
||||
content="",
|
||||
thinking_content="",
|
||||
@@ -397,9 +412,9 @@ async def _create_assistant_retry_turn(
|
||||
session_id=session.id,
|
||||
user_id=user_id,
|
||||
parent_message_id=user_message.id,
|
||||
role="assistant",
|
||||
kind="thinking",
|
||||
status="pending",
|
||||
role=PlaygroundMessageRole.ASSISTANT.value,
|
||||
kind=PlaygroundMessageKind.THINKING.value,
|
||||
status=PlaygroundMessageStatus.PENDING.value,
|
||||
title="AI 回应",
|
||||
content="",
|
||||
thinking_content="",
|
||||
@@ -439,7 +454,7 @@ async def stop_message(
|
||||
session = await _require_session(db, user_id=user_id, session_key=payload.session_key)
|
||||
message = await _require_visible_message(db, user_id=user_id, public_id=payload.message_id)
|
||||
|
||||
if message.status not in {"pending", "thinking", "answering"}:
|
||||
if message.status not in ACTIVE_MESSAGE_STATUSES:
|
||||
return await _build_action_response(db, session=session)
|
||||
|
||||
active_run = _ACTIVE_RUNS.get(message.public_id)
|
||||
@@ -447,7 +462,7 @@ async def stop_message(
|
||||
active_run.stop_requested.set()
|
||||
active_run.task.cancel()
|
||||
|
||||
message.status = "stopped"
|
||||
message.status = PlaygroundMessageStatus.STOPPED.value
|
||||
if "已手动停止生成" not in (message.meta or []):
|
||||
message.meta = [*(message.meta or []), "已手动停止生成"]
|
||||
await db.flush()
|
||||
@@ -469,7 +484,7 @@ async def resend_turn(
|
||||
db,
|
||||
user_id=user_id,
|
||||
public_id=payload.user_message_id,
|
||||
role="user",
|
||||
role=PlaygroundMessageRole.USER.value,
|
||||
)
|
||||
|
||||
later_messages = await db.execute(
|
||||
@@ -481,7 +496,7 @@ async def resend_turn(
|
||||
)
|
||||
for item in later_messages.scalars().all():
|
||||
item.is_visible = False
|
||||
if item.status in {"pending", "thinking", "answering"}:
|
||||
if item.status in ACTIVE_MESSAGE_STATUSES:
|
||||
active_run = _ACTIVE_RUNS.get(item.public_id)
|
||||
if active_run is not None:
|
||||
active_run.stop_requested.set()
|
||||
@@ -520,7 +535,7 @@ async def edit_user_message(
|
||||
db,
|
||||
user_id=user_id,
|
||||
public_id=payload.user_message_id,
|
||||
role="user",
|
||||
role=PlaygroundMessageRole.USER.value,
|
||||
)
|
||||
|
||||
user_message.content = payload.content.strip()
|
||||
@@ -566,12 +581,12 @@ def _build_conversation_history(messages: Sequence[PlaygroundMessage], current_u
|
||||
for item in messages:
|
||||
if item.id >= current_user_message_id:
|
||||
break
|
||||
if item.role == "system":
|
||||
if item.role == PlaygroundMessageRole.SYSTEM.value:
|
||||
continue
|
||||
history.append(
|
||||
{
|
||||
"role": item.role,
|
||||
"kind": item.kind or "message",
|
||||
"kind": item.kind or PlaygroundMessageKind.MESSAGE.value,
|
||||
"title": item.title,
|
||||
"content": item.content or "",
|
||||
}
|
||||
@@ -668,7 +683,11 @@ async def _run_assistant_message(
|
||||
assistant_message = await _mark_message_state(
|
||||
db,
|
||||
message_id=assistant_message_id,
|
||||
status="thinking" if analysis.thinking_blocks else "answering",
|
||||
status=(
|
||||
PlaygroundMessageStatus.THINKING.value
|
||||
if analysis.thinking_blocks
|
||||
else PlaygroundMessageStatus.ANSWERING.value
|
||||
),
|
||||
title=f"{analysis.provider} / {analysis.model}",
|
||||
provider=analysis.provider,
|
||||
model=analysis.model,
|
||||
@@ -706,7 +725,7 @@ async def _run_assistant_message(
|
||||
await _mark_message_state(
|
||||
db,
|
||||
message_id=assistant_message_id,
|
||||
status="answering",
|
||||
status=PlaygroundMessageStatus.ANSWERING.value,
|
||||
content=content[:cursor],
|
||||
)
|
||||
await db.commit()
|
||||
@@ -717,7 +736,7 @@ async def _run_assistant_message(
|
||||
assistant_message = await _mark_message_state(
|
||||
db,
|
||||
message_id=assistant_message_id,
|
||||
status="done",
|
||||
status=PlaygroundMessageStatus.DONE.value,
|
||||
content=content,
|
||||
meta=[
|
||||
f"Request ID: {request_id}",
|
||||
@@ -762,8 +781,8 @@ async def _run_assistant_message(
|
||||
async with async_session_factory() as db:
|
||||
result = await db.execute(select(PlaygroundMessage).where(PlaygroundMessage.id == assistant_message_id))
|
||||
message = result.scalar_one_or_none()
|
||||
if message is not None and message.status in {"pending", "thinking", "answering"}:
|
||||
message.status = "stopped"
|
||||
if message is not None and message.status in ACTIVE_MESSAGE_STATUSES:
|
||||
message.status = PlaygroundMessageStatus.STOPPED.value
|
||||
if "已手动停止生成" not in (message.meta or []):
|
||||
message.meta = [*(message.meta or []), "已手动停止生成"]
|
||||
await db.flush()
|
||||
@@ -795,7 +814,7 @@ async def _run_assistant_message(
|
||||
result = await db.execute(select(PlaygroundMessage).where(PlaygroundMessage.id == assistant_message_id))
|
||||
message = result.scalar_one_or_none()
|
||||
if message is not None:
|
||||
message.status = "error"
|
||||
message.status = PlaygroundMessageStatus.ERROR.value
|
||||
message.content = message.content or f"分析失败:{error_message}"
|
||||
message.meta = [
|
||||
*(message.meta or []),
|
||||
|
||||
Reference in New Issue
Block a user