JeCabrera commited on
Commit
3b22c40
·
verified ·
1 Parent(s): 47be5c6

Upload 13 files

Browse files
Files changed (8) hide show
  1. .gitattributes +36 -36
  2. .streamlit/config.toml +7 -7
  3. LICENSE +201 -201
  4. app.py +316 -279
  5. reels_formulas.py +102 -0
  6. requirements.txt +3 -3
  7. session_state.py +10 -1
  8. system_prompts.py +120 -90
.gitattributes CHANGED
@@ -1,36 +1,36 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
36
- docs/gemini-chatbot.gif filter=lfs diff=lfs merge=lfs -text
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ docs/gemini-chatbot.gif filter=lfs diff=lfs merge=lfs -text
.streamlit/config.toml CHANGED
@@ -1,7 +1,7 @@
1
- [theme]
2
- primaryColor = "#4ECDC4" # Color turquesa similar al del logo
3
- backgroundColor = "#1A1A1A" # Fondo oscuro para resaltar los elementos
4
- secondaryBackgroundColor = "#252A34" # Gris oscuro para paneles
5
- textColor = "#FFFFFF" # Texto blanco para mejor contraste
6
- font = "sans serif"
7
- # 335095
 
1
+ [theme]
2
+ primaryColor = "#4ECDC4" # Color turquesa similar al del logo
3
+ backgroundColor = "#1A1A1A" # Fondo oscuro para resaltar los elementos
4
+ secondaryBackgroundColor = "#252A34" # Gris oscuro para paneles
5
+ textColor = "#FFFFFF" # Texto blanco para mejor contraste
6
+ font = "sans serif"
7
+ # 335095
LICENSE CHANGED
@@ -1,201 +1,201 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but
32
- not limited to compiled object code, generated documentation,
33
- and conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work
38
- (an example is provided in the Appendix below).
39
-
40
- "Derivative Works" shall mean any work, whether in Source or Object
41
- form, that is based on (or derived from) the Work and for which the
42
- editorial revisions, annotations, elaborations, or other modifications
43
- represent, as a whole, an original work of authorship. For the purposes
44
- of this License, Derivative Works shall not include works that remain
45
- separable from, or merely link (or bind by name) to the interfaces of,
46
- the Work and Derivative Works thereof.
47
-
48
- "Contribution" shall mean any work of authorship, including
49
- the original version of the Work and any modifications or additions
50
- to that Work or Derivative Works thereof, that is intentionally
51
- submitted to Licensor for inclusion in the Work by the copyright owner
52
- or by an individual or Legal Entity authorized to submit on behalf of
53
- the copyright owner. For the purposes of this definition, "submitted"
54
- means any form of electronic, verbal, or written communication sent
55
- to the Licensor or its representatives, including but not limited to
56
- communication on electronic mailing lists, source code control systems,
57
- and issue tracking systems that are managed by, or on behalf of, the
58
- Licensor for the purpose of discussing and improving the Work, but
59
- excluding communication that is conspicuously marked or otherwise
60
- designated in writing by the copyright owner as "Not a Contribution."
61
-
62
- "Contributor" shall mean Licensor and any individual or Legal Entity
63
- on behalf of whom a Contribution has been received by Licensor and
64
- subsequently incorporated within the Work.
65
-
66
- 2. Grant of Copyright License. Subject to the terms and conditions of
67
- this License, each Contributor hereby grants to You a perpetual,
68
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
- copyright license to reproduce, prepare Derivative Works of,
70
- publicly display, publicly perform, sublicense, and distribute the
71
- Work and such Derivative Works in Source or Object form.
72
-
73
- 3. Grant of Patent License. Subject to the terms and conditions of
74
- this License, each Contributor hereby grants to You a perpetual,
75
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
- (except as stated in this section) patent license to make, have made,
77
- use, offer to sell, sell, import, and otherwise transfer the Work,
78
- where such license applies only to those patent claims licensable
79
- by such Contributor that are necessarily infringed by their
80
- Contribution(s) alone or by combination of their Contribution(s)
81
- with the Work to which such Contribution(s) was submitted. If You
82
- institute patent litigation against any entity (including a
83
- cross-claim or counterclaim in a lawsuit) alleging that the Work
84
- or a Contribution incorporated within the Work constitutes direct
85
- or contributory patent infringement, then any patent licenses
86
- granted to You under this License for that Work shall terminate
87
- as of the date such litigation is filed.
88
-
89
- 4. Redistribution. You may reproduce and distribute copies of the
90
- Work or Derivative Works thereof in any medium, with or without
91
- modifications, and in Source or Object form, provided that You
92
- meet the following conditions:
93
-
94
- (a) You must give any other recipients of the Work or
95
- Derivative Works a copy of this License; and
96
-
97
- (b) You must cause any modified files to carry prominent notices
98
- stating that You changed the files; and
99
-
100
- (c) You must retain, in the Source form of any Derivative Works
101
- that You distribute, all copyright, patent, trademark, and
102
- attribution notices from the Source form of the Work,
103
- excluding those notices that do not pertain to any part of
104
- the Derivative Works; and
105
-
106
- (d) If the Work includes a "NOTICE" text file as part of its
107
- distribution, then any Derivative Works that You distribute must
108
- include a readable copy of the attribution notices contained
109
- within such NOTICE file, excluding those notices that do not
110
- pertain to any part of the Derivative Works, in at least one
111
- of the following places: within a NOTICE text file distributed
112
- as part of the Derivative Works; within the Source form or
113
- documentation, if provided along with the Derivative Works; or,
114
- within a display generated by the Derivative Works, if and
115
- wherever such third-party notices normally appear. The contents
116
- of the NOTICE file are for informational purposes only and
117
- do not modify the License. You may add Your own attribution
118
- notices within Derivative Works that You distribute, alongside
119
- or as an addendum to the NOTICE text from the Work, provided
120
- that such additional attribution notices cannot be construed
121
- as modifying the License.
122
-
123
- You may add Your own copyright statement to Your modifications and
124
- may provide additional or different license terms and conditions
125
- for use, reproduction, or distribution of Your modifications, or
126
- for any such Derivative Works as a whole, provided Your use,
127
- reproduction, and distribution of the Work otherwise complies with
128
- the conditions stated in this License.
129
-
130
- 5. Submission of Contributions. Unless You explicitly state otherwise,
131
- any Contribution intentionally submitted for inclusion in the Work
132
- by You to the Licensor shall be under the terms and conditions of
133
- this License, without any additional terms or conditions.
134
- Notwithstanding the above, nothing herein shall supersede or modify
135
- the terms of any separate license agreement you may have executed
136
- with Licensor regarding such Contributions.
137
-
138
- 6. Trademarks. This License does not grant permission to use the trade
139
- names, trademarks, service marks, or product names of the Licensor,
140
- except as required for reasonable and customary use in describing the
141
- origin of the Work and reproducing the content of the NOTICE file.
142
-
143
- 7. Disclaimer of Warranty. Unless required by applicable law or
144
- agreed to in writing, Licensor provides the Work (and each
145
- Contributor provides its Contributions) on an "AS IS" BASIS,
146
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
- implied, including, without limitation, any warranties or conditions
148
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
- PARTICULAR PURPOSE. You are solely responsible for determining the
150
- appropriateness of using or redistributing the Work and assume any
151
- risks associated with Your exercise of permissions under this License.
152
-
153
- 8. Limitation of Liability. In no event and under no legal theory,
154
- whether in tort (including negligence), contract, or otherwise,
155
- unless required by applicable law (such as deliberate and grossly
156
- negligent acts) or agreed to in writing, shall any Contributor be
157
- liable to You for damages, including any direct, indirect, special,
158
- incidental, or consequential damages of any character arising as a
159
- result of this License or out of the use or inability to use the
160
- Work (including but not limited to damages for loss of goodwill,
161
- work stoppage, computer failure or malfunction, or any and all
162
- other commercial damages or losses), even if such Contributor
163
- has been advised of the possibility of such damages.
164
-
165
- 9. Accepting Warranty or Additional Liability. While redistributing
166
- the Work or Derivative Works thereof, You may choose to offer,
167
- and charge a fee for, acceptance of support, warranty, indemnity,
168
- or other liability obligations and/or rights consistent with this
169
- License. However, in accepting such obligations, You may act only
170
- on Your own behalf and on Your sole responsibility, not on behalf
171
- of any other Contributor, and only if You agree to indemnify,
172
- defend, and hold each Contributor harmless for any liability
173
- incurred by, or claims asserted against, such Contributor by reason
174
- of your accepting any such warranty or additional liability.
175
-
176
- END OF TERMS AND CONDITIONS
177
-
178
- APPENDIX: How to apply the Apache License to your work.
179
-
180
- To apply the Apache License to your work, attach the following
181
- boilerplate notice, with the fields enclosed by brackets "[]"
182
- replaced with your own identifying information. (Don't include
183
- the brackets!) The text should be enclosed in the appropriate
184
- comment syntax for the file format. We also recommend that a
185
- file or class name and description of purpose be included on the
186
- same "printed page" as the copyright notice for easier
187
- identification within third-party archives.
188
-
189
- Copyright [yyyy] [name of copyright owner]
190
-
191
- Licensed under the Apache License, Version 2.0 (the "License");
192
- you may not use this file except in compliance with the License.
193
- You may obtain a copy of the License at
194
-
195
- http://www.apache.org/licenses/LICENSE-2.0
196
-
197
- Unless required by applicable law or agreed to in writing, software
198
- distributed under the License is distributed on an "AS IS" BASIS,
199
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
- See the License for the specific language governing permissions and
201
- limitations under the License.
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
app.py CHANGED
@@ -1,279 +1,316 @@
1
- import time
2
- import os
3
- import joblib
4
- import streamlit as st
5
- import google.generativeai as genai
6
- from dotenv import load_dotenv
7
- from puv_formulas import puv_formulas
8
- from system_prompts import get_unified_puv_prompt
9
- from session_state import SessionState
10
-
11
- # Inicializar el estado de la sesión
12
- state = SessionState()
13
-
14
- # Función para detectar saludos y generar respuestas personalizadas
15
- def is_greeting(text):
16
- """Detecta si el texto es un saludo simple"""
17
- text = text.lower().strip()
18
- greetings = ['hola', 'hey', 'saludos', 'buenos días', 'buenas tardes', 'buenas noches', 'hi', 'hello']
19
-
20
- # Solo considerar como saludo si es el primer mensaje del usuario
21
- # y es un saludo simple
22
- is_simple_greeting = any(greeting in text for greeting in greetings) and len(text.split()) < 4
23
- return is_simple_greeting and len(state.messages) == 0
24
-
25
- # Función para procesar mensajes (unifica la lógica de procesamiento)
26
- def process_message(prompt, is_example=False):
27
- """Procesa un mensaje del usuario, ya sea directo o de un ejemplo"""
28
- handle_chat_title(prompt)
29
-
30
- with st.chat_message('user', avatar=USER_AVATAR_ICON):
31
- st.markdown(prompt)
32
-
33
- state.add_message('user', prompt, USER_AVATAR_ICON)
34
-
35
- # Obtener el prompt mejorado primero
36
- enhanced_prompt = get_enhanced_prompt(prompt, is_example)
37
-
38
- # Mover la respuesta del modelo después del mensaje del usuario
39
- with st.chat_message(MODEL_ROLE, avatar=AI_AVATAR_ICON):
40
- try:
41
- message_placeholder = st.empty()
42
- typing_indicator = st.empty()
43
- typing_indicator.markdown("*Generando respuesta...*")
44
-
45
- response = state.send_message(enhanced_prompt)
46
- full_response = stream_response(response, message_placeholder, typing_indicator)
47
-
48
- if full_response:
49
- state.add_message(MODEL_ROLE, full_response, AI_AVATAR_ICON)
50
- state.gemini_history = state.chat.history
51
- state.save_chat_history()
52
-
53
- except Exception as e:
54
- st.error(f"Error en el streaming: {str(e)}")
55
- return
56
-
57
- def handle_chat_title(prompt):
58
- """Maneja la lógica del título del chat"""
59
- if state.chat_id not in past_chats:
60
- temp_title = f'SesiónChat-{state.chat_id}'
61
- generated_title = state.generate_chat_title(prompt)
62
- state.chat_title = generated_title or temp_title
63
- past_chats[state.chat_id] = state.chat_title
64
- else:
65
- state.chat_title = past_chats[state.chat_id]
66
- joblib.dump(past_chats, 'data/past_chats_list')
67
-
68
- def get_enhanced_prompt(prompt, is_example):
69
- """Genera el prompt mejorado según el tipo de mensaje"""
70
- if is_greeting(prompt):
71
- return f"El usuario te ha saludado con '{prompt}'. Preséntate brevemente, explica qué es una PUV en 1-2 líneas, y haz 1-2 preguntas iniciales para comenzar a crear la PUV del usuario (como a quién se dirige su producto/servicio o qué ofrece). Sé amigable, breve y toma la iniciativa como el experto que eres."
72
- elif is_example:
73
- return f"El usuario ha seleccionado un ejemplo: '{prompt}'. Responde de manera conversacional y sencilla, como si estuvieras hablando con un amigo. Evita tecnicismos innecesarios. Enfócate en dar información práctica que ayude al usuario a crear su PUV. Usa ejemplos concretos cuando sea posible. Termina tu respuesta con una pregunta que invite al usuario a compartir información sobre su negocio para poder ayudarle a crear su PUV personalizada."
74
- return prompt
75
-
76
- def process_model_response(enhanced_prompt):
77
- """Procesa la respuesta del modelo"""
78
- with st.chat_message(MODEL_ROLE, avatar=AI_AVATAR_ICON):
79
- try:
80
- message_placeholder = st.empty()
81
- typing_indicator = st.empty()
82
- typing_indicator.markdown("*Generando respuesta...*")
83
-
84
- response = state.send_message(enhanced_prompt)
85
- full_response = stream_response(response, message_placeholder, typing_indicator)
86
-
87
- # Actualizar historial
88
- state.add_message(role=MODEL_ROLE, content=full_response, avatar=AI_AVATAR_ICON)
89
- state.gemini_history = state.chat.history
90
- state.save_chat_history()
91
-
92
- except Exception as e:
93
- st.error(f"Error: {str(e)}")
94
-
95
- def stream_response(response, message_placeholder, typing_indicator):
96
- """Maneja el streaming de la respuesta"""
97
- full_response = ''
98
- try:
99
- for chunk in response:
100
- if chunk.text:
101
- for ch in chunk.text:
102
- full_response += ch
103
- time.sleep(0.01)
104
- typing_indicator.markdown("*Generando respuesta...*")
105
- message_placeholder.markdown(full_response + '▌')
106
- except Exception as e:
107
- st.error(f"Error en el streaming: {str(e)}")
108
- return ''
109
-
110
- typing_indicator.empty()
111
- message_placeholder.markdown(full_response)
112
- return full_response
113
-
114
- # Función para cargar CSS personalizado
115
- def load_css(file_path):
116
- with open(file_path) as f:
117
- st.markdown(f'<style>{f.read()}</style>', unsafe_allow_html=True)
118
-
119
- # Intentar cargar el CSS personalizado con ruta absoluta para mayor seguridad
120
- try:
121
- css_path = os.path.join(os.path.dirname(__file__), 'static', 'css', 'style.css')
122
- load_css(css_path)
123
- except Exception as e:
124
- print(f"Error al cargar CSS: {e}")
125
- # Si el archivo no existe, crear un estilo básico en línea
126
- st.markdown("""
127
- <style>
128
- .robocopy-title {
129
- color: white !important;
130
- font-weight: bold;
131
- font-size: clamp(2.5em, 5vw, 4em);
132
- line-height: 1.2;
133
- }
134
- </style>
135
- """, unsafe_allow_html=True)
136
-
137
- # Función de utilidad para mostrar la carátula inicial
138
- def display_initial_header():
139
- col1, col2, col3 = st.columns([1, 2, 1])
140
- with col2:
141
- # Centrar la imagen
142
- st.markdown("""
143
- <style>
144
- div.stImage {
145
- text-align: center;
146
- display: block;
147
- margin-left: auto;
148
- margin-right: auto;
149
- }
150
- </style>
151
- """, unsafe_allow_html=True)
152
- st.image("robocopy_logo.png", width=300, use_container_width=True)
153
-
154
- # Título con diseño responsivo (eliminado el símbolo ∞)
155
- st.markdown("""
156
- <div style='text-align: center; margin-top: -35px; width: 100%;'>
157
- <h1 class='robocopy-title' style='width: 100%; text-align: center; color: white !important; font-size: clamp(2.5em, 5vw, 4em); line-height: 1.2;'>PUV Creator</h1>
158
- </div>
159
- """, unsafe_allow_html=True)
160
-
161
- # Subtítulo con margen superior ajustado a -30px
162
- st.markdown("""
163
- <div style='text-align: center; width: 100%;'>
164
- <p style='font-size: 16px; color: white; width: 100%; text-align: center; margin-top: -20px;'>By Jesús Cabrera</p>
165
- </div>
166
- """, unsafe_allow_html=True)
167
-
168
- # Descripción con fondo eliminado y margen superior ajustado a -20px
169
- st.markdown("""
170
- <div style='text-align: center; width: 100%;'>
171
- <p style='font-size: 16px; background-color: transparent; padding: 12px; border-radius: 8px; margin-top: -20px; color: white; width: 100%; text-align: center;'>
172
- 🎯 Experto en crear Propuestas de Valor Únicas que convierten audiencia en clientes
173
- </p>
174
- </div>
175
- """, unsafe_allow_html=True)
176
-
177
- # Función para mostrar ejemplos de preguntas
178
- def display_examples():
179
- ejemplos = [
180
- {"texto": "¿Qué es una Propuesta de Valor Única? 🎯", "prompt": "Explícame qué es una Propuesta de Valor Única (PUV) y por qué es importante para mi negocio"},
181
- {"texto": "¿Cómo puedo crear mi PUV? 📝", "prompt": "Guíame paso a paso en el proceso de crear una Propuesta de Valor Única efectiva"},
182
- {"texto": "¿Qué elementos debe tener mi PUV? ✨", "prompt": "¿Cuáles son los elementos esenciales que debe incluir una Propuesta de Valor Única exitosa?"},
183
- {"texto": "¿Cuál es la mejor fórmula para mi caso? 🤔", "prompt": "Ayúdame a elegir la fórmula más adecuada para mi Propuesta de Valor según mi tipo de negocio"}
184
- ]
185
-
186
- # Crear los botones de ejemplo
187
- cols = st.columns(4)
188
- for idx, ejemplo in enumerate(ejemplos):
189
- with cols[idx]:
190
- if st.button(ejemplo["texto"], key=f"ejemplo_{idx}", help=ejemplo["prompt"]):
191
- state.prompt = ejemplo["prompt"]
192
- st.rerun()
193
-
194
- # Cargar variables de entorno
195
- load_dotenv()
196
- GOOGLE_API_KEY=os.environ.get('GOOGLE_API_KEY')
197
- genai.configure(api_key=GOOGLE_API_KEY)
198
-
199
- # Configuración de la aplicación
200
- new_chat_id = f'{time.time()}'
201
- MODEL_ROLE = 'ai'
202
- AI_AVATAR_ICON = '🤖' # Cambia el emoji por uno de robot para coincidir con tu logo
203
- USER_AVATAR_ICON = '👤' # Añade un avatar para el usuario
204
-
205
- # Crear carpeta de datos si no existe
206
- try:
207
- os.mkdir('data/')
208
- except:
209
- # data/ folder already exists
210
- pass
211
-
212
- # Cargar chats anteriores
213
- try:
214
- past_chats: dict = joblib.load('data/past_chats_list')
215
- except:
216
- past_chats = {}
217
-
218
- # Sidebar para seleccionar chats anteriores
219
- with st.sidebar:
220
- st.write('# Chats Anteriores')
221
- if state.chat_id is None:
222
- state.chat_id = st.selectbox(
223
- label='Selecciona un chat anterior',
224
- options=[new_chat_id] + list(past_chats.keys()),
225
- format_func=lambda x: past_chats.get(x, 'Nuevo Chat'),
226
- placeholder='_',
227
- )
228
- else:
229
- # This will happen the first time AI response comes in
230
- state.chat_id = st.selectbox(
231
- label='Selecciona un chat anterior',
232
- options=[new_chat_id, state.chat_id] + list(past_chats.keys()),
233
- index=1,
234
- format_func=lambda x: past_chats.get(x, 'Nuevo Chat' if x != state.chat_id else state.chat_title),
235
- placeholder='_',
236
- )
237
- # Save new chats after a message has been sent to AI
238
- state.chat_title = f'SesiónChat-{state.chat_id}'
239
-
240
- # Cargar historial del chat
241
- state.load_chat_history()
242
-
243
- # Inicializar el modelo y el chat
244
- state.initialize_model('gemini-2.0-flash')
245
- state.initialize_chat() # Siempre inicializar el chat después del modelo
246
-
247
- # Mostrar mensajes del historial
248
- for message in state.messages:
249
- with st.chat_message(
250
- name=message['role'],
251
- avatar=message.get('avatar'),
252
- ):
253
- st.markdown(message['content'])
254
-
255
- # Mensaje inicial del sistema si es un chat nuevo
256
- if not state.has_messages():
257
- # Mostrar la carátula inicial con el logo centrado
258
- display_initial_header()
259
-
260
- # Mostrar los ejemplos
261
- display_examples()
262
-
263
- # Inicializar el chat con el prompt unificado
264
- system_prompt = get_unified_puv_prompt()
265
- if state.chat is not None: # Verificación adicional de seguridad
266
- state.chat.send_message(system_prompt)
267
- else:
268
- st.error("Error: No se pudo inicializar el chat correctamente.")
269
-
270
- # Procesar entrada del usuario
271
- if prompt := st.chat_input('Describe tu producto/servicio y audiencia objetivo...'):
272
- process_message(prompt, is_example=False)
273
-
274
- # Procesar ejemplos seleccionados
275
- if state.has_prompt():
276
- prompt = state.prompt
277
- process_message(prompt, is_example=True)
278
- # Limpiar el prompt
279
- state.clear_prompt()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import os
3
+ import joblib
4
+ import streamlit as st
5
+ import google.generativeai as genai
6
+ from dotenv import load_dotenv
7
+ from reels_formulas import reels_formulas
8
+ from system_prompts import get_reels_script_prompt
9
+ from session_state import SessionState
10
+
11
+ # Configuración de la página - DEBE SER LA PRIMERA LLAMADA A STREAMLIT
12
+ st.set_page_config(
13
+ page_title="RoboCopy - Reels Creator",
14
+ page_icon="🎬",
15
+ layout="wide",
16
+ initial_sidebar_state="expanded"
17
+ )
18
+
19
+ # Inicializar el estado de la sesión
20
+ state = SessionState()
21
+
22
+ # Función para detectar saludos y generar respuestas personalizadas
23
+ def is_greeting(text):
24
+ """Detecta si el texto es un saludo simple"""
25
+ text = text.lower().strip()
26
+ greetings = ['hola', 'hey', 'saludos', 'buenos días', 'buenas tardes', 'buenas noches', 'hi', 'hello']
27
+
28
+ # Solo considerar como saludo si es el primer mensaje del usuario
29
+ # y es un saludo simple
30
+ is_simple_greeting = any(greeting in text for greeting in greetings) and len(text.split()) < 4
31
+ return is_simple_greeting and len(state.messages) == 0
32
+
33
+ # Función para procesar mensajes (unifica la lógica de procesamiento)
34
+ def process_message(prompt, is_example=False):
35
+ """Procesa un mensaje del usuario, ya sea directo o de un ejemplo"""
36
+ handle_chat_title(prompt)
37
+
38
+ with st.chat_message('user', avatar=USER_AVATAR_ICON):
39
+ st.markdown(prompt)
40
+
41
+ state.add_message('user', prompt, USER_AVATAR_ICON)
42
+
43
+ # Obtener el prompt mejorado primero
44
+ enhanced_prompt = get_enhanced_prompt(prompt, is_example)
45
+
46
+ # Mover la respuesta del modelo después del mensaje del usuario
47
+ with st.chat_message(MODEL_ROLE, avatar=AI_AVATAR_ICON):
48
+ try:
49
+ message_placeholder = st.empty()
50
+ typing_indicator = st.empty()
51
+ typing_indicator.markdown("*Generando respuesta...*")
52
+
53
+ response = state.send_message(enhanced_prompt)
54
+ full_response = stream_response(response, message_placeholder, typing_indicator)
55
+
56
+ if full_response:
57
+ state.add_message(MODEL_ROLE, full_response, AI_AVATAR_ICON)
58
+ state.gemini_history = state.chat.history
59
+ state.save_chat_history()
60
+
61
+ except Exception as e:
62
+ st.error(f"Error en el streaming: {str(e)}")
63
+ return
64
+
65
+ def handle_chat_title(prompt):
66
+ """Maneja la lógica del título del chat"""
67
+ if state.chat_id not in past_chats:
68
+ temp_title = f'SesiónChat-{state.chat_id}'
69
+ generated_title = state.generate_chat_title(prompt)
70
+ state.chat_title = generated_title or temp_title
71
+ past_chats[state.chat_id] = state.chat_title
72
+ else:
73
+ state.chat_title = past_chats[state.chat_id]
74
+ joblib.dump(past_chats, 'data/past_chats_list')
75
+
76
+ def get_enhanced_prompt(prompt, is_example):
77
+ """Genera el prompt mejorado según el tipo de mensaje"""
78
+ # Importar las preguntas directamente desde system_prompts.py
79
+ from system_prompts import get_discovery_questions
80
+
81
+ # Obtener la lista de preguntas
82
+ discovery_questions = get_discovery_questions()
83
+
84
+ if is_greeting(prompt):
85
+ return f"El usuario te ha saludado con '{prompt}'. Preséntate brevemente (máximo 2 líneas), explica qué es un guion de Reel en 1 línea, y haz ÚNICAMENTE esta pregunta: '{discovery_questions[0]}'. Recuerda hablar siempre en segunda persona, dirigiéndote al usuario. NUNCA hables en primera persona como si fueras tú quien crea el Reel."
86
+ elif is_example:
87
+ return f"El usuario ha seleccionado un ejemplo: '{prompt}'. Responde de manera breve y directa, y haz ÚNICAMENTE esta pregunta: '{discovery_questions[0]}'. Recuerda hablar siempre en segunda persona, dirigiéndote al usuario. NUNCA hables en primera persona como si fueras tú quien crea el Reel."
88
+ else:
89
+ # Analizar la respuesta del usuario para determinar qué pregunta hacer a continuación
90
+ if "audiencia" in prompt.lower() or "dirigido" in prompt.lower() or "público" in prompt.lower():
91
+ # Si el usuario respondió sobre la audiencia, hacer la segunda pregunta
92
+ return f"Gracias por esa información sobre tu audiencia. Ahora, {discovery_questions[1]}. Recuerda hablar siempre en segunda persona, dirigiéndote al usuario."
93
+ elif "producto" in prompt.lower() or "servicio" in prompt.lower() or "promocionar" in prompt.lower() or "ofreces" in prompt.lower():
94
+ # Si el usuario respondió sobre el producto/servicio, hacer la tercera pregunta
95
+ return f"Entendido. Ahora, {discovery_questions[2]}. Recuerda hablar siempre en segunda persona, dirigiéndote al usuario."
96
+ elif "problema" in prompt.lower() or "duda" in prompt.lower() or "gancho" in prompt.lower():
97
+ # Si el usuario respondió sobre el problema/duda, hacer la cuarta pregunta
98
+ return f"Perfecto. Por último, {discovery_questions[3]}. Recuerda hablar siempre en segunda persona, dirigiéndote al usuario."
99
+ elif "acción" in prompt.lower() or "cta" in prompt.lower() or "comprar" in prompt.lower() or "registrarse" in prompt.lower() or "seguir" in prompt.lower():
100
+ # Si el usuario respondió sobre la acción/CTA, proceder a la creación del guion
101
+ system_prompt = get_reels_script_prompt()
102
+ return f"Gracias por toda la información proporcionada. Ahora vamos a crear un guion de Reel efectivo basado en tus respuestas. Recuerda hablar siempre en segunda persona, dirigiéndote al usuario. NUNCA hables en primera persona como si fueras tú quien crea el Reel. {system_prompt}"
103
+ else:
104
+ # Si no se puede determinar en qué parte del proceso estamos, hacer la primera pregunta
105
+ return f"Para crear un guion de Reel efectivo, necesito hacerte algunas preguntas clave. Empecemos: {discovery_questions[0]}. Recuerda hablar siempre en segunda persona, dirigiéndote al usuario."
106
+ return prompt
107
+
108
+ def process_model_response(enhanced_prompt):
109
+ """Procesa la respuesta del modelo"""
110
+ with st.chat_message(MODEL_ROLE, avatar=AI_AVATAR_ICON):
111
+ try:
112
+ message_placeholder = st.empty()
113
+ typing_indicator = st.empty()
114
+ typing_indicator.markdown("*Generando respuesta...*")
115
+
116
+ response = state.send_message(enhanced_prompt)
117
+ full_response = stream_response(response, message_placeholder, typing_indicator)
118
+
119
+ # Actualizar historial
120
+ state.add_message(role=MODEL_ROLE, content=full_response, avatar=AI_AVATAR_ICON)
121
+ state.gemini_history = state.chat.history
122
+ state.save_chat_history()
123
+
124
+ except Exception as e:
125
+ st.error(f"Error: {str(e)}")
126
+
127
+ def stream_response(response, message_placeholder, typing_indicator):
128
+ """Maneja el streaming de la respuesta"""
129
+ full_response = ''
130
+ try:
131
+ for chunk in response:
132
+ if chunk.text:
133
+ for ch in chunk.text:
134
+ full_response += ch
135
+ time.sleep(0.01)
136
+ typing_indicator.markdown("*Generando respuesta...*")
137
+ message_placeholder.markdown(full_response + '▌')
138
+ except Exception as e:
139
+ st.error(f"Error en el streaming: {str(e)}")
140
+ return ''
141
+
142
+ typing_indicator.empty()
143
+ message_placeholder.markdown(full_response)
144
+ return full_response
145
+
146
+ # Función para cargar CSS personalizado
147
+ def load_css(file_path):
148
+ with open(file_path) as f:
149
+ st.markdown(f'<style>{f.read()}</style>', unsafe_allow_html=True)
150
+
151
+ # Intentar cargar el CSS personalizado con ruta absoluta para mayor seguridad
152
+ try:
153
+ css_path = os.path.join(os.path.dirname(__file__), 'static', 'css', 'style.css')
154
+ load_css(css_path)
155
+ except Exception as e:
156
+ print(f"Error al cargar CSS: {e}")
157
+ # Si el archivo no existe, crear un estilo básico en línea
158
+ st.markdown("""
159
+ <style>
160
+ .robocopy-title {
161
+ color: white !important;
162
+ font-weight: bold;
163
+ font-size: clamp(2.5em, 5vw, 4em);
164
+ line-height: 1.2;
165
+ }
166
+ </style>
167
+ """, unsafe_allow_html=True)
168
+
169
+ # Función de utilidad para mostrar la carátula inicial
170
+ def display_initial_header():
171
+ col1, col2, col3 = st.columns([1, 2, 1])
172
+ with col2:
173
+ # Centrar la imagen
174
+ st.markdown("""
175
+ <style>
176
+ div.stImage {
177
+ text-align: center;
178
+ display: block;
179
+ margin-left: auto;
180
+ margin-right: auto;
181
+ }
182
+ </style>
183
+ """, unsafe_allow_html=True)
184
+ st.image("robocopy_logo.png", width=300, use_container_width=True)
185
+
186
+ # Título con diseño responsivo
187
+ st.markdown("""
188
+ <div style='text-align: center; margin-top: -35px; width: 100%;'>
189
+ <h1 class='robocopy-title' style='width: 100%; text-align: center; color: white !important; font-size: clamp(2.5em, 5vw, 4em); line-height: 1.2;'>Reels Creator</h1>
190
+ </div>
191
+ """, unsafe_allow_html=True)
192
+
193
+ # Subtítulo con margen superior ajustado a -30px
194
+ st.markdown("""
195
+ <div style='text-align: center; width: 100%;'>
196
+ <p style='font-size: 16px; color: white; width: 100%; text-align: center; margin-top: -20px;'>By Jesús Cabrera</p>
197
+ </div>
198
+ """, unsafe_allow_html=True)
199
+
200
+ # Descripción con fondo eliminado y margen superior ajustado a -20px
201
+ st.markdown("""
202
+ <div style='text-align: center; width: 100%;'>
203
+ <p style='font-size: 16px; background-color: transparent; padding: 12px; border-radius: 8px; margin-top: -20px; color: white; width: 100%; text-align: center;'>
204
+ 🎬 Experto en crear guiones de Reels virales para Instagram y Facebook
205
+ </p>
206
+ </div>
207
+ """, unsafe_allow_html=True)
208
+
209
+ # Función para mostrar ejemplos de preguntas
210
+ def display_examples():
211
+ ejemplos = [
212
+ {"texto": "¿Qué es un Reel efectivo? 🎬", "prompt": "Explícame qué es un Reel efectivo y por qué es importante para mi estrategia de redes sociales"},
213
+ {"texto": "¿Cómo puedo crear mi guion de Reel? 📝", "prompt": "Guíame paso a paso en el proceso de crear un guion de Reel efectivo"},
214
+ {"texto": "¿Qué elementos debe tener mi Reel? ✨", "prompt": "¿Cuáles son los elementos esenciales que debe incluir un Reel exitoso?"},
215
+ {"texto": "¿Cuál es la mejor fórmula para mi caso? 🤔", "prompt": "Ayúdame a elegir la fórmula más adecuada para mi guion de Reel según mi nicho"}
216
+ ]
217
+
218
+ # Crear los botones de ejemplo
219
+ cols = st.columns(4)
220
+ for idx, ejemplo in enumerate(ejemplos):
221
+ with cols[idx]:
222
+ if st.button(ejemplo["texto"], key=f"ejemplo_{idx}", help=ejemplo["prompt"]):
223
+ state.prompt = ejemplo["prompt"]
224
+ st.rerun()
225
+
226
+ # Cargar variables de entorno
227
+ load_dotenv()
228
+ GOOGLE_API_KEY=os.environ.get('GOOGLE_API_KEY')
229
+ genai.configure(api_key=GOOGLE_API_KEY)
230
+
231
+ # Configuración de la aplicación
232
+ new_chat_id = f'{time.time()}'
233
+ MODEL_ROLE = 'model'
234
+ USER_AVATAR_ICON = '👤'
235
+ AI_AVATAR_ICON = '🤖'
236
+
237
+ # Crear directorio de datos si no existe
238
+ os.makedirs('data', exist_ok=True)
239
+
240
+ # Cargar historial de chats pasados
241
+ try:
242
+ past_chats = joblib.load('data/past_chats_list')
243
+ except:
244
+ past_chats = {}
245
+
246
+ # Inicializar el sistema de prompt
247
+ system_prompt = get_reels_script_prompt()
248
+
249
+ # Inicializar el modelo si no está inicializado
250
+ if state.model is None:
251
+ state.initialize_model('gemini-2.0-flash') # Especificar la versión del modelo
252
+ state.initialize_chat()
253
+
254
+ # Sidebar para navegación y opciones
255
+ with st.sidebar:
256
+ st.markdown("## 🎬 RoboCopy - Reels Creator")
257
+ st.markdown("---")
258
+
259
+ # Botón para nueva conversación
260
+ if st.button("🆕 Nueva Conversación", use_container_width=True):
261
+ state.chat_id = new_chat_id
262
+ state.messages = []
263
+ state.gemini_history = []
264
+ state.initialize_chat()
265
+ st.rerun()
266
+
267
+ # Selector de chats pasados
268
+ st.markdown("### 💬 Conversaciones Pasadas")
269
+
270
+ # Mostrar chats pasados en orden inverso (más recientes primero)
271
+ past_chat_ids = list(past_chats.keys())
272
+ past_chat_ids.sort(reverse=True)
273
+
274
+ for chat_id in past_chat_ids:
275
+ chat_title = past_chats[chat_id]
276
+ if st.button(f"📝 {chat_title}", key=f"chat_{chat_id}", use_container_width=True):
277
+ state.chat_id = chat_id
278
+ state.load_chat_history(chat_id)
279
+ state.initialize_chat(state.gemini_history)
280
+ st.rerun()
281
+
282
+ # Información adicional
283
+ st.markdown("---")
284
+ st.markdown("### ℹ️ Información")
285
+ st.markdown("""
286
+ **RoboCopy - Reels Creator** te ayuda a crear guiones efectivos para tus Reels de Instagram y Facebook.
287
+
288
+ Simplemente describe tu nicho, audiencia y objetivo, y te ayudaremos a crear un guion optimizado para generar engagement.
289
+ """)
290
+
291
+ # Contenido principal
292
+ if state.chat_id is None:
293
+ state.chat_id = new_chat_id
294
+
295
+ # Mostrar la carátula inicial
296
+ display_initial_header()
297
+
298
+ # Mostrar ejemplos de preguntas
299
+ st.markdown("### 💡 Ejemplos de preguntas para comenzar:")
300
+ display_examples()
301
+
302
+ # Mostrar historial de mensajes
303
+ for message in state.messages:
304
+ with st.chat_message(message["role"], avatar=message.get("avatar")):
305
+ st.markdown(message["content"])
306
+
307
+ # Procesar el prompt si existe
308
+ if state.has_prompt():
309
+ prompt = state.prompt
310
+ state.clear_prompt()
311
+ process_message(prompt, is_example=True)
312
+
313
+ # Input para nuevo mensaje
314
+ user_input = st.chat_input("Escribe tu mensaje aquí...")
315
+ if user_input:
316
+ process_message(user_input)
reels_formulas.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ reels_formulas = {
2
+ "Hook-Resolution Formula": {
3
+ "description": """
4
+ The Hook-Resolution Formula creates highly effective reels that capture attention and offer real value:
5
+
6
+ 7-step structure:
7
+ 1. Hook in the form of an initial question
8
+ - Start the reel with a question that captures the viewer's attention
9
+ - Must be relevant to your niche
10
+ - Focus on a specific problem your audience faces
11
+
12
+ 2. First resolution, easy and concrete
13
+ - Offer a quick and simple answer to the problem posed
14
+ - Provide an accessible initial solution
15
+ - Keep the explanation brief but valuable
16
+
17
+ 3. Repeat the question in the form of an affirmation
18
+ - Reformulate the initial question as an affirmation
19
+ - Reinforce the problem you're addressing
20
+ - Create an emotional connection with the viewer
21
+
22
+ 4. Second more complex resolution
23
+ - Develop the answer with more details
24
+ - Offer specific advice and elaborate solutions
25
+ - Provide information that demonstrates your expertise
26
+
27
+ 5. Affirm another related problem
28
+ - Mention a problem related to the main topic
29
+ - Expand the scope of the reel
30
+ - Provide even more value
31
+
32
+ 6. Final resolution of your initial question
33
+ - Summarize the answers you've given
34
+ - Reaffirm the solution to the problem posed
35
+ - Make it clear how you can help
36
+
37
+ 7. Make your call to action
38
+ - Invite the viewer to interact
39
+ - Suggest visiting your store, following you on social media, or taking a specific action
40
+ - Close with a clear value proposition
41
+ """,
42
+ "examples": [
43
+ {
44
+ "nicho": "Maquillaje",
45
+ "problema": "Base de maquillaje que se cuartea",
46
+ "script": """
47
+ "¿Cansada de que tu base se vea acartonada o cuarteada a las pocas horas?"
48
+
49
+ "La hidratación es clave! Prepara tu piel antes del maquillaje para que luzca radiante."
50
+
51
+ "Sí, sabemos que el maquillaje que se cuartea es un problema común."
52
+
53
+ "Además de la hidratación, asegúrate de usar productos compatibles con tu tipo de piel y aplica las cantidades correctas. Evita sobrecargar las zonas grasosas."
54
+
55
+ "Y si además no estás usando la brocha o esponja adecuada, eso también puede influir en el acabado final."
56
+
57
+ "Así que ya sabes: hidratación adecuada, productos compatibles y aplicación correcta. ¡Dile adiós al maquillaje cuarteado y hola a una piel impecable!"
58
+
59
+ "¡Visítanos en nuestra tienda para encontrar los productos ideales para tu piel y recibir asesoramiento personalizado! ¡Te esperamos!"
60
+ """
61
+ },
62
+ {
63
+ "nicho": "Fitness",
64
+ "problema": "Dificultad para perder grasa abdominal",
65
+ "script": """
66
+ "¿Frustrado/a porque haces mil abdominales y la grasa de la barriga no desaparece?"
67
+
68
+ "El ejercicio localizado no quema grasa específica de esa zona. Necesitas un enfoque integral."
69
+
70
+ "Sí, entendemos que la grasa abdominal persistente es uno de los mayores desafíos fitness."
71
+
72
+ "Para realmente transformar tu abdomen, necesitas combinar entrenamiento de fuerza completo, cardio estratégico y, lo más importante, una alimentación adecuada con déficit calórico. El 80% de tus resultados vendrán de lo que comes."
73
+
74
+ "Y además, el estrés crónico y la falta de sueño pueden estar saboteando tus esfuerzos al aumentar el cortisol, que promueve el almacenamiento de grasa abdominal."
75
+
76
+ "Así que ya lo sabes: enfoque integral con entrenamiento completo, nutrición adecuada y manejo del estrés. ¡La transformación real va más allá de los abdominales!"
77
+
78
+ "¡Descarga mi guía completa de transformación corporal haciendo clic en el link de mi bio! Incluye plan alimenticio y rutinas específicas."
79
+ """
80
+ },
81
+ {
82
+ "nicho": "Marketing Digital",
83
+ "problema": "Bajo engagement en redes sociales",
84
+ "script": """
85
+ "¿Frustrado porque publicas constantemente pero tu engagement sigue por los suelos?"
86
+
87
+ "La consistencia es importante, pero el contenido relevante para tu audiencia es lo que realmente genera interacción."
88
+
89
+ "Sí, el bajo engagement es uno de los problemas más comunes y desmoralizantes en redes sociales."
90
+
91
+ "Para realmente aumentar tu engagement, necesitas entender profundamente a tu audiencia y crear contenido que resuelva sus problemas o les entretenga genuinamente. Además, es crucial analizar tus métricas para identificar qué tipo de contenido funciona mejor y a qué horas tu audiencia está más activa."
92
+
93
+ "Y si no estás utilizando llamados a la acción efectivos o no respondes a los comentarios rápidamente, también estás perdiendo oportunidades valiosas de interacción."
94
+
95
+ "Así que recuerda: contenido valioso enfocado en tu audiencia, análisis de métricas y participación activa. ¡El engagement no se trata de publicar más, sino de publicar mejor!"
96
+
97
+ "¡Inscríbete en mi taller gratuito de estrategia de contenido! Link en bio para reservar tu lugar ahora."
98
+ """
99
+ }
100
+ ]
101
+ }
102
+ }
requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
- google-generativeai>=0.7.0
2
- streamlit==1.29.0
3
- joblib==1.3.2
4
  python-dotenv
 
