Spaces:
Sleeping
Sleeping
quachtiensinh27
feat: initialize core agent infrastructure including Redis client, tool directory, scheduling logic, and documentation.
85ff578 | """ | |
| Summarization tool using LangChain + LLM. | |
| """ | |
| import time | |
| import logging | |
| from typing import Any, List | |
| from pydantic import BaseModel, Field | |
| from langchain_core.output_parsers import JsonOutputParser | |
| from langchain_core.prompts import ChatPromptTemplate | |
| from .base import register_tool, get_llm | |
| from .utils import preprocess_messages, extract_metadata_from_messages | |
| try: | |
| from ..redis_client import redis_client | |
| except (ImportError, ValueError): | |
| from redis_client import redis_client | |
| logger = logging.getLogger(__name__) | |
| # --- Pydantic Schemas --- | |
| class ThreadSummary(BaseModel): | |
| """Schema cho tóm tắt của một thread.""" | |
| thread_id: str = Field(description="ID hoặc tên chủ đề của thread") | |
| main_discussion: str = Field(description="Nội dung chính đang thảo luận") | |
| conversation_flow: str = Field(description="Tóm tắt diễn biến cuộc hội thoại (ai hỏi, ai trả lời, mâu thuẫn/đồng thuận)") | |
| status: str = Field(description="Trạng thái: 'Đã chốt' hoặc 'Chưa chốt'") | |
| conclusion: str = Field(description="Kết luận cuối cùng") | |
| class DecisionObject(BaseModel): | |
| """Schema cho một quyết định cụ thể.""" | |
| content: str = Field(description="Nội dung quyết định vừa chốt") | |
| confirmed_by: list[str] = Field(description="Tên những người đã thống nhất/đồng thuận") | |
| class TaskObject(BaseModel): | |
| """Schema cho một công việc được giao.""" | |
| task: str = Field(description="Nội dung công việc") | |
| assignee: str = Field(description="Người thực hiện (nếu có)") | |
| deadline: str = Field(description="Hạn chót (nếu có đề cập)") | |
| class TLDRResponse(BaseModel): | |
| """Schema cho response JSON tổng thể.""" | |
| summary: list[ThreadSummary] = Field(description="Danh sách tóm tắt các thread") | |
| links_found: list[str] = Field(description="Danh sách các liên kết (URL) được tìm thấy") | |
| files_found: list[dict] = Field(description="Danh sách các tệp tin/ảnh được tìm thấy") | |
| decisions: list[DecisionObject] = Field(default=[], description="Danh sách các quyết định quan trọng vừa chốt (Decision Log)") | |
| assigned_tasks: list[TaskObject] = Field(default=[], description="Danh sách các công việc vừa được giao (Task List)") | |
| # --- System Prompt --- | |
| SYSTEM_PROMPT_TLDR = """ | |
| Bạn là một THƯ KÝ DỰ ÁN chuyên nghiệp. | |
| Nhiệm vụ: tóm tắt các đoạn chat nhóm thành báo cáo chính xác tuyệt đối. | |
| - **ƯU TIÊN**: Nếu người dùng có yêu cầu cụ thể (query), bạn phải tập trung giải quyết yêu cầu đó trong phần đầu của `summary`. | |
| - Xác định rõ 'conversation_flow': mô tả cách cuộc thảo luận diễn ra (ví dụ: A đề xuất, B phản đối, cuối cùng cả nhóm đồng ý). | |
| - **QUAN TRỌNG**: Nếu thấy các câu lệnh mang tính chốt hạ như "ok", "duyệt", "thống nhất vậy đi", "chốt cái này"... hãy đưa vào mục `decisions`. | |
| - **QUAN TRỌNG**: Nếu thấy có sự phân công công việc (Ví dụ: "Hùng làm slide nhé", "A check lại giá") -> đưa vào `assigned_tasks`. | |
| - Trả về JSON đúng schema. | |
| """ | |
| # ... (execute_tool part) | |
| def tool_summarize_chat( | |
| messages: List[dict] = None, | |
| limit: int = 100, | |
| room_id: str = None, | |
| dm_id: str = None, | |
| conversation_id: str = None, | |
| query: str = None, | |
| auto_save: bool = False | |
| ) -> dict: | |
| start_time = time.time() | |
| try: | |
| if messages is None: | |
| if conversation_id: | |
| messages = redis_client.get_messages_by_conversation_id(conversation_id, limit) | |
| elif dm_id: | |
| messages = redis_client.get_dm_messages(dm_id, limit) | |
| elif room_id: | |
| messages = redis_client.get_room_messages(room_id, limit) | |
| else: | |
| raise ValueError("Either room_id, dm_id or conversation_id is required when messages is not provided") | |
| if not messages: | |
| return { | |
| "status": "success", | |
| "data": { | |
| "summary": [], | |
| "links_found": [], | |
| "files_found": [], | |
| "decisions": [], | |
| "assigned_tasks": [] | |
| }, | |
| "metrics": {"processing_time_sec": 0} | |
| } | |
| # 1. Trích xuất Metadata (Links/Files) | |
| metadata = extract_metadata_from_messages(messages) | |
| # 2. Tiền xử lý văn bản cho LLM | |
| formatted_threads = preprocess_messages(messages) | |
| llm = get_llm() | |
| parser = JsonOutputParser(pydantic_object=TLDRResponse) | |
| prompt = ChatPromptTemplate.from_messages([ | |
| ("system", SYSTEM_PROMPT_TLDR), | |
| ("human", "Dựa trên các tin nhắn sau, hãy thực hiện yêu cầu này: {query}\n\nNỘI DUNG TIN NHẮN:\n{chat_threads}\n\n{format_instructions}"), | |
| ]) | |
| chain = prompt | llm | parser | |
| result = chain.invoke({ | |
| "chat_threads": formatted_threads, | |
| "query": query or "Tóm tắt tổng quát các nội dung quan trọng.", | |
| "format_instructions": parser.get_format_instructions(), | |
| }) | |
| # Merge metadata vào kết quả | |
| result["links_found"] = list(set(result.get("links_found", []) + metadata["links"])) | |
| result["files_found"] = metadata["files"] | |
| # 3. Logic Tự động lưu (Auto-save) và Thưởng điểm (Rewards) | |
| if auto_save and room_id: | |
| for dec in result.get("decisions", []): | |
| redis_client.save_decision(room_id, dec) | |
| # Thưởng điểm cho những người tham gia chốt | |
| for user in dec.get("confirmed_by", []): | |
| redis_client.add_reward(room_id, user, points=2) | |
| for task in result.get("assigned_tasks", []): | |
| redis_client.save_task(room_id, task) | |
| # Thưởng điểm cho người nhận task | |
| if task.get("assignee"): | |
| redis_client.add_reward(room_id, task["assignee"], points=3) | |
| processing_time = round(time.time() - start_time, 2) | |
| return { | |
| "status": "success", | |
| "data": result, | |
| "metrics": {"processing_time_sec": processing_time} | |
| } | |
| except Exception as e: | |
| logger.error(f"Summarizer error: {e}") | |
| return {"status": "error", "data": {"error": str(e)}, "metrics": {"processing_time_sec": 0}} | |