jmisak commited on
Commit
fbc9719
·
verified ·
1 Parent(s): 0f8b454

Upload 5 files

Browse files
Files changed (4) hide show
  1. CHANGELOG.md +10 -4
  2. README.md +12 -11
  3. llm_backend.py +4 -3
  4. survey_generator.py +62 -57
CHANGELOG.md CHANGED
@@ -10,7 +10,7 @@ All notable changes to ConversAI will be documented in this file.
10
  - **No API endpoint issues** - everything runs on your Space
11
  - **Faster after first load** - models cached in memory
12
  - **100% private** - all processing happens locally
13
- - Default model: **google/flan-t5-base** (250MB, very fast)
14
  - Supports all Flan-T5 variants (base, large, xl, xxl)
15
 
16
  ### Added
@@ -43,10 +43,16 @@ All notable changes to ConversAI will be documented in this file.
43
  - Added model caching to keep models in memory
44
  - Auto-detects CUDA/CPU and optimizes accordingly
45
 
46
- - **Default model**: `google/flan-t5-base` (line 83)
47
  - Changed from API-based to local transformers
48
- - Smaller model for faster loading
49
- - User can upgrade to larger models via LLM_MODEL env var
 
 
 
 
 
 
50
 
51
  - **New dependencies added** to requirements.txt:
52
  - transformers>=4.36.0
 
10
  - **No API endpoint issues** - everything runs on your Space
11
  - **Faster after first load** - models cached in memory
12
  - **100% private** - all processing happens locally
13
+ - Default model: **google/flan-t5-large** (1.2GB, good quality)
14
  - Supports all Flan-T5 variants (base, large, xl, xxl)
15
 
16
  ### Added
 
43
  - Added model caching to keep models in memory
44
  - Auto-detects CUDA/CPU and optimizes accordingly
45
 
46
+ - **Default model**: `google/flan-t5-large` (line 84)
47
  - Changed from API-based to local transformers
48
+ - 1.2GB model provides good balance of quality and speed
49
+ - Better at JSON generation than smaller models
50
+ - User can upgrade to xl/xxl or downgrade to base via LLM_MODEL env var
51
+
52
+ - **Improved prompts** in `survey_generator.py`:
53
+ - Simplified prompts for better T5 model compatibility
54
+ - Added fallback survey generation if JSON parsing fails
55
+ - More direct instructions with concrete examples
56
 
57
  - **New dependencies added** to requirements.txt:
58
  - transformers>=4.36.0
README.md CHANGED
@@ -57,9 +57,10 @@ Battle the blank page, reach global audiences, and uncover insights with AI assi
57
 
58
  **✨ Zero configuration needed!** ConversAI works out-of-the-box on HuggingFace Spaces using local model loading.
59
 
60
- **Default Model:** google/flan-t5-base
61
  - ✅ **100% Free** - No API keys, no costs, ever
62
- - ✅ **Fast** - Models load locally, typically 2-5 seconds per request after loading
 
63
  - ✅ **No API dependencies** - Runs entirely on your Space's compute
64
  - ✅ **Private** - All processing happens locally, nothing sent to external APIs
65
  - ✅ **Reliable** - Google's instruction-tuned model, battle-tested
@@ -77,9 +78,9 @@ You can try different free models by setting the `LLM_MODEL` environment variabl
77
 
78
  | Model | Best For | Speed | Quality | Model Size |
79
  |-------|----------|-------|---------|------------|
80
- | **google/flan-t5-base** (default) | Balanced - fast & small | ⚡⚡⚡ Very Fast | ⭐⭐ Good | 250MB |
81
- | **google/flan-t5-large** | Better quality | ⚡⚡ Fast | ⭐⭐⭐ Better | 1.2GB |
82
- | **google/flan-t5-xl** | Best quality | ⚡ Medium | ⭐⭐⭐⭐ Excellent | 3GB |
83
  | **google/flan-t5-xxl** | Maximum quality | ⚡ Slower | ⭐⭐⭐⭐⭐ Best | 11GB |
84
 
85
  **Note:** Flan-T5 models are Google's instruction-tuned models, specifically designed for following instructions. They run locally with transformers library.
@@ -102,12 +103,12 @@ LLM_MODEL=google/flan-t5-xl
102
 
103
  ### Tips for Best Performance with Local Models
104
 
105
- 1. **Start with flan-t5-base** - Fast loading and good results
106
- 2. **First load takes time** - Model downloads and loads (~1-2 minutes for base)
107
- 3. **Subsequent requests are fast** - Model stays in memory (2-5 seconds)
108
- 4. **Upgrade model size for quality** - flan-t5-large or xl for better results
109
- 5. **Keep prompts concise** - Shorter outlines = faster generation
110
- 6. **Monitor memory** - Larger models (XL, XXL) need more RAM
111
 
112
  ## 📦 Installation
113
 
 
57
 
58
  **✨ Zero configuration needed!** ConversAI works out-of-the-box on HuggingFace Spaces using local model loading.
59
 
60
+ **Default Model:** google/flan-t5-large
61
  - ✅ **100% Free** - No API keys, no costs, ever