1
+ google-generativeai>=0.7.0
2
+ streamlit==1.29.0
3
+ joblib==1.3.2
4
  python-dotenv
session_state.py CHANGED
@@ -118,7 +118,16 @@ class SessionState:
118
  if self.model is None:
119
  self.initialize_model()
120
 
121
- # Inicializar el chat sin generation_config
 
 
 
 
 
 
 
 
 
122
  self.chat = self.model.start_chat(history=history)
123
 
124
  # Verificar que el chat se inicializó correctamente
 
118
  if self.model is None:
119
  self.initialize_model()
120
 
121
+ # Inicializar el chat con instrucciones específicas para hablar en segunda persona
122
+ system_instruction = """
123
+ IMPORTANTE: Siempre habla en segunda persona, dirigiéndote al usuario.
124
+ NUNCA hables en primera persona como si fueras tú quien crea el Reel.
125
+ Recuerda que estás ayudando al usuario a crear SU guion, no estás creando un guion para ti mismo.
126
+ NUNCA uses frases como "Mi audiencia objetivo", "Mi producto", "Mi servicio", etc.
127
+ En su lugar, usa "Tu audiencia objetivo", "Tu producto", "Tu servicio", etc.
128
+ """
129
+
130
+ # Inicializar el chat con las instrucciones
131
  self.chat = self.model.start_chat(history=history)
