AUXteam commited on
Commit
6a2a662
·
verified ·
1 Parent(s): 9bc10b9

Feat: Enable real LLM querying inside TinyTroupe simulation loops

Browse files
backend/services/tinytroupe_manager.py CHANGED
@@ -2,6 +2,7 @@ import concurrent.futures
2
  import time
3
  import os
4
  import json
 
5
  import logging
6
  from typing import List, Dict, Any
7
  import tinytroupe
@@ -35,10 +36,6 @@ class TinyTroupeSimulationManager:
35
 
36
  # 2. Generate missing personas via TinyTroupe LLM call
37
  if missing_count > 0:
38
- # Setting config to point to Helmholtz endpoint. This is a bit of a hack as tinytroupe
39
- # expects an INI file. In the previous implementation, the config file `tinytroupe/config.ini` was updated.
40
- # Assuming the config correctly set to alias-large as per memory.
41
-
42
  try:
43
  factory = TinyPersonFactory(business_description)
44
  for i in range(missing_count):
@@ -71,7 +68,6 @@ class TinyTroupeSimulationManager:
71
  # Push new personas
72
  if new_personas:
73
  from backend.services.git_sync import git_sync
74
- # background_push can be slow, might want to spawn another thread but for now it's fine in this executor
75
  git_sync.background_push(commit_message=f"Added {len(new_personas)} new personas for job {job_id}")
76
 
77
  job_registry.update_job(
@@ -92,12 +88,10 @@ class TinyTroupeSimulationManager:
92
  # Instantiate TinyPersons
93
  persons = []
94
  for p_data in personas_data:
95
- # We mock creating a TinyPerson from JSON data here.
96
- # TinyPerson has a specific load_json method or init signature.
97
- # For this implementation we'll instantiate them directly or use a mock.
98
  try:
99
  p = TinyPerson(name=p_data.get("name", "Unknown"))
100
- p._persona = p_data
 
101
  persons.append(p)
102
  except Exception as e:
103
  logger.error(f"Failed to load person data: {e}")
@@ -112,30 +106,55 @@ class TinyTroupeSimulationManager:
112
  def process_person(person: TinyPerson, index: int):
113
  # Prompt the persona with the content
114
  try:
115
- prompt = f"Please read this {format_type}: '{content_text}'. Rate its impact, attention, and relevance from 0 to 100, and provide a comment."
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
- # Instead of actually calling LLM which could block or fail during tests,
118
- # we do a mock interaction, or if connected, a real one.
119
- # person.listen_and_act(prompt)
120
- # response = person.pop_actions_and_get_contents_for("TALK", False)
121
 
122
- # For stability on Hugging Face spaces without a paid API key, use simulated response:
123
- time.sleep(1) # simulate think time
124
 
125
- simulated_response = {
 
126
  "name": person.name,
127
- "impact_score": 85,
128
- "attention": 90,
129
- "relevance": 88,
130
- "comment": f"As someone interested in {person._persona.get('occupation', 'this topic')}, I found this very engaging."
131
  }
132
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  # Update progress
134
  current_prog = job_registry.get_job(job_id).get("progress_percentage", 10)
135
  progress_increment = 80 // len(persons)
136
  job_registry.update_job(job_id, progress_percentage=current_prog + progress_increment)
137
 
138
- return simulated_response
139
 
140
  except Exception as e:
141
  logger.error(f"Person {person.name} failed to process: {e}")
 
2
  import time
3
  import os
4
  import json
5
+ import re
6
  import logging
7
  from typing import List, Dict, Any
8
  import tinytroupe
 
36
 
37
  # 2. Generate missing personas via TinyTroupe LLM call
38
  if missing_count > 0:
 
 
 
 
39
  try:
40
  factory = TinyPersonFactory(business_description)
41
  for i in range(missing_count):
 
68
  # Push new personas
69
  if new_personas:
70
  from backend.services.git_sync import git_sync
 
71
  git_sync.background_push(commit_message=f"Added {len(new_personas)} new personas for job {job_id}")
72
 
73
  job_registry.update_job(
 
88
  # Instantiate TinyPersons
89
  persons = []
90
  for p_data in personas_data:
 
 
 
91
  try:
92
  p = TinyPerson(name=p_data.get("name", "Unknown"))
93
+ # Make sure TinyPerson uses the loaded dictionary for the _persona structure
94
+ p._persona = p_data
95
  persons.append(p)
96
  except Exception as e:
97
  logger.error(f"Failed to load person data: {e}")
 
106
  def process_person(person: TinyPerson, index: int):
107
  # Prompt the persona with the content
108
  try:
109
+ # Instruct the persona to reply strictly in a JSON block
110
+ prompt = (
111
+ f"Please read this {format_type}:\n\n'{content_text}'\n\n"
112
+ f"Based on your persona and interests, rate its impact, attention, and relevance from 0 to 100, "
113
+ f"and provide a short comment analyzing it.\n"
114
+ f"Respond strictly with a JSON block in the following format:\n"
115
+ f"{{\n"
116
+ f" \"impact_score\": 85,\n"
117
+ f" \"attention\": 90,\n"
118
+ f" \"relevance\": 88,\n"
119
+ f" \"comment\": \"Your detailed comment here.\"\n"
120
+ f"}}"
121
+ )
122
 
123
+ person.listen_and_act(prompt)
124
+ response_texts = person.pop_actions_and_get_contents_for("TALK", False)
 
 
125
 
126
+ # Ensure we have a string
127
+ full_text = " ".join(response_texts) if isinstance(response_texts, list) else str(response_texts)
128
 
129
+ # Fallback default
130
+ parsed_response = {
131
  "name": person.name,
132
+ "impact_score": 50,
133
+ "attention": 50,
134
+ "relevance": 50,
135
+ "comment": full_text[:200] + "..." if len(full_text) > 200 else full_text
136
  }
137
+
138
+ # Attempt to extract JSON block
139
+ json_match = re.search(r"\{.*\}", full_text, re.DOTALL)
140
+ if json_match:
141
+ try:
142
+ extracted_data = json.loads(json_match.group(0))
143
+ parsed_response.update({
144
+ "impact_score": extracted_data.get("impact_score", 50),
145
+ "attention": extracted_data.get("attention", 50),
146
+ "relevance": extracted_data.get("relevance", 50),
147
+ "comment": extracted_data.get("comment", parsed_response["comment"])
148
+ })
149
+ except json.JSONDecodeError:
150
+ logger.warning(f"Failed to decode JSON from {person.name}'s response: {full_text}")
151
+
152
  # Update progress
153
  current_prog = job_registry.get_job(job_id).get("progress_percentage", 10)
154
  progress_increment = 80 // len(persons)
155
  job_registry.update_job(job_id, progress_percentage=current_prog + progress_increment)
156
 
157
+ return parsed_response
158
 
159
  except Exception as e:
160
  logger.error(f"Person {person.name} failed to process: {e}")