From 84e2d2930f57e66888d21f858c37b3f895afdfca Mon Sep 17 00:00:00 2001 From: hduc-le Date: Mon, 1 Jun 2026 03:42:42 +0000 Subject: [PATCH] fix ontology category, simulation context and reddit twhin-bert --- .../app/services/oasis_profile_generator.py | 8 ++- backend/app/services/simulation_ipc.py | 2 +- backend/app/services/zep_tools.py | 23 ++++---- backend/app/utils/llm_cost.py | 6 +- backend/scripts/run_parallel_simulation.py | 56 +++++++++++++++++-- 5 files changed, 75 insertions(+), 20 deletions(-) diff --git a/backend/app/services/oasis_profile_generator.py b/backend/app/services/oasis_profile_generator.py index d12458ed..4e86bad3 100644 --- a/backend/app/services/oasis_profile_generator.py +++ b/backend/app/services/oasis_profile_generator.py @@ -120,6 +120,8 @@ class OasisAgentProfile: profile["profession"] = self.profession if self.interested_topics: profile["interested_topics"] = self.interested_topics + if self.entity_category: + profile["entity_category"] = self.entity_category return profile @@ -929,7 +931,7 @@ Dựa vào toàn bộ thông tin trên, xác định thực thể này thuộc l BƯỚC 2 — TẠO HỒ SƠ: Tạo JSON với các trường sau, điều chỉnh theo kết quả phân loại: -1. entity_category: Kết quả phân loại ở Bước 1 — "individual" hoặc "organization" +1. entity_category: "individual"/"organization" 2. bio: Tiểu sử mạng xã hội ngắn gọn, tối đa 200 ký tự. @@ -1547,7 +1549,7 @@ QUAN TRỌNG: "user_id": profile.user_id if profile.user_id is not None else idx, "username": profile.user_name, "name": profile.name, - "bio": profile.bio[:150] if profile.bio else f"{profile.name}", # Cap ở 150 ký tự + "bio": profile.bio if profile.bio else f"{profile.name}", "persona": profile.persona or f"{profile.name} is a participant in social discussions.", "karma": profile.karma if profile.karma else 1000, "created_at": profile.created_at, @@ -1562,6 +1564,8 @@ QUAN TRỌNG: item["profession"] = profile.profession if profile.interested_topics: item["interested_topics"] = profile.interested_topics + if profile.entity_category: + item["entity_category"] = profile.entity_category data.append(item) diff --git a/backend/app/services/simulation_ipc.py b/backend/app/services/simulation_ipc.py index 4c7b6eed..afddff04 100644 --- a/backend/app/services/simulation_ipc.py +++ b/backend/app/services/simulation_ipc.py @@ -137,7 +137,7 @@ class SimulationIPCClient: TimeoutError: Lỗi quá thời gian chờ phản hồi """ command_id = str(uuid.uuid4()) - command = s( + command = IPCCommand( command_id=command_id, command_type=command_type, args=args diff --git a/backend/app/services/zep_tools.py b/backend/app/services/zep_tools.py index db1a35a5..830825f0 100644 --- a/backend/app/services/zep_tools.py +++ b/backend/app/services/zep_tools.py @@ -438,9 +438,6 @@ class ZepToolsService: if self._llm_client is None: self._llm_client = LLMClient( component="zep_tools", - metadata={ - "phase": "zep_tools", - }, ) return self._llm_client @@ -1151,13 +1148,14 @@ Trả về danh sách các câu hỏi phụ dưới định dạng JSON.""" {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ], - temperature=0.3 + temperature=0.3, + metadata={"phase": "_generate_sub_queries"}, ) - + sub_queries = response.get("sub_queries", []) # Ép kiểu để chắc chắn danh sách toàn kiểu string return [str(sq) for sq in sub_queries[:max_queries]] - + except Exception as e: logger.warning(f"Failed to generate sub-queries: {str(e)}, using default sub-queries") # Hạ cấp (fallback): Trả về các biến thể chung chung của câu hỏi ban đầu @@ -1672,9 +1670,10 @@ Hãy chọn tối đa {max_agents} Agent phù hợp nhất để phỏng vấn v {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ], - temperature=0.3 + temperature=0.3, + metadata={"phase": "_select_agents_for_interview"}, ) - + selected_indices = response.get("selected_indices", [])[:max_agents] reasoning = response.get("reasoning", "Auto selected based on relevance") @@ -1751,9 +1750,10 @@ Hãy tạo từ 3-5 câu hỏi phỏng vấn.""" {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ], - temperature=0.5 + temperature=0.5, + metadata={"phase": "_generate_interview_questions"}, ) - + return response.get("questions", [f"What is your opinion on {interview_requirement}?"]) except Exception as e: @@ -1832,7 +1832,8 @@ Hãy tạo bản tóm tắt phỏng vấn.""" {"role": "user", "content": user_prompt} ], temperature=0.3, - max_tokens=4096 + max_tokens=4096, + metadata={"phase": "_generate_interview_summary"}, ) return summary diff --git a/backend/app/utils/llm_cost.py b/backend/app/utils/llm_cost.py index e71b3c94..a213e380 100644 --- a/backend/app/utils/llm_cost.py +++ b/backend/app/utils/llm_cost.py @@ -24,7 +24,7 @@ MODEL_COSTS_PER_1M_TOKENS: Dict[str, Dict[str, float]] = { "Qwen/Qwen3.5-27B": {"input": 0.5, "output": 3.0}, "Qwen/Qwen3.6-27B": {"input": 0.5, "output": 3.0}, "gemini-3-flash": {"input": 0.5, "output": 3.0}, - "gemini-3.1-flash-lite": {"input": 0.25, "output": 1.5}, + "Qwen/Qwen3.6-27B-FP8 ": {"input": 0.5, "output": 3.0}, } @@ -174,8 +174,10 @@ def record_llm_cost( request_no = int(counter["requests"]) cumulative_cost = _quantize_8(counter["total_cost"]) + phase = metadata.get("phase") + component_label = f"{component}.{phase}" if phase else component line = ( - f"[{timestamp}] [Request {request_no}] [{component}] " + f"[{timestamp}] [Request {request_no}] [{component_label}] " f"Called model: {model_name}, " f"input_tokens: {usage_dict['input_tokens']} | " f"output_tokens: {usage_dict['output_tokens']} | " diff --git a/backend/scripts/run_parallel_simulation.py b/backend/scripts/run_parallel_simulation.py index ae9aa485..7eff5565 100644 --- a/backend/scripts/run_parallel_simulation.py +++ b/backend/scripts/run_parallel_simulation.py @@ -203,6 +203,9 @@ from llm_cost_patch import install_openai_cost_patch try: from camel.models import ModelFactory from camel.types import ModelPlatformType + from camel.memories import ChatHistoryMemory, ScoreBasedContextCreator + from camel.utils import OpenAITokenCounter + from camel.types import ModelType import oasis from oasis import ( ActionType, @@ -211,6 +214,8 @@ try: generate_twitter_agent_graph, generate_reddit_agent_graph ) + from oasis.social_platform import Platform + from oasis.social_platform.channel import Channel except ImportError as e: print(f"Error: Missing dependency {e}") print("Please install first: pip install oasis-ai camel-ai") @@ -1120,6 +1125,33 @@ def create_model(config: Dict[str, Any], use_boost: bool = False): ) +def configure_agent_memory_limits(agent_graph, token_limit=150000, message_window_size=25): + """ + Cấu hình giới hạn memory cho tất cả agent trong agent_graph. + + OASIS tạo SocialAgent không truyền message_window_size hay token_limit + cho ChatAgent (CAMEL), khiến conversation history tăng vô hạn qua các round. + Khi context vượt quá giới hạn model (131072 tokens cho Qwen3.6-27B-FP8), + LLM API trả về BadRequestError và agent bị bỏ qua round đó. + + Hàm này thay thế memory của mỗi agent bằng ChatHistoryMemory có: + - token_limit: giới hạn token context (ScoreBasedContextCreator sẽ cắt bớt + message cũ khi vượt, ưu tiên giữ message mới và system message) + - message_window_size: giới hạn số message giữ lại (tầng bảo vệ thứ hai) + + ChatAgent.memory setter tự động gọi init_messages() để giữ system message. + """ + configured_count = 0 + for agent_id, agent in agent_graph.get_agents(): + token_counter = OpenAITokenCounter(ModelType.GPT_4O_MINI) + context_creator = ScoreBasedContextCreator(token_counter, token_limit=token_limit) + new_memory = ChatHistoryMemory(context_creator, window_size=message_window_size) + agent.memory = new_memory + configured_count += 1 + + return configured_count + + def get_active_agents_for_round( env, config: Dict[str, Any], @@ -1277,6 +1309,10 @@ async def run_twitter_simulation( available_actions=TWITTER_ACTIONS, ) + # Cấu hình giới hạn memory để tránh context overflow (131072 token limit) + mem_count = configure_agent_memory_limits(result.agent_graph) + log_info(f"Configured memory limits for {mem_count} agents") + # Xây dựng agent_names map — dùng cho log và enrich context agent_names = get_agent_names_from_config(config) for agent_id, agent in result.agent_graph.get_agents(): @@ -1289,11 +1325,19 @@ async def run_twitter_simulation( if os.path.exists(db_path): os.remove(db_path) + twitter_channel = Channel() + twitter_platform = Platform( + db_path=db_path, + channel=twitter_channel, + recsys_type="reddit", # score-based, không load model embedding → nhanh hơn twhin-bert + refresh_rec_post_count=2, + max_rec_post_len=2, + following_post_count=3, + ) result.env = oasis.make( agent_graph=result.agent_graph, - platform=oasis.DefaultPlatformType.TWITTER, - database_path=db_path, - semaphore=3, # Tối đa 3 LLM call đồng thời trong cùng 1 round + platform=twitter_platform, + semaphore=20, ) await result.env.reset() @@ -1471,6 +1515,10 @@ async def run_reddit_simulation( available_actions=REDDIT_ACTIONS, ) + # Cấu hình giới hạn memory để tránh context overflow (131072 token limit) + mem_count = configure_agent_memory_limits(result.agent_graph) + log_info(f"Configured memory limits for {mem_count} agents") + agent_names = get_agent_names_from_config(config) for agent_id, agent in result.agent_graph.get_agents(): if agent_id not in agent_names: @@ -1484,7 +1532,7 @@ async def run_reddit_simulation( agent_graph=result.agent_graph, platform=oasis.DefaultPlatformType.REDDIT, database_path=db_path, - semaphore=3, + semaphore=20, ) await result.env.reset()