132
 
133
  # Verificar que el chat se inicializó correctamente
system_prompts.py CHANGED
@@ -1,132 +1,162 @@
1
  # Prompt unificado para RoboCopy
2
- from puv_formulas import puv_formulas
3
-
4
- def get_unified_puv_prompt():
5
- # Obtener las fórmulas disponibles
6
- formulas_disponibles = list(puv_formulas.keys())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  # Crear la lista de opciones para el usuario
9
  opciones_formulas = ""
10
- for i, formula in enumerate(formulas_disponibles, 1):
11
- # Extraer una breve descripción de cada fórmula
12
- if formula == "Fórmula Tradicional":
13
- descripcion = "Comienza con 'Yo ayudo a...' y destaca un punto de dolor específico."
14
- elif formula == "Fórmula Anti-tradicional":
15
- descripcion = "Usa aperturas como 'Yo transformo...' o 'Me especializo en...'"
16
- elif formula == "Contrato Imposible":
17
- descripcion = "Utiliza aperturas impactantes como estadísticas sorprendentes, preguntas retóricas o declaraciones disruptivas."
18
- elif formula == "Reto Ridículo":
19
- descripcion = "Comienza con una historia divertida relacionada con tu industria."
20
-
21
- opciones_formulas += f"{i}. {formula}: {descripcion}\n"
22
 
