style(dashboard): uv lint
This commit is contained in:
parent
7c866e7b2b
commit
cfc9b903de
@ -19,7 +19,7 @@
|
|||||||
- [ ] 知识图谱的上传和可视化,支持属性,标签的展示
|
- [ ] 知识图谱的上传和可视化,支持属性,标签的展示
|
||||||
- [ ] 集成智能体评估,首先使用命令行来实现,然后考虑放在 UI 里面展示
|
- [ ] 集成智能体评估,首先使用命令行来实现,然后考虑放在 UI 里面展示
|
||||||
- [ ] 开发与生产环境隔离
|
- [ ] 开发与生产环境隔离
|
||||||
- [ ] 添加统计信息
|
- [x] 添加统计信息
|
||||||
- [ ] 支持 MinerU 的解析方法
|
- [ ] 支持 MinerU 的解析方法
|
||||||
- [ ] Options 中添加网络搜索和绘制图片的选项,分别是用来调用工具
|
- [ ] Options 中添加网络搜索和绘制图片的选项,分别是用来调用工具
|
||||||
|
|
||||||
|
|||||||
@ -272,9 +272,7 @@ async def update_profile(
|
|||||||
|
|
||||||
# 检查用户名是否已被其他用户使用
|
# 检查用户名是否已被其他用户使用
|
||||||
existing_user = (
|
existing_user = (
|
||||||
db.query(User)
|
db.query(User).filter(User.username == profile_data.username, User.id != current_user.id).first()
|
||||||
.filter(User.username == profile_data.username, User.id != current_user.id)
|
|
||||||
.first()
|
|
||||||
)
|
)
|
||||||
if existing_user:
|
if existing_user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|||||||
@ -183,11 +183,11 @@ async def chat_agent(
|
|||||||
|
|
||||||
# 格式清洗
|
# 格式清洗
|
||||||
if finish_reason := msg_dict.get("response_metadata", {}).get("finish_reason"):
|
if finish_reason := msg_dict.get("response_metadata", {}).get("finish_reason"):
|
||||||
if "tool_call" in finish_reason and len(finish_reason) > len("tool_call") :
|
if "tool_call" in finish_reason and len(finish_reason) > len("tool_call"):
|
||||||
model_name = msg_dict.get("response_metadata", {}).get("model_name", "")
|
model_name = msg_dict.get("response_metadata", {}).get("model_name", "")
|
||||||
repeat_count = len(finish_reason) // len("tool_call")
|
repeat_count = len(finish_reason) // len("tool_call")
|
||||||
msg_dict["response_metadata"]["finish_reason"] = "tool_call"
|
msg_dict["response_metadata"]["finish_reason"] = "tool_call"
|
||||||
msg_dict["response_metadata"]["model_name"] = model_name[:len(model_name)//repeat_count]
|
msg_dict["response_metadata"]["model_name"] = model_name[: len(model_name) // repeat_count]
|
||||||
|
|
||||||
# 保存 AI 消息
|
# 保存 AI 消息
|
||||||
ai_msg = conv_mgr.add_message(
|
ai_msg = conv_mgr.add_message(
|
||||||
|
|||||||
@ -421,9 +421,7 @@ async def get_knowledge_stats(
|
|||||||
for _fid, finfo in files_meta.items():
|
for _fid, finfo in files_meta.items():
|
||||||
file_ext = (finfo.get("file_type") or "").lower()
|
file_ext = (finfo.get("file_type") or "").lower()
|
||||||
# 统一映射显示名
|
# 统一映射显示名
|
||||||
display_name = file_type_mapping.get(
|
display_name = file_type_mapping.get(file_ext, file_ext.upper() + "文件" if file_ext else "其他")
|
||||||
file_ext, file_ext.upper() + "文件" if file_ext else "其他"
|
|
||||||
)
|
|
||||||
files_by_type[display_name] = files_by_type.get(display_name, 0) + 1
|
files_by_type[display_name] = files_by_type.get(display_name, 0) + 1
|
||||||
|
|
||||||
# 估算大小(如果路径存在且是本地文件)
|
# 估算大小(如果路径存在且是本地文件)
|
||||||
@ -721,33 +719,29 @@ async def get_call_timeseries_stats(
|
|||||||
):
|
):
|
||||||
"""Get time series statistics for call analytics (Admin only)"""
|
"""Get time series statistics for call analytics (Admin only)"""
|
||||||
try:
|
try:
|
||||||
from src.storage.db.models import Conversation, Message, ToolCall, ConversationStats
|
from src.storage.db.models import Conversation, Message, ToolCall
|
||||||
|
|
||||||
# 计算时间范围(使用北京时间 UTC+8)
|
# 计算时间范围(使用北京时间 UTC+8)
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
beijing_time = now + timedelta(hours=8) # 转换为北京时间
|
|
||||||
|
|
||||||
if time_range == "7hours":
|
if time_range == "7hours":
|
||||||
intervals = 7
|
intervals = 7
|
||||||
# 包含当前小时:从6小时前开始
|
# 包含当前小时:从6小时前开始
|
||||||
start_time = now - timedelta(hours=intervals-1)
|
start_time = now - timedelta(hours=intervals - 1)
|
||||||
time_format = "%Y-%m-%d %H:00"
|
|
||||||
# SQLite compatible approach: 使用datetime函数转换UTC时间为北京时间
|
# SQLite compatible approach: 使用datetime函数转换UTC时间为北京时间
|
||||||
group_format = func.strftime("%Y-%m-%d %H:00", func.datetime(Message.created_at, '+8 hours'))
|
group_format = func.strftime("%Y-%m-%d %H:00", func.datetime(Message.created_at, "+8 hours"))
|
||||||
elif time_range == "7weeks":
|
elif time_range == "7weeks":
|
||||||
intervals = 7
|
intervals = 7
|
||||||
# 包含当前周:从6周前开始
|
# 包含当前周:从6周前开始
|
||||||
start_time = now - timedelta(weeks=intervals-1)
|
start_time = now - timedelta(weeks=intervals - 1)
|
||||||
time_format = "%Y-W%U"
|
|
||||||
# SQLite compatible approach: 使用datetime函数转换UTC时间为北京时间
|
# SQLite compatible approach: 使用datetime函数转换UTC时间为北京时间
|
||||||
group_format = func.strftime("%Y-%W", func.datetime(Message.created_at, '+8 hours'))
|
group_format = func.strftime("%Y-%W", func.datetime(Message.created_at, "+8 hours"))
|
||||||
else: # 7days (default)
|
else: # 7days (default)
|
||||||
intervals = 7
|
intervals = 7
|
||||||
# 包含当前天:从6天前开始
|
# 包含当前天:从6天前开始
|
||||||
start_time = now - timedelta(days=intervals-1)
|
start_time = now - timedelta(days=intervals - 1)
|
||||||
time_format = "%Y-%m-%d"
|
|
||||||
# SQLite compatible approach: 使用datetime函数转换UTC时间为北京时间
|
# SQLite compatible approach: 使用datetime函数转换UTC时间为北京时间
|
||||||
group_format = func.strftime("%Y-%m-%d", func.datetime(Message.created_at, '+8 hours'))
|
group_format = func.strftime("%Y-%m-%d", func.datetime(Message.created_at, "+8 hours"))
|
||||||
|
|
||||||
# 根据类型查询数据
|
# 根据类型查询数据
|
||||||
if type == "models":
|
if type == "models":
|
||||||
@ -757,7 +751,7 @@ async def get_call_timeseries_stats(
|
|||||||
db.query(
|
db.query(
|
||||||
group_format.label("date"),
|
group_format.label("date"),
|
||||||
func.count(Message.id).label("count"),
|
func.count(Message.id).label("count"),
|
||||||
func.json_extract(Message.extra_metadata, "$.response_metadata.model_name").label("category")
|
func.json_extract(Message.extra_metadata, "$.response_metadata.model_name").label("category"),
|
||||||
)
|
)
|
||||||
.filter(Message.role == "assistant", Message.created_at >= start_time)
|
.filter(Message.role == "assistant", Message.created_at >= start_time)
|
||||||
.filter(Message.extra_metadata.isnot(None))
|
.filter(Message.extra_metadata.isnot(None))
|
||||||
@ -768,17 +762,17 @@ async def get_call_timeseries_stats(
|
|||||||
# 智能体调用统计(基于对话数量,按智能体分组)
|
# 智能体调用统计(基于对话数量,按智能体分组)
|
||||||
# 为对话创建独立的时间格式化器
|
# 为对话创建独立的时间格式化器
|
||||||
if time_range == "7hours":
|
if time_range == "7hours":
|
||||||
conv_group_format = func.strftime("%Y-%m-%d %H:00", func.datetime(Conversation.created_at, '+8 hours'))
|
conv_group_format = func.strftime("%Y-%m-%d %H:00", func.datetime(Conversation.created_at, "+8 hours"))
|
||||||
elif time_range == "7weeks":
|
elif time_range == "7weeks":
|
||||||
conv_group_format = func.strftime("%Y-%W", func.datetime(Conversation.created_at, '+8 hours'))
|
conv_group_format = func.strftime("%Y-%W", func.datetime(Conversation.created_at, "+8 hours"))
|
||||||
else: # 7days
|
else: # 7days
|
||||||
conv_group_format = func.strftime("%Y-%m-%d", func.datetime(Conversation.created_at, '+8 hours'))
|
conv_group_format = func.strftime("%Y-%m-%d", func.datetime(Conversation.created_at, "+8 hours"))
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
db.query(
|
db.query(
|
||||||
conv_group_format.label("date"),
|
conv_group_format.label("date"),
|
||||||
func.count(Conversation.id).label("count"),
|
func.count(Conversation.id).label("count"),
|
||||||
Conversation.agent_id.label("category")
|
Conversation.agent_id.label("category"),
|
||||||
)
|
)
|
||||||
.filter(Conversation.created_at >= start_time)
|
.filter(Conversation.created_at >= start_time)
|
||||||
.group_by(conv_group_format, Conversation.agent_id)
|
.group_by(conv_group_format, Conversation.agent_id)
|
||||||
@ -787,22 +781,20 @@ async def get_call_timeseries_stats(
|
|||||||
elif type == "tokens":
|
elif type == "tokens":
|
||||||
# Token消耗统计(区分input/output tokens)
|
# Token消耗统计(区分input/output tokens)
|
||||||
# 先查询input tokens
|
# 先查询input tokens
|
||||||
from sqlalchemy import text, literal
|
from sqlalchemy import literal
|
||||||
|
|
||||||
input_query = (
|
input_query = (
|
||||||
db.query(
|
db.query(
|
||||||
group_format.label("date"),
|
group_format.label("date"),
|
||||||
func.sum(
|
func.sum(
|
||||||
func.coalesce(
|
func.coalesce(func.json_extract(Message.extra_metadata, "$.usage_metadata.input_tokens"), 0)
|
||||||
func.json_extract(Message.extra_metadata, "$.usage_metadata.input_tokens"), 0
|
|
||||||
)
|
|
||||||
).label("count"),
|
).label("count"),
|
||||||
literal("input_tokens").label("category")
|
literal("input_tokens").label("category"),
|
||||||
)
|
)
|
||||||
.filter(
|
.filter(
|
||||||
Message.created_at >= start_time,
|
Message.created_at >= start_time,
|
||||||
Message.extra_metadata.isnot(None),
|
Message.extra_metadata.isnot(None),
|
||||||
func.json_extract(Message.extra_metadata, "$.usage_metadata").isnot(None)
|
func.json_extract(Message.extra_metadata, "$.usage_metadata").isnot(None),
|
||||||
)
|
)
|
||||||
.group_by(group_format)
|
.group_by(group_format)
|
||||||
.order_by(group_format)
|
.order_by(group_format)
|
||||||
@ -813,16 +805,14 @@ async def get_call_timeseries_stats(
|
|||||||
db.query(
|
db.query(
|
||||||
group_format.label("date"),
|
group_format.label("date"),
|
||||||
func.sum(
|
func.sum(
|
||||||
func.coalesce(
|
func.coalesce(func.json_extract(Message.extra_metadata, "$.usage_metadata.output_tokens"), 0)
|
||||||
func.json_extract(Message.extra_metadata, "$.usage_metadata.output_tokens"), 0
|
|
||||||
)
|
|
||||||
).label("count"),
|
).label("count"),
|
||||||
literal("output_tokens").label("category")
|
literal("output_tokens").label("category"),
|
||||||
)
|
)
|
||||||
.filter(
|
.filter(
|
||||||
Message.created_at >= start_time,
|
Message.created_at >= start_time,
|
||||||
Message.extra_metadata.isnot(None),
|
Message.extra_metadata.isnot(None),
|
||||||
func.json_extract(Message.extra_metadata, "$.usage_metadata").isnot(None)
|
func.json_extract(Message.extra_metadata, "$.usage_metadata").isnot(None),
|
||||||
)
|
)
|
||||||
.group_by(group_format)
|
.group_by(group_format)
|
||||||
.order_by(group_format)
|
.order_by(group_format)
|
||||||
@ -836,17 +826,17 @@ async def get_call_timeseries_stats(
|
|||||||
# 工具调用统计(按工具名称分组)
|
# 工具调用统计(按工具名称分组)
|
||||||
# 为工具调用创建独立的时间格式化器
|
# 为工具调用创建独立的时间格式化器
|
||||||
if time_range == "7hours":
|
if time_range == "7hours":
|
||||||
tool_group_format = func.strftime("%Y-%m-%d %H:00", func.datetime(ToolCall.created_at, '+8 hours'))
|
tool_group_format = func.strftime("%Y-%m-%d %H:00", func.datetime(ToolCall.created_at, "+8 hours"))
|
||||||
elif time_range == "7weeks":
|
elif time_range == "7weeks":
|
||||||
tool_group_format = func.strftime("%Y-%W", func.datetime(ToolCall.created_at, '+8 hours'))
|
tool_group_format = func.strftime("%Y-%W", func.datetime(ToolCall.created_at, "+8 hours"))
|
||||||
else: # 7days
|
else: # 7days
|
||||||
tool_group_format = func.strftime("%Y-%m-%d", func.datetime(ToolCall.created_at, '+8 hours'))
|
tool_group_format = func.strftime("%Y-%m-%d", func.datetime(ToolCall.created_at, "+8 hours"))
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
db.query(
|
db.query(
|
||||||
tool_group_format.label("date"),
|
tool_group_format.label("date"),
|
||||||
func.count(ToolCall.id).label("count"),
|
func.count(ToolCall.id).label("count"),
|
||||||
ToolCall.tool_name.label("category")
|
ToolCall.tool_name.label("category"),
|
||||||
)
|
)
|
||||||
.filter(ToolCall.created_at >= start_time)
|
.filter(ToolCall.created_at >= start_time)
|
||||||
.group_by(tool_group_format, ToolCall.tool_name)
|
.group_by(tool_group_format, ToolCall.tool_name)
|
||||||
@ -862,7 +852,7 @@ async def get_call_timeseries_stats(
|
|||||||
# 首先收集所有类别
|
# 首先收集所有类别
|
||||||
categories = set()
|
categories = set()
|
||||||
for result in results:
|
for result in results:
|
||||||
if hasattr(result, 'category') and result.category:
|
if hasattr(result, "category") and result.category:
|
||||||
categories.add(result.category)
|
categories.add(result.category)
|
||||||
|
|
||||||
# 如果没有类别数据,提供默认类别
|
# 如果没有类别数据,提供默认类别
|
||||||
@ -882,7 +872,7 @@ async def get_call_timeseries_stats(
|
|||||||
time_data = {}
|
time_data = {}
|
||||||
for result in results:
|
for result in results:
|
||||||
date_key = result.date
|
date_key = result.date
|
||||||
category = getattr(result, 'category', 'unknown')
|
category = getattr(result, "category", "unknown")
|
||||||
count = result.count
|
count = result.count
|
||||||
|
|
||||||
if date_key not in time_data:
|
if date_key not in time_data:
|
||||||
@ -921,17 +911,14 @@ async def get_call_timeseries_stats(
|
|||||||
if category not in day_data:
|
if category not in day_data:
|
||||||
day_data[category] = 0
|
day_data[category] = 0
|
||||||
|
|
||||||
data.append({
|
data.append({"date": date_key, "data": day_data, "total": day_total})
|
||||||
"date": date_key,
|
|
||||||
"data": day_data,
|
|
||||||
"total": day_total
|
|
||||||
})
|
|
||||||
current_time += delta
|
current_time += delta
|
||||||
|
|
||||||
# 计算统计指标
|
# 计算统计指标
|
||||||
if type == "tools":
|
if type == "tools":
|
||||||
# 对于工具调用,显示所有时间的总数(与ToolStatsComponent保持一致)
|
# 对于工具调用,显示所有时间的总数(与ToolStatsComponent保持一致)
|
||||||
from src.storage.db.models import ToolCall
|
from src.storage.db.models import ToolCall
|
||||||
|
|
||||||
total_count = db.query(func.count(ToolCall.id)).scalar() or 0
|
total_count = db.query(func.count(ToolCall.id)).scalar() or 0
|
||||||
else:
|
else:
|
||||||
# 其他类型使用时间序列数据的总和
|
# 其他类型使用时间序列数据的总和
|
||||||
|
|||||||
@ -2,6 +2,7 @@ from datetime import UTC, datetime
|
|||||||
|
|
||||||
from langchain_core.messages import AIMessageChunk, ToolMessage
|
from langchain_core.messages import AIMessageChunk, ToolMessage
|
||||||
from langchain_core.runnables import RunnableConfig
|
from langchain_core.runnables import RunnableConfig
|
||||||
|
|
||||||
from src.agents.common.base import BaseAgent
|
from src.agents.common.base import BaseAgent
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -205,15 +205,11 @@ class ChromaKB(KnowledgeBase):
|
|||||||
total_batches = (len(chunks) + batch_size - 1) // batch_size
|
total_batches = (len(chunks) + batch_size - 1) // batch_size
|
||||||
|
|
||||||
for i in range(0, len(chunks), batch_size):
|
for i in range(0, len(chunks), batch_size):
|
||||||
batch_documents = documents[i:i + batch_size]
|
batch_documents = documents[i : i + batch_size]
|
||||||
batch_metadatas = metadatas[i:i + batch_size]
|
batch_metadatas = metadatas[i : i + batch_size]
|
||||||
batch_ids = ids[i:i + batch_size]
|
batch_ids = ids[i : i + batch_size]
|
||||||
|
|
||||||
collection.add(
|
collection.add(documents=batch_documents, metadatas=batch_metadatas, ids=batch_ids)
|
||||||
documents=batch_documents,
|
|
||||||
metadatas=batch_metadatas,
|
|
||||||
ids=batch_ids
|
|
||||||
)
|
|
||||||
|
|
||||||
batch_num = i // batch_size + 1
|
batch_num = i // batch_size + 1
|
||||||
logger.info(f"Processed batch {batch_num}/{total_batches} for {filename}")
|
logger.info(f"Processed batch {batch_num}/{total_batches} for {filename}")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user