Spaces:
Sleeping
Sleeping
Commit ·
8c43ca8
1
Parent(s): 552e239
Thêm room_id vào state
Browse files- graph.py +1 -0
- redis_client.py +30 -0
- state.py +2 -0
- tools/chat_tools.py +11 -52
graph.py
CHANGED
|
@@ -55,6 +55,7 @@ def run(query: dict) -> AgentState:
|
|
| 55 |
AgentState cuối cùng (có final_answer).
|
| 56 |
"""
|
| 57 |
initial_state: AgentState = {
|
|
|
|
| 58 |
"sender_id": query["from"],
|
| 59 |
"time": query.get("time", ""),
|
| 60 |
"raw_query": query["body"],
|
|
|
|
| 55 |
AgentState cuối cùng (có final_answer).
|
| 56 |
"""
|
| 57 |
initial_state: AgentState = {
|
| 58 |
+
"room_id": query.get("room_id", ""),
|
| 59 |
"sender_id": query["from"],
|
| 60 |
"time": query.get("time", ""),
|
| 61 |
"raw_query": query["body"],
|
redis_client.py
CHANGED
|
@@ -86,6 +86,36 @@ class RedisClient:
|
|
| 86 |
logger.error(f"Redis ping failed: {e}")
|
| 87 |
return False
|
| 88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
def get_room_messages(self, room_id: str, limit: int = 100) -> list[dict]:
|
| 90 |
"""
|
| 91 |
Fetch recent messages from a room.
|
|
|
|
| 86 |
logger.error(f"Redis ping failed: {e}")
|
| 87 |
return False
|
| 88 |
|
| 89 |
+
def save_room_messages(self, room_id: str, messages: list[dict]) -> bool:
|
| 90 |
+
"""Overwrite messages for a room (used for test seeding)."""
|
| 91 |
+
try:
|
| 92 |
+
if self._use_local:
|
| 93 |
+
db = self._load_local()
|
| 94 |
+
db.setdefault("messages", {})[room_id] = messages
|
| 95 |
+
self._save_local(db)
|
| 96 |
+
return True
|
| 97 |
+
|
| 98 |
+
key = self._key("room", "messages", room_id)
|
| 99 |
+
self._client.delete(key)
|
| 100 |
+
for i, msg in enumerate(messages):
|
| 101 |
+
msg_id = msg.get("id") or f"{room_id}_{i}"
|
| 102 |
+
ts = i
|
| 103 |
+
if "timestamp" in msg:
|
| 104 |
+
try:
|
| 105 |
+
dt = datetime.fromisoformat(msg["timestamp"].replace("Z", "+00:00"))
|
| 106 |
+
ts = int(dt.timestamp() * 1000)
|
| 107 |
+
except Exception:
|
| 108 |
+
ts = int(time.time() * 1000) + i
|
| 109 |
+
self._client.zadd(key, {msg_id: ts})
|
| 110 |
+
self._client.hset(
|
| 111 |
+
self._key("msg", msg_id),
|
| 112 |
+
mapping={k: str(v) for k, v in msg.items()},
|
| 113 |
+
)
|
| 114 |
+
return True
|
| 115 |
+
except Exception as e:
|
| 116 |
+
logger.error(f"Failed to save room messages: {e}")
|
| 117 |
+
return False
|
| 118 |
+
|
| 119 |
def get_room_messages(self, room_id: str, limit: int = 100) -> list[dict]:
|
| 120 |
"""
|
| 121 |
Fetch recent messages from a room.
|
state.py
CHANGED
|
@@ -15,6 +15,7 @@ class AgentState(TypedDict):
|
|
| 15 |
"""
|
| 16 |
Trạng thái duy nhất chạy xuyên suốt graph.
|
| 17 |
|
|
|
|
| 18 |
sender_id : ID người dùng, ví dụ "@NguyenVanA"
|
| 19 |
time : Thời điểm gửi (ISO-8601)
|
| 20 |
raw_query : Nội dung tin nhắn gốc
|
|
@@ -24,6 +25,7 @@ class AgentState(TypedDict):
|
|
| 24 |
max_iters : Giới hạn vòng lặp tool
|
| 25 |
final_answer : Câu trả lời cuối cùng
|
| 26 |
"""
|
|
|
|
| 27 |
sender_id: str
|
| 28 |
time: str
|
| 29 |
raw_query: str
|
|
|
|
| 15 |
"""
|
| 16 |
Trạng thái duy nhất chạy xuyên suốt graph.
|
| 17 |
|
| 18 |
+
room_id : ID phòng/nhóm học tập, ví dụ "room_a20"
|
| 19 |
sender_id : ID người dùng, ví dụ "@NguyenVanA"
|
| 20 |
time : Thời điểm gửi (ISO-8601)
|
| 21 |
raw_query : Nội dung tin nhắn gốc
|
|
|
|
| 25 |
max_iters : Giới hạn vòng lặp tool
|
| 26 |
final_answer : Câu trả lời cuối cùng
|
| 27 |
"""
|
| 28 |
+
room_id: str
|
| 29 |
sender_id: str
|
| 30 |
time: str
|
| 31 |
raw_query: str
|
tools/chat_tools.py
CHANGED
|
@@ -1,57 +1,16 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
-
#
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
[2024-06-01 09:02] @NguyenVanA : Python có dùng được cho AI không?
|
| 8 |
-
[2024-06-01 09:03] @Assistant : Có, Python là ngôn ngữ phổ biến nhất trong AI/ML.
|
| 9 |
-
Các thư viện nổi bật: TensorFlow, PyTorch, scikit-learn.
|
| 10 |
-
[2024-06-01 09:10] @NguyenVanA : Còn LangChain thì sao?
|
| 11 |
-
[2024-06-01 09:11] @Assistant : LangChain là framework giúp xây dựng ứng dụng LLM dễ dàng hơn,
|
| 12 |
-
hỗ trợ chain, agent, memory và tool use.
|
| 13 |
-
[2024-06-01 09:15] @NguyenVanA : Cảm ơn bạn!
|
| 14 |
-
[2024-06-01 09:15] @Assistant : Không có gì! Chúc bạn học vui.
|
| 15 |
-
""".strip()
|
| 16 |
|
|
|
|
| 17 |
|
| 18 |
-
|
| 19 |
-
def fetch_chat_history(sender_id: str, limit: int = 100) -> str:
|
| 20 |
-
"""
|
| 21 |
-
Trích xuất lịch sử trò chuyện trước đó của người dùng.
|
| 22 |
|
| 23 |
-
|
| 24 |
-
sender_id : ID người dùng, ví dụ "@NguyenVanA".
|
| 25 |
-
limit : Số lượng tin nhắn tối đa cần lấy (mặc định 100).
|
| 26 |
-
|
| 27 |
-
Returns:
|
| 28 |
-
Chuỗi văn bản chứa lịch sử chat được định dạng sẵn.
|
| 29 |
-
"""
|
| 30 |
-
# ── TODO: thay bằng logic thật (DB query, API call...) ──────────────────
|
| 31 |
-
print(f" [tool] fetch_chat_history(sender_id={sender_id!r}, limit={limit})")
|
| 32 |
-
return f"Lịch sử chat của {sender_id} (mock):\n\n{MOCK_HISTORY}"
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
@tool
|
| 36 |
-
def summarize_messages(content: str) -> str:
|
| 37 |
-
"""
|
| 38 |
-
Tóm tắt nội dung đoạn chat được cung cấp.
|
| 39 |
-
|
| 40 |
-
Args:
|
| 41 |
-
content : Văn bản cần tóm tắt (thường là kết quả của fetch_chat_history).
|
| 42 |
-
|
| 43 |
-
Returns:
|
| 44 |
-
Đoạn tóm tắt ngắn gọn, súc tích.
|
| 45 |
-
"""
|
| 46 |
-
# ── TODO: thay bằng logic thật (gọi LLM riêng, extractive summary...) ──
|
| 47 |
-
print(f" [tool] summarize_messages(content[:50]={content[:50]!r}...)")
|
| 48 |
-
return (
|
| 49 |
-
"Tóm tắt (mock): Người dùng hỏi về Python và ứng dụng trong AI. "
|
| 50 |
-
"Trợ lý giải thích Python là ngôn ngữ phổ biến nhất trong AI/ML, "
|
| 51 |
-
"giới thiệu các thư viện TensorFlow, PyTorch, scikit-learn và "
|
| 52 |
-
"framework LangChain dùng để xây dựng ứng dụng LLM."
|
| 53 |
-
)
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
TOOLS = [fetch_chat_history, summarize_messages]
|
| 57 |
TOOL_MAP = {t.name: t for t in TOOLS}
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Re-exports real tools (memory, scheduler, summarizer) as LangChain tools.
|
| 3 |
+
Replaces the previous mock implementations.
|
| 4 |
+
"""
|
| 5 |
|
| 6 |
+
# Import modules so register_tool decorators fire and populate base.TOOLS
|
| 7 |
+
from . import memory as _memory_mod # noqa: F401
|
| 8 |
+
from . import scheduler as _scheduler_mod # noqa: F401
|
| 9 |
+
from . import summarizer as _summarizer_mod # noqa: F401
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
+
from .base import TOOLS as _REGISTRY, get_langchain_tools
|
| 12 |
|
| 13 |
+
_ALLOWED = {"save_memory", "get_memories", "get_schedule", "add_event", "summarize_chat"}
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
+
TOOLS = [t for t in get_langchain_tools() if t.name in _ALLOWED]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
TOOL_MAP = {t.name: t for t in TOOLS}
|