23
- # Añadir ejemplos específicos para cada fórmula
24
  ejemplos_formulas = ""
25
- for formula, datos in puv_formulas.items():
26
- if "examples" in datos and len(datos["examples"]) > 0:
27
- # Tomar el primer ejemplo de cada fórmula
28
- ejemplo = datos["examples"][0]
29
- ejemplos_formulas += f"\n**Ejemplo de {formula}:**\n"
30
- ejemplos_formulas += f"- Público: {ejemplo['target_audience']}\n"
31
- ejemplos_formulas += f"- Producto: {ejemplo['product_service']}\n"
32
- ejemplos_formulas += f"- PUV: \"{ejemplo['uvp']}\"\n"
33
 
34
- # Construir el prompt base
35
- prompt_base = f"""You are RoboCopy, a strategic and empathetic assistant whose sole mission is to help the user create a clear, specific, and emotionally relevant Unique Value Proposition (UVP) for their ideal customer. You represent a team trained by Gary Halbert, Gary Bencivenga, and David Ogilvy — experts in positioning, copywriting, consumer psychology, and differentiation.
36
- Your style is conversational, warm, and direct. You do not overwhelm the user with unnecessary questions — you only ask what's essential to write a compelling UVP.
37
- You have been trained in the principles of Gary Halbert (real, persuasive conversations), Gary Bencivenga (emotional precision and deep benefits), and David Ogilvy (crystal-clear positioning and benefit-driven messaging).
38
 
39
- IMPORTANTE: Todas tus respuestas deben ser en español. Siempre comunícate con el usuario en español y genera las Propuestas de Valor Únicas (PUV) en español.
40
 
41
  ---
42
 
43
- ### 🔍 1. DISCOVERY PHASE (Simplified Version)
44
-
45
- **Objective:** Get only what's strictly necessary to start.
46
 
47
- Ask these 3 questions, **one at a time**:
48
 
49
- 1. What do you do and what's your experience?
50
- 2. Who is your ideal customer and what problem do they have?
51
- 3. What product or service do you offer?
52
 
53
- Once these are answered, do not ask anything else unless clarity is missing. If everything is clear, proceed to internal analysis.
 
54
 
55
- ---
 
56
 
57
- ### 🧠 2. INTERNAL RAPID ANALYSIS
 
58
 
59
- IMPORTANT: This analysis is for INTERNAL USE ONLY. NEVER share these points with the user or mention you are doing this. UNDER NO CIRCUMSTANCES should you show the result of this analysis, not even as a "summary" or "reminder." Just use your conclusions to write better UVPs.
60
 
61
- Internally analyze the following:
 
62
 
63
- 1. TARGET AUDIENCE ANALYSIS Pain Points:
64
- - What specific frustrations does this audience experience?
65
- - What are their biggest daily challenges?
66
- - What emotional problems do they face?
67
- - What have they tried before that didn't work?
68
- - What's stopping them from achieving their goals?
69
 
70
- 2. PRODUCT/SERVICE ANALYSIS – Benefits:
71
- - What tangible results do clients get?
72
- - What specific transformation does it offer?
73
- - What's the unique method or differentiator?
74
- - What competitive advantages does it have?
75
- - What emotional benefits does it provide?
 
 
 
 
76
 
77
  ---
78
 
79
- ### 🧪 3. UVP CREATION
80
 
81
- Durante nuestra conversación, recopilaré la siguiente información:
82
- INFORMACIÓN DEL NEGOCIO:
83
- Producto/Servicio: [Preguntaré esto durante nuestra conversación]
84
- Audiencia Objetivo: [Preguntaré esto durante nuestra conversión]
85
- A que se dedica, años de experiencia: [Preguntaré esto durante nuestra conversión]
86
 
87
- Basado en esta información, te sugeriré un tipo de fórmula de las siguientes opciones:
88
- {opciones_formulas}
 
 
 
89
 
90
- Aquí tienes ejemplos reales de cada fórmula para inspirarte:
91
- {ejemplos_formulas}
 
 
 
92
 
93
- IMPORTANTE: Cuando el usuario te pida crear una PUV, debes preguntarle qué fórmula prefiere usar de las opciones anteriores. Si el usuario no especifica una fórmula, debes sugerirle la más adecuada según su caso y usar esa fórmula para crear las PUVs.
94
 
95
- EXAMPLE TO FOLLOW:
96
 
97
- Based on your internal analysis of the pain points and product benefits (do not output the analysis), create UVPs following the structure provided in the formula selected by the user or suggested by you.
98
 
99
- CRITICAL INSTRUCTIONS:
100
- - Each UVP must be specific and measurable
101
- - Focus on the transformation journey
102
- - Use natural, conversational language
103
- - Avoid generic phrases and buzzwords
104
- - Output ONLY the UVPs — nothing else
105
 
106
- If the user does not specify the number of UVPs to generate, default to 3.
107
- IMPORTANTE: Presenta las 3 versiones de PUV ÚNICAMENTE con numeración (1., 2., 3.), sin etiquetas descriptivas como "Enfocada en la transformación:" o "Enfocada en el diferenciador:". No incluyas explicaciones adicionales, comentarios sobre su estructura ni justificaciones. Simplemente muestra las 3 PUVs numeradas, una tras otra, sin texto explicativo antes, durante o después de cada una.
108
 
109
- Por ejemplo, así:
110
 
111
- 1. "Primera PUV completa aquí."
112
 
113
- 2. "Segunda PUV completa aquí."
114
 
115
- 3. "Tercera PUV completa aquí."
116
 
117
- ---
 
 
 
118
 
119
- ### 📏 4. VALIDACIÓN FINAL
120
 
121
- Antes de entregarla, asegúrate de que:
122
 
123
- - Tiene un dolor claro.
124
- - Promete una transformación concreta y deseable.
125
- - Tiene un diferenciador real, no genérico.
126
- - Es fácil de entender y recordar.
 
127
 
128
- NO uses emojis, signos innecesarios ni adornos. Manténlo profesional, humano y directo.
129
  """
