Coverage for apps / ai / migrations / 0009_fix_discover_prompts.py: 59%

27 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-11 00:40 +0000

1"""Fix discover prompts to return arrays instead of single objects. 

2 

3The validator expects arrays of 1-5 items, but the prompts were instructing 

4the AI to return a single object. This caused validation failures and 

5"No suggestions yet" on the Discover tab. 

6 

7Fixes QA-057. 

8""" 

9 

10from django.db import migrations 

11 

12 

13# New prompts that request arrays of 3-5 suggestions 

14DISCOVER_SEASONAL_PROMPT = '''You are a culinary calendar expert. 

15Based on the current date and season, suggest 3-5 appropriate recipes. 

16 

17Always respond with valid JSON as an array of 3-5 suggestions: 

18[ 

19 {"search_query": "specific seasonal dish", "title": "Suggestion Title", "description": "Why this is perfect for the season"}, 

20 ... 

21] 

22 

23Consider: 

24- Current season and weather 

25- Upcoming holidays within the next 2 weeks 

26- Seasonal ingredient availability 

27- Traditional dishes for the time of year 

28 

29Provide varied suggestions (different cuisines, dish types, or occasions). 

30 

31IMPORTANT: Respond with ONLY the JSON array, no additional text.''' 

32 

33DISCOVER_FAVORITES_PROMPT = '''You are a culinary recommendation engine. 

34Based on a user's recipe history, suggest 3-5 new recipes they might enjoy. 

35 

36Always respond with valid JSON as an array of 3-5 suggestions: 

37[ 

38 {"search_query": "specific dish name", "title": "Suggestion Title", "description": "Why they might enjoy this"}, 

39 ... 

40] 

41 

42The search_query should be specific dish names or cuisine types matching their preferences. 

43Provide varied suggestions based on different aspects of their history. 

44Keep descriptions concise (1-2 sentences). 

45 

46IMPORTANT: Respond with ONLY the JSON array, no additional text.''' 

47 

48DISCOVER_NEW_PROMPT = '''You are a culinary adventure guide. 

49Based on a user's cooking history, suggest 3-5 new and different dishes they haven't tried. 

50 

51Always respond with valid JSON as an array of 3-5 suggestions: 

52[ 

53 {"search_query": "specific dish from different cuisine", "title": "Adventure Title", "description": "Why this would be a fun culinary adventure"}, 

54 ... 

55] 

56 

57Suggest dishes that: 

58- Are from cuisines they haven't explored 

59- Use techniques they might not have tried 

60- Introduce new flavors while remaining accessible 

61- Are achievable for a home cook 

62 

63Provide varied adventures (different cuisines, techniques, or flavor profiles). 

64 

65IMPORTANT: Respond with ONLY the JSON array, no additional text.''' 

66 

67 

68# Original prompts for rollback 

69ORIGINAL_DISCOVER_SEASONAL = '''You are a culinary calendar expert. 

70Based on the current date and season, suggest an appropriate recipe. 

71 

72Always respond with valid JSON in this exact format: 

73{ 

74 "search_query": "specific seasonal dish or recipe name", 

75 "title": "Seasonal Suggestion Title", 

76 "description": "Brief explanation of why this is perfect for the season" 

77} 

78 

79Consider: 

80- Current season and weather 

81- Upcoming holidays within the next 2 weeks 

82- Seasonal ingredient availability 

83- Traditional dishes for the time of year 

84 

85IMPORTANT: Respond with ONLY the JSON, no additional text, explanation, or commentary.''' 

86 

87ORIGINAL_DISCOVER_FAVORITES = '''You are a culinary recommendation engine. 

88Based on a user's favorite recipes, suggest a new recipe they might enjoy. 

89 

90Always respond with valid JSON in this exact format: 

91{ 

92 "search_query": "specific search query to find similar recipes", 

93 "title": "Suggested Recipe Category", 

94 "description": "Brief explanation of why this suggestion fits their taste" 

95} 

96 

97The search_query should be a specific dish name or cuisine type that matches their preferences. 

98Keep descriptions concise (1-2 sentences). 

99 

100IMPORTANT: Respond with ONLY the JSON, no additional text, explanation, or commentary.''' 

101 

102ORIGINAL_DISCOVER_NEW = '''You are a culinary adventure guide. 

103Based on a user's cooking history, suggest something new and different they haven't tried. 

104 

105Always respond with valid JSON in this exact format: 

106{ 

107 "search_query": "specific dish from a different cuisine or technique", 

108 "title": "Adventure Suggestion Title", 

109 "description": "Brief explanation of why this would be a fun culinary adventure" 

110} 

111 

112Suggest dishes that: 

113- Are from cuisines they haven't explored 

114- Use techniques they might not have tried 

115- Introduce new flavors while remaining accessible 

116- Are achievable for a home cook 

117 

118IMPORTANT: Respond with ONLY the JSON, no additional text, explanation, or commentary.''' 

119 

120 

121def update_discover_prompts(apps, schema_editor): 

122 """Update discover prompts to request arrays of 3-5 suggestions.""" 

123 AIPrompt = apps.get_model('ai', 'AIPrompt') 

124 

125 prompts_to_update = [ 

126 ('discover_seasonal', DISCOVER_SEASONAL_PROMPT), 

127 ('discover_favorites', DISCOVER_FAVORITES_PROMPT), 

128 ('discover_new', DISCOVER_NEW_PROMPT), 

129 ] 

130 

131 for prompt_type, new_prompt in prompts_to_update: 

132 try: 

133 prompt = AIPrompt.objects.get(prompt_type=prompt_type) 

134 prompt.system_prompt = new_prompt 

135 prompt.save() 

136 except AIPrompt.DoesNotExist: 

137 pass 

138 

139 

140def reverse_update(apps, schema_editor): 

141 """Revert to original single-object prompts.""" 

142 AIPrompt = apps.get_model('ai', 'AIPrompt') 

143 

144 prompts_to_revert = [ 

145 ('discover_seasonal', ORIGINAL_DISCOVER_SEASONAL), 

146 ('discover_favorites', ORIGINAL_DISCOVER_FAVORITES), 

147 ('discover_new', ORIGINAL_DISCOVER_NEW), 

148 ] 

149 

150 for prompt_type, original_prompt in prompts_to_revert: 

151 try: 

152 prompt = AIPrompt.objects.get(prompt_type=prompt_type) 

153 prompt.system_prompt = original_prompt 

154 prompt.save() 

155 except AIPrompt.DoesNotExist: 

156 pass 

157 

158 

159class Migration(migrations.Migration): 

160 

161 dependencies = [ 

162 ('ai', '0008_update_serving_adjustment_indivisible'), 

163 ] 

164 

165 operations = [ 

166 migrations.RunPython(update_discover_prompts, reverse_update), 

167 ] 

← Back to Dashboard