62
+ - ✅ **Good quality** - 1.2GB model, excellent at following instructions
63
+ - ✅ **Fast after loading** - Typically 3-8 seconds per request after initial load
64
  - ✅ **No API dependencies** - Runs entirely on your Space's compute
65
  - ✅ **Private** - All processing happens locally, nothing sent to external APIs
66
  - ✅ **Reliable** - Google's instruction-tuned model, battle-tested
 
78
 
79
  | Model | Best For | Speed | Quality | Model Size |
80
  |-------|----------|-------|---------|------------|
81
+ | **google/flan-t5-base** | Testing - fastest | ⚡⚡⚡ Very Fast | ⭐⭐ Basic | 250MB |
82
+ | **google/flan-t5-large** (default) | **Recommended** - balanced | ⚡⚡ Fast | ⭐⭐⭐ Good | 1.2GB |
83
+ | **google/flan-t5-xl** | Better quality | ⚡ Medium | ⭐⭐⭐⭐ Excellent | 3GB |
84
  | **google/flan-t5-xxl** | Maximum quality | ⚡ Slower | ⭐⭐⭐⭐⭐ Best | 11GB |
85
 
86
  **Note:** Flan-T5 models are Google's instruction-tuned models, specifically designed for following instructions. They run locally with transformers library.
 
103
 
104
  ### Tips for Best Performance with Local Models
105
 
106
+ 1. **Default model (flan-t5-large) is recommended** - Good balance of quality and speed
107
+ 2. **First load takes time** - Model downloads and loads (~2-3 minutes for large)
108
+ 3. **Subsequent requests are fast** - Model stays in memory (3-8 seconds)
109
+ 4. **For simple testing** - Use flan-t5-base (faster loading)
110
+ 5. **For best quality** - Use flan-t5-xl or xxl (requires more memory)
111
+ 6. **Keep prompts clear** - Simpler outlines work better with smaller models
112
 
113
  ## 📦 Installation
114
 
llm_backend.py CHANGED
@@ -78,9 +78,10 @@ class LLMBackend:
78
  defaults = {
79
  LLMProvider.OPENAI: "gpt-4o-mini",
80
  LLMProvider.ANTHROPIC: "claude-3-5-sonnet-20241022",
81
- # Using Flan-T5-Base - small, fast, works locally with transformers
82
- # For larger models, try: google/flan-t5-large or google/flan-t5-xl
83
- LLMProvider.HUGGINGFACE: "google/flan-t5-base",
 
84
  LLMProvider.LM_STUDIO: "google/gemma-3-27b"
85
  }
86
  return os.getenv("LLM_MODEL", defaults[self.provider])
 
78
  defaults = {
79
  LLMProvider.OPENAI: "gpt-4o-mini",
80
  LLMProvider.ANTHROPIC: "claude-3-5-sonnet-20241022",
81
+ # Using Flan-T5-Large - good balance of size (1.2GB) and quality
82
+ # For smaller/faster: google/flan-t5-base (250MB)
83
+ # For better quality: google/flan-t5-xl (3GB) or google/flan-t5-xxl (11GB)
84
+ LLMProvider.HUGGINGFACE: "google/flan-t5-large",
85
  LLMProvider.LM_STUDIO: "google/gemma-3-27b"
86
  }
87
  return os.getenv("LLM_MODEL", defaults[self.provider])
survey_generator.py CHANGED
@@ -58,64 +58,22 @@ class SurveyGenerator:
58
 
59
  def _get_system_prompt(self) -> str:
60
  """System prompt for survey generation"""
61
- return """You are an expert survey designer and qualitative researcher with deep knowledge of:
62
- - Industry best practices for survey design
63
- - Question formulation techniques (open-ended, closed-ended, Likert scales)
64
- - Avoiding bias and leading questions
65
- - Survey flow and respondent experience
66
- - Research methodologies (interviews, focus groups, ethnographic studies)
67
-
68
- Your task is to generate professional, well-structured surveys that will yield high-quality research data.
69
- Follow these principles:
70
- 1. Use clear, unambiguous language
71
- 2. Avoid double-barreled questions
72
- 3. Include a logical flow from general to specific
73
- 4. Balance open-ended and structured questions appropriately
74
- 5. Consider the respondent's cognitive load
75
- 6. Include screening questions when relevant
76
- 7. Add instructions and context where helpful
77
-
78
- Always respond with valid JSON containing the survey structure."""
79
 
80
  def _build_generation_prompt(self, outline, survey_type, num_questions, target_audience) -> str:
81
  """Build the user prompt for survey generation"""