130
-
131
- return prompt_base
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # Prompt unificado para RoboCopy
2
+ from reels_formulas import reels_formulas
3
+
4
+ def get_discovery_questions():
5
+ """
6
+ Devuelve la lista de preguntas para la fase de descubrimiento del Reel.
7
+ """
8
+ return [
9
+ "¿A quién va dirigido específicamente tu Reel? (Define tu audiencia objetivo con detalles como edad, intereses, ocupación, etc.)",
10
+ "¿Qué producto o servicio quieres promocionar? (Describe brevemente qué ofreces)",
11
+ "¿Cuál es la duda o problema principal que tu audiencia tiene sobre este producto/servicio? (Esto será la base para el gancho inicial)",
12
+ "¿Qué acción específica quieres que realicen los espectadores después de ver tu Reel? (Comprar, registrarse, seguirte, etc.)"
13
+ ]
14
+
15
+ def get_formulas_options_and_examples(discovery_questions=None):
16
+ """
17
+ Procesa las fórmulas disponibles y genera opciones y ejemplos formatados.
18
+ """
19
+ # Si no se proporcionan preguntas, obtenerlas
20
+ if discovery_questions is None:
21
+ discovery_questions = get_discovery_questions()
22
+
23
+ formulas_disponibles = list(reels_formulas.keys())
24
 
25
  # Crear la lista de opciones para el usuario
26
  opciones_formulas = ""
27
+ for i, formula_nombre in enumerate(formulas_disponibles, 1):
28
+ formula_data = reels_formulas[formula_nombre]
29
+ descripcion_completa = formula_data.get("description", "Descripción no disponible.")
30
+ descripcion_breve = descripcion_completa.split('\n')[0].strip()
31
+ if not descripcion_breve and len(descripcion_completa.split('\n')) > 1:
32
+ descripcion_breve = descripcion_completa.split('\n')[1].strip()
33
+ opciones_formulas += f"{i}. {formula_nombre}: {descripcion_breve}\n"
 
 
 
 
 
34
 
35
+ # Añadir ejemplos específicos para cada fórmula de Reel
36
  ejemplos_formulas = ""
37
+ for formula_nombre, datos_formula in reels_formulas.items():
38
+ if "examples" in datos_formula and len(datos_formula["examples"]) > 0:
39
+ ejemplo = datos_formula["examples"][0]
40
+ ejemplos_formulas += f"\n**Ejemplo de Guion con {formula_nombre}:**\n"
41
+ ejemplos_formulas += f"- Nicho: {ejemplo.get('nicho', 'No especificado')}\n"
42
+ ejemplos_formulas += f"- Problema/Tema: {ejemplo.get('problema', 'No especificado')}\n"
43
+ ejemplos_formulas += f"- Guion Ejemplo:\n```\n{ejemplo.get('script', 'No disponible')}\n```\n"
 