82
- return f"""Generate a professional {survey_type} survey based on the following outline:
83
-
84
- OUTLINE:
85
- {outline}
86
-
87
- REQUIREMENTS:
88
- - Target number of questions: {num_questions}
89
- - Target audience: {target_audience}
90
- - Survey type: {survey_type}
91
-
92
- Please generate a complete survey with:
93
- 1. A clear title
94
- 2. An introduction/welcome message
95
- 3. Well-crafted questions following best practices
96
- 4. Appropriate question types for the research goals
97
- 5. A thank you/closing message
98
-
99
- Respond with a JSON object in this exact format:
100
- {{
101
- "title": "Survey Title",
102
- "introduction": "Welcome message and instructions",
103
- "questions": [
104
- {{
105
- "id": 1,
106
- "question_text": "The question to ask",
107
- "question_type": "open_ended|multiple_choice|likert_scale|yes_no|rating",
108
- "options": ["option1", "option2"],
109
- "required": true|false,
110
- "help_text": "Optional clarification"
111
- }}
112
- ],
113
- "closing": "Thank you message"
114
- }}
115
-
116
- For open-ended questions, omit the "options" field.
117
- For multiple choice and Likert questions, include appropriate options.
118
- Ensure questions follow best practices and are unbiased."""
119
 
120
  def _parse_survey_response(self, response: str) -> Dict:
121
  """Parse LLM response into survey structure"""
@@ -132,6 +90,12 @@ Ensure questions follow best practices and are unbiased."""
132
  end = response.find("```", start)
133
  response = response[start:end].strip()
134
 
 
 
 
 
 
 
135
  try:
136
  survey_data = json.loads(response)
137
 
@@ -147,8 +111,49 @@ Ensure questions follow best practices and are unbiased."""
147
 
148
  return survey_data
149
 
150
- except json.JSONDecodeError as e:
151
- raise Exception(f"Failed to parse survey JSON: {str(e)}\nResponse: {response}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
  def refine_question(self, question: str, improvement_type: str = "clarity") -> str:
154
  """
 
58
 
59
  def _get_system_prompt(self) -> str:
60
  """System prompt for survey generation"""
61
+ return """You are a professional survey designer. Create surveys in valid JSON format only."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  def _build_generation_prompt(self, outline, survey_type, num_questions, target_audience) -> str:
64
  """Build the user prompt for survey generation"""
65
+ # For T5 models, we need a very simple, direct instruction
66
+ return f"""Task: Generate a JSON survey.
67
+
68
+ Topic: {outline}
69
+ Questions needed: {num_questions}
70
+ Audience: {target_audience}
71
+ Type: {survey_type}
72
+
73
+ Required JSON format:
74
+ {{"title": "Survey Title Here", "introduction": "Welcome message here", "questions": [{{"id": 1, "question_text": "Your first question?", "question_type": "open_ended", "required": true}}, {{"id": 2, "question_text": "Your second question?", "question_type": "open_ended", "required": true}}], "closing": "Thank you message here"}}
75
+
76
+ Generate the complete survey JSON now:"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  def _parse_survey_response(self, response: str) -> Dict:
79
  """Parse LLM response into survey structure"""
 
90
  end = response.find("```", start)
91
  response = response[start:end].strip()
92
 
93
+ # Try to find JSON object in response
94
+ if "{" in response and "}" in response:
95
+ start = response.find("{")
96
+ end = response.rfind("}") + 1
97
+ response = response[start:end]
98
+
99
  try:
100
  survey_data = json.loads(response)
101
 
 
111
 
112
  return survey_data
113
 
114
+ except (json.JSONDecodeError, ValueError) as e:
115
+ # Fallback: Try to create a simple survey from the response
116
+ print(f"Warning: JSON parsing failed, attempting fallback. Error: {e}")
117
+ return self._create_fallback_survey(response)
118
+
119
+ def _create_fallback_survey(self, response: str) -> Dict:
120
+ """Create a basic survey structure from non-JSON response"""
121
+ # Extract potential questions from numbered list
122
+ lines = [line.strip() for line in response.split('\n') if line.strip()]
123
+
124
+ # Look for numbered items or lines with question marks
125
+ questions = []
126
+ question_id = 1
127
+
128
+ for line in lines:
129
+ # Remove leading numbers, bullets, etc.
130
+ clean_line = line.lstrip('0123456789.-) ')
131
+
132
+ # Check if it looks like a question
133
+ if len(clean_line) > 10 and (clean_line.endswith('?') or
134
+ any(word in clean_line.lower() for word in ['what', 'how', 'why', 'when', 'where', 'which', 'would', 'could', 'should', 'do you'])):
135
+ questions.append({
136
+ "id": question_id,
137
+ "question_text": clean_line,
138
+ "question_type": "open_ended",
139
+ "required": True
140
+ })
141
+ question_id += 1
142
+
143
+ # If we didn't find enough questions, create generic ones
144
+ if len(questions) < 3:
145
+ questions = [
146
+ {"id": 1, "question_text": "What are your thoughts on this topic?", "question_type": "open_ended", "required": True},
147
+ {"id": 2, "question_text": "Can you describe your experience?", "question_type": "open_ended", "required": True},
148
+ {"id": 3, "question_text": "What suggestions do you have for improvement?", "question_type": "open_ended", "required": True}
149
+ ]
150
+
151
+ return {
152
+ "title": "Survey",
153
+ "introduction": "Thank you for participating in this survey. Please answer the following questions.",
154
+ "questions": questions[:10], # Limit to 10 questions
155
+ "closing": "Thank you for your time and feedback!"
156
+ }
157
 
158
  def refine_question(self, question: str, improvement_type: str = "clarity") -> str:
159
  """