44
 
45
+ # Construir el prompt para RoboCopy
46
+ return f"""Eres RoboCopy, un asistente estratégico especializado en crear guiones virales para Reels de Instagram y Facebook. Tu misión es ayudar al usuario a crear guiones efectivos que generen engagement.
 
 
47
 
48
+ IMPORTANTE: Todas tus respuestas deben ser en español. Siempre comunícate con el usuario en español y genera los guiones para Reels en español.
49
 
50
  ---
51
 
52
+ ### 🎬 PROCESO DE CREACIÓN DE GUIONES PARA REELS
 
 
53
 
54
+ Tu objetivo es guiar al usuario a través de un proceso estructurado para crear guiones de Reels efectivos. Sigue estos pasos en orden:
55
 
56
+ 1. Cuando el usuario te pida ayuda con un Reel, haz ÚNICAMENTE la primera pregunta de la lista y espera su respuesta:
57
+ "{discovery_questions[0]}"
 
58
 
59
+ 2. Después de recibir la respuesta a la primera pregunta, haz ÚNICAMENTE la segunda pregunta:
60
+ "{discovery_questions[1]}"
61
 
62
+ 3. Después de recibir la respuesta a la segunda pregunta, haz ÚNICAMENTE la tercera pregunta:
63
+ "{discovery_questions[2]}"
64
 
65
+ 4. Después de recibir la respuesta a la tercera pregunta, haz ÚNICAMENTE la cuarta pregunta:
66
+ "{discovery_questions[3]}"
67
 
68
+ 5. Una vez que tengas todas las respuestas, sugiere 3-5 ideas de Reels específicas para el público objetivo definido por el usuario. Pregunta al usuario cuál de estas ideas le gusta más.
69
 
70
+ 6. Después de que el usuario elija una idea, pregúntale qué fórmula de guion prefiere usar de las siguientes opciones:
71
+ {opciones_formulas}
72
 
73
+ 7. Finalmente, crea un guion de Reel basado en la idea elegida y la fórmula seleccionada.
 
 
 
 
 
74
 
75
+ REGLAS IMPORTANTES:
76
+ - Haz SOLO UNA pregunta a la vez y espera la respuesta del usuario.
77
+ - No avances a la siguiente pregunta hasta que el usuario haya respondido la anterior.
78
+ - No expliques el proceso completo al usuario, simplemente guíalo paso a paso.
79
+ - Mantén tus respuestas breves y directas.
80
+ - Nunca muestres tu análisis interno al usuario.
81
+ - SIEMPRE habla en segunda persona, dirigiéndote al usuario. NUNCA hables en primera persona como si fueras tú quien crea el Reel.
82
+ - NUNCA uses frases como "Mi audiencia objetivo", "Mi producto", "Mi servicio", etc. En su lugar, usa "Tu audiencia objetivo", "Tu producto", "Tu servicio", etc.
83
+ - Recuerda que estás ayudando al usuario a crear SU guion, no estás creando un guion para ti mismo.
84
+ - Cuando hagas preguntas, hazlas directamente al usuario. Por ejemplo: "¿A quién va dirigido específicamente tu Reel?" en lugar de "Necesito saber a quién va dirigido este Reel".
85
 
86
  ---
87
 
88
+ ### 🧠 ANÁLISIS INTERNO (SOLO PARA TI, NUNCA MOSTRAR AL USUARIO)
89
 
90
+ Después de recopilar las respuestas a las cuatro preguntas, analiza internamente:
 
 
 
 
91
 
92
+ 1. ANÁLISIS DE LA AUDIENCIA DEL REEL:
93
+ - ¿Qué frustraciones específicas tiene esta audiencia?
94
+ - ¿Cuáles son sus aspiraciones o resultados deseados?
95
+ - ¿Qué emociones serían efectivas para evocar?
96
+ - ¿Qué tipo de contenido resonaría más con ellos?
97
 
98
+ 2. ANÁLISIS DEL CONTENIDO DEL REEL:
99
+ - ¿Cuál es el mensaje clave que debe transmitirse?
100
+ - ¿Qué gancho (hook) capturaría mejor la atención?
101
+ - ¿Qué elementos visuales potenciarían el mensaje?
102
+ - ¿Cuál es la llamada a la acción más efectiva?
103
 
104
+ ---
105
 
106
+ ### ✍️ CREACIÓN DEL GUIÓN DEL REEL
107
 
108
+ Basado en tu análisis interno (que nunca mostrarás al usuario), crea un guion de Reel que:
109
 
110
+ - Tenga un gancho potente en los primeros 3 segundos
111
+ - Aborde el problema o necesidad específica de la audiencia
112
+ - Entregue valor o entretenimiento de forma concisa
113
+ - Incluya una llamada a la acción clara
114
+ - Sea visualmente imaginable y adecuado para Reels
 
115
 
116
+ Si el usuario no indica cuántos guiones quiere, crea 3.
 
117
 
118
+ IMPORTANTE: Presenta los guiones SOLO con numeración (1., 2., 3.), sin explicaciones ni etiquetas.
119
 
120
+ Ejemplo de formato:
121
 
122
+ 1. [Texto completo del Reel aquí.]
123
 
124
+ 2. [Texto completo del Reel aquí.]
125
 
126
+ 3. [Texto completo del Reel aquí.]
127
+
128
+ Ejemplos de guiones para inspirarte:
129
+ {ejemplos_formulas}
130
 
131
+ ---
132
 
133
+ ### VALIDACIÓN FINAL
134
 
135
+ Antes de entregar, asegúrate de que el guión:
136
+ - Tiene un gancho claro al inicio.
137
+ - Muestra una transformación.
138
+ - Conecta con un dolor o deseo emocional.
139
+ - Termina con una acción específica o frase memorable.
140
 
141
+ NO uses emojis, signos innecesarios ni adornos. Mantén el guión humano, natural y directo.
142
  """
 
 
143
 
144
+ def get_reels_prompt():
145
+ """
146
+ Devuelve el prompt completo para la creación de guiones de Reels.
147
+ """
148
+ discovery_questions = get_discovery_questions()
149
+ return get_formulas_options_and_examples(discovery_questions)
150
+
151
+ # Mantener compatibilidad con código existente
152
+ def get_unified_reels_prompt():
153
+ """
154
+ Función de compatibilidad que devuelve el prompt de Reels.
155
+ """
156
+ return get_reels_prompt()
157
+
158
+ def get_reels_script_prompt():
159
+ """
160
+ Función de compatibilidad que devuelve el prompt de Reels.
161
+ """
162
+ return get_reels_prompt()