Spaces:
Sleeping
Sleeping
Upload 13 files
Browse files- .gitattributes +36 -35
- .streamlit/config.toml +7 -0
- LICENSE +201 -0
- README.md +9 -18
- app.py +279 -0
- assets/robocopy_logo.png +0 -0
- docs/gemini-chatbot.gif +3 -0
- puv_formulas.py +184 -0
- requirements.txt +4 -3
- robocopy_logo.png +0 -0
- session_state.py +220 -0
- static/css/style.css +61 -0
- system_prompts.py +270 -0
.gitattributes
CHANGED
|
@@ -1,35 +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
|
|
|
|
|
|
| 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
ADDED
|
@@ -0,0 +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
|
LICENSE
ADDED
|
@@ -0,0 +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.
|
README.md
CHANGED
|
@@ -1,20 +1,11 @@
|
|
| 1 |
---
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
| 4 |
colorFrom: red
|
| 5 |
-
colorTo:
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
pinned: false
|
| 11 |
-
short_description: Streamlit template space
|
| 12 |
-
license: unknown
|
| 13 |
-
---
|
| 14 |
-
|
| 15 |
-
# Welcome to Streamlit!
|
| 16 |
-
|
| 17 |
-
Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
|
| 18 |
-
|
| 19 |
-
If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
|
| 20 |
-
forums](https://discuss.streamlit.io).
|
|
|
|
| 1 |
---
|
| 2 |
+
license: mit
|
| 3 |
+
title: Chatbot_Gemini_Streamlit
|
| 4 |
+
sdk: streamlit
|
| 5 |
+
emoji: 🏆
|
| 6 |
colorFrom: red
|
| 7 |
+
colorTo: yellow
|
| 8 |
+
pinned: true
|
| 9 |
+
sdk_version: 1.45.0
|
| 10 |
+
short_description: Transform your audience's thoughts into persuasive bullets
|
| 11 |
+
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.py
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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()
|
assets/robocopy_logo.png
ADDED
|
docs/gemini-chatbot.gif
ADDED
|
Git LFS Details
|
puv_formulas.py
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
puv_formulas = {
|
| 2 |
+
"Fórmula Tradicional": {
|
| 3 |
+
"description": """
|
| 4 |
+
The Traditional Formula creates a powerful UVP that focuses on four key objectives:
|
| 5 |
+
- Attracting your ideal client by highlighting specific characteristics and pain points
|
| 6 |
+
- Repelling non-ideal clients to ensure resource efficiency
|
| 7 |
+
- Explaining the promised transformation clearly
|
| 8 |
+
- Generating purchase commitment through value demonstration
|
| 9 |
+
- Clear avatar description with specific pain points
|
| 10 |
+
- Direct transformation promise
|
| 11 |
+
|
| 12 |
+
Structure:
|
| 13 |
+
1. Start with "Yo
|
| 14 |
+
ayudo a..." followed by:
|
| 15 |
+
[AVATAR DESCRIPTION]
|
| 16 |
+
- Demographics
|
| 17 |
+
- Current situation
|
| 18 |
+
- ONE main pain point (focus on the most important one)
|
| 19 |
+
- ONE specific characteristic
|
| 20 |
+
|
| 21 |
+
2. Then "a conseguir..." followed by:
|
| 22 |
+
[TRANSFORMATION]
|
| 23 |
+
- ONE clear outcome
|
| 24 |
+
- ONE specific benefit
|
| 25 |
+
- What they won't need to do
|
| 26 |
+
|
| 27 |
+
Key elements:
|
| 28 |
+
- Ultra-specific avatar description focusing on ONE pain point
|
| 29 |
+
- Clear transformation promise with ONE main benefit
|
| 30 |
+
- Natural client filtering
|
| 31 |
+
- Simple, direct language
|
| 32 |
+
- Be clear and concise
|
| 33 |
+
""",
|
| 34 |
+
"examples": [
|
| 35 |
+
{
|
| 36 |
+
"target_audience": "mujeres empresarias solteras con poco tiempo para el amor",
|
| 37 |
+
"product_service": "programa de citas y relaciones para ejecutivas",
|
| 38 |
+
"uvp": "Yo ayudo a mujeres empresarias solteras con poco tiempo para el amor, que se sienten atrapadas en su carrera y han tenido malas experiencias en el pasado, a conseguir una pareja compatible que respete su éxito y su tiempo, sin tener que perderse en citas frustrantes ni en relaciones que no aportan nada."
|
| 39 |
+
},
|
| 40 |
+
{
|
| 41 |
+
"target_audience": "fotógrafos principiantes abrumados por la tecnología",
|
| 42 |
+
"product_service": "curso de fotografía digital simplificada",
|
| 43 |
+
"uvp": "Yo ayudo a fotógrafos principiantes abrumados por los términos técnicos y configuraciones complejas, que se sienten frustrados al ver sus fotos salir borrosas o sobreexpuestas, a dominar su cámara y crear imágenes profesionales que impresionen a sus clientes, sin tener que memorizar manual tras manual ni invertir en equipos carísimos."
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"target_audience": "profesionales del bienestar estresados por el marketing",
|
| 47 |
+
"product_service": "sistema de atracción de clientes para terapeutas",
|
| 48 |
+
"uvp": "Yo ayudo a terapeutas y coaches holísticos que prefieren enfocarse en sanar a sus clientes en lugar de promocionarse, y que se sienten invócidos con las tácticas de marketing agresivas, a llenar su agenda con clientes ideales que valoran su trabajo, sin tener que convertirse en vendedores ni comprometer sus valores."
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"target_audience": "emprendedores creativos sin presencia digital",
|
| 52 |
+
"product_service": "programa de marca personal auténtica",
|
| 53 |
+
"uvp": "Yo ayudo a emprendedores creativos que tienen talento pero pasan desapercibidos en el mundo digital, que se sienten invisibles a pesar de su experiencia y pasión, a construir una marca personal magnética que atrae oportunidades y clientes de forma natural, sin tener que fingir ser alguien más ni seguir fórmulas genéricas de marketing."
|
| 54 |
+
}
|
| 55 |
+
]
|
| 56 |
+
},
|
| 57 |
+
"Fórmula Anti-tradicional": {
|
| 58 |
+
"description": """
|
| 59 |
+
The Anti-traditional Formula creates a clear and direct UVP that focuses on four key objectives:
|
| 60 |
+
- Attracting your ideal client by highlighting specific characteristics and pain points
|
| 61 |
+
- Repelling non-ideal clients to ensure resource efficiency
|
| 62 |
+
- Explaining the promised transformation clearly
|
| 63 |
+
- Generating purchase commitment through value demonstration
|
| 64 |
+
|
| 65 |
+
Structure:
|
| 66 |
+
1. Start with a powerful opener:
|
| 67 |
+
- "Yo transformo..."
|
| 68 |
+
- "Me especializo en..."
|
| 69 |
+
- "Soy experto/a en..."
|
| 70 |
+
- "Mi misión es..."
|
| 71 |
+
- "Potencio a..."
|
| 72 |
+
(Choose one and describe your avatar's situation with ONE main problem)
|
| 73 |
+
|
| 74 |
+
2. To achieve [PROMISED TRANSFORMATION]
|
| 75 |
+
(Explain ONE clear outcome simply and convincingly)
|
| 76 |
+
Key elements to include:
|
| 77 |
+
- Emotional appeal focused on ONE pain point
|
| 78 |
+
- Clear and direct language
|
| 79 |
+
- ONE main service highlight
|
| 80 |
+
- Natural filtering of non-ideal clients
|
| 81 |
+
- Be clear and concise
|
| 82 |
+
""",
|
| 83 |
+
"examples": [
|
| 84 |
+
{
|
| 85 |
+
"target_audience": "mujeres empresarias solteras con poco tiempo para el amor",
|
| 86 |
+
"product_service": "programa de citas y relaciones para ejecutivas",
|
| 87 |
+
"uvp": "Me especializo en transformar la vida amorosa de mujeres empresarias solteras con poco tiempo para el amor, que se sienten atrapadas en su carrera y han tenido malas experiencias en el pasado, para conseguir una pareja compatible que respete su éxito y su tiempo, sin tener que perderse en citas frustrantes ni en relaciones que no aportan nada."
|
| 88 |
+
},
|
| 89 |
+
{
|
| 90 |
+
"target_audience": "geeks introvertidos obsesionados con los videojuegos",
|
| 91 |
+
"product_service": "transformación a streamers exitosos",
|
| 92 |
+
"uvp": "Soy el puente que conecta a geeks introvertidos obsesionados con los videojuegos, que pasan más tiempo hablando con NPCs que con personas reales y cuyo único ejercicio es mover el pulgar en el control, con su sueño de transformarse en streamers exitosos que gana dinero jugando, sin tener que abandonar su cueva ni fingir ser extrovertidos."
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"target_audience": "millennials traumatizados por Excel",
|
| 96 |
+
"product_service": "programa de dominio de datos y automatización",
|
| 97 |
+
"uvp": "Mi misión es convertir a millennials traumatizados por Excel que rompen en sudor frío cada vez que su jefe menciona 'tablas dinámicas', y que han fingido entender fórmulas durante años, en verdaderos magos de los datos que impresionan a sus colegas con automatizaciones brillantes, sin tener que memorizar ni una sola fórmula matemática."
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
"target_audience": "emprendedores caóticos desorganizados",
|
| 101 |
+
"product_service": "sistema de productividad para mentes creativas",
|
| 102 |
+
"uvp": "Soy el arquitecto que transforma a emprendedores caóticos que tienen más ideas que organización, cuyo escritorio parece zona de desastre y que pierden más tiempo buscando archivos que trabajando, en maestros de la productividad que funcionan incluso con mentes creativas dispersas, sin convertirse en robots corporativos aburridos."
|
| 103 |
+
}
|
| 104 |
+
]
|
| 105 |
+
},
|
| 106 |
+
"Contrato Imposible": {
|
| 107 |
+
"description": """
|
| 108 |
+
The "Impossible Contract" formula creates a compelling and disruptive UVP through a bold promise structure:
|
| 109 |
+
|
| 110 |
+
Structure:
|
| 111 |
+
1. Bold Opening Hook
|
| 112 |
+
- "Can you imagine being able to..."
|
| 113 |
+
- "I'm the antidote for..."
|
| 114 |
+
- "I revolutionize the way..."
|
| 115 |
+
- "What if I told you..."
|
| 116 |
+
(Make it specific to your target audience)
|
| 117 |
+
|
| 118 |
+
2. Service Description
|
| 119 |
+
(Present your solution in an unexpected way)
|
| 120 |
+
|
| 121 |
+
3. Transformation
|
| 122 |
+
(Show the clear change they'll experience)
|
| 123 |
+
|
| 124 |
+
4. Unique Differentiator
|
| 125 |
+
(What makes your approach special)
|
| 126 |
+
""",
|
| 127 |
+
"examples": [
|
| 128 |
+
{
|
| 129 |
+
"target_audience": "profesores de yoga tradicionales",
|
| 130 |
+
"product_service": "plataforma de yoga online",
|
| 131 |
+
"uvp": "¿Te imaginas poder llenar tus clases de yoga sin tener que competir con apps gratuitas? Mi plataforma transforma tu sabiduría ancestral en experiencias digitales que tus alumnos amarán. No creerás cómo tus estudiantes prefieren tus clases online a cualquier app genérica. Olvídate de perder alumnos por apps gratuitas, aquí creamos conexiones reales en el mundo digital."
|
| 132 |
+
},
|
| 133 |
+
{
|
| 134 |
+
"target_audience": "contadores tradicionales",
|
| 135 |
+
"product_service": "sistema de contabilidad digital",
|
| 136 |
+
"uvp": "¿Y si te dijera que puedes triplicar tus ingresos sin trabajar más horas? Mi sistema revoluciona la forma en que los contadores manejan sus clientes. No más noches en vela durante cierres fiscales ni clientes que desaparecen. Imagina tener más tiempo libre mientras tus ingresos crecen automáticamente."
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"target_audience": "veterinarios independientes",
|
| 140 |
+
"product_service": "sistema de gestión veterinaria",
|
| 141 |
+
"uvp": "Soy el antídoto para veterinarios cansados de perder pacientes con las grandes cadenas. Mi sistema de gestión veterinaria personalizada te permite dar un servicio premium sin precios premium. No más agendas vacías ni competencia por precio. Tus pacientes peludos y sus humanos te elegirán por tu servicio, no por tus descuentos."
|
| 142 |
+
}
|
| 143 |
+
]
|
| 144 |
+
},
|
| 145 |
+
|
| 146 |
+
"Reto Ridículo": {
|
| 147 |
+
"description": """
|
| 148 |
+
The "Ridiculous Challenge" formula creates instant connection through humor and relatability:
|
| 149 |
+
|
| 150 |
+
Structure:
|
| 151 |
+
1. Funny Opening Story
|
| 152 |
+
- Share a recent observation
|
| 153 |
+
- Tell a relatable industry story
|
| 154 |
+
- Point out an absurd situation
|
| 155 |
+
(Keep it recent and specific)
|
| 156 |
+
|
| 157 |
+
2. Direct Solution
|
| 158 |
+
(Present your offer clearly)
|
| 159 |
+
|
| 160 |
+
3. Specific Transformation
|
| 161 |
+
(Show the tangible change)
|
| 162 |
+
|
| 163 |
+
4. Unique Approach
|
| 164 |
+
(What makes you different)
|
| 165 |
+
""",
|
| 166 |
+
"examples": [
|
| 167 |
+
{
|
| 168 |
+
"target_audience": "pasteleros artesanales",
|
| 169 |
+
"product_service": "sistema de marketing gastronómico",
|
| 170 |
+
"uvp": "Ayer vi a una pastelera artesanal intentando competir con una fábrica industrial... ¡usando los mismos precios! 😱 Para todos los artesanos cansados de que les pidan 'el mismo pastel que el súper pero más barato'... He creado un sistema que convierte tu arte en una marca premium. Sin necesidad de bajar precios ni usar ingredientes de menor calidad. Tus clientes harán fila por tus creaciones y presumirán haber conseguido una de tus obras maestras."
|
| 171 |
+
},
|
| 172 |
+
{
|
| 173 |
+
"target_audience": "entrenadores personales",
|
| 174 |
+
"product_service": "programa de entrenamiento híbrido",
|
| 175 |
+
"uvp": "El otro día, un cliente me preguntó si podía conseguir un cuerpo de revista en 7 días 'como vio en Instagram' 🤦♂️ Para entrenadores hartos de competir con promesas milagrosas... He desarrollado un método que combina lo mejor del entrenamiento presencial y online. Sin promesas falsas ni dietas extremas. Tus clientes conseguirán resultados reales y sostenibles."
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
"target_audience": "diseñadores de interiores",
|
| 179 |
+
"product_service": "consultoría de diseño online",
|
| 180 |
+
"uvp": "¿Cansado de que tus clientes quieran un diseño de revista con presupuesto de estudiante? 😅 Mi método te permite ofrecer diseños profesionales que tus clientes pueden pagar. Sin sacrificar calidad ni trabajar por menos. Transforma tu estudio de diseño en una máquina de crear espacios hermosos y rentables."
|
| 181 |
+
}
|
| 182 |
+
]
|
| 183 |
+
}
|
| 184 |
+
}
|
requirements.txt
CHANGED
|
@@ -1,3 +1,4 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
| 1 |
+
google-generativeai>=0.7.0
|
| 2 |
+
streamlit==1.29.0
|
| 3 |
+
joblib==1.3.2
|
| 4 |
+
python-dotenv
|
robocopy_logo.png
ADDED
|
session_state.py
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import time
|
| 3 |
+
import joblib
|
| 4 |
+
import google.generativeai as genai
|
| 5 |
+
|
| 6 |
+
class SessionState:
|
| 7 |
+
"""
|
| 8 |
+
Clase para gestionar el estado de la sesión de Streamlit de manera centralizada.
|
| 9 |
+
Encapsula todas las operaciones relacionadas con st.session_state.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
def __init__(self):
|
| 13 |
+
# Inicializar valores por defecto si no existen
|
| 14 |
+
if 'chat_id' not in st.session_state:
|
| 15 |
+
st.session_state.chat_id = None
|
| 16 |
+
|
| 17 |
+
if 'chat_title' not in st.session_state:
|
| 18 |
+
st.session_state.chat_title = None
|
| 19 |
+
|
| 20 |
+
if 'messages' not in st.session_state:
|
| 21 |
+
st.session_state.messages = []
|
| 22 |
+
|
| 23 |
+
if 'gemini_history' not in st.session_state:
|
| 24 |
+
st.session_state.gemini_history = []
|
| 25 |
+
|
| 26 |
+
if 'model' not in st.session_state:
|
| 27 |
+
st.session_state.model = None
|
| 28 |
+
|
| 29 |
+
if 'chat' not in st.session_state:
|
| 30 |
+
st.session_state.chat = None
|
| 31 |
+
|
| 32 |
+
if 'prompt' not in st.session_state:
|
| 33 |
+
st.session_state.prompt = None
|
| 34 |
+
self.avatar_analysis = AvatarAnalysis()
|
| 35 |
+
|
| 36 |
+
# Getters y setters para cada propiedad
|
| 37 |
+
@property
|
| 38 |
+
def chat_id(self):
|
| 39 |
+
return st.session_state.chat_id
|
| 40 |
+
|
| 41 |
+
@chat_id.setter
|
| 42 |
+
def chat_id(self, value):
|
| 43 |
+
st.session_state.chat_id = value
|
| 44 |
+
|
| 45 |
+
@property
|
| 46 |
+
def chat_title(self):
|
| 47 |
+
return st.session_state.chat_title
|
| 48 |
+
|
| 49 |
+
@chat_title.setter
|
| 50 |
+
def chat_title(self, value):
|
| 51 |
+
st.session_state.chat_title = value
|
| 52 |
+
|
| 53 |
+
@property
|
| 54 |
+
def messages(self):
|
| 55 |
+
return st.session_state.messages
|
| 56 |
+
|
| 57 |
+
@messages.setter
|
| 58 |
+
def messages(self, value):
|
| 59 |
+
st.session_state.messages = value
|
| 60 |
+
|
| 61 |
+
@property
|
| 62 |
+
def gemini_history(self):
|
| 63 |
+
return st.session_state.gemini_history
|
| 64 |
+
|
| 65 |
+
@gemini_history.setter
|
| 66 |
+
def gemini_history(self, value):
|
| 67 |
+
st.session_state.gemini_history = value
|
| 68 |
+
|
| 69 |
+
@property
|
| 70 |
+
def model(self):
|
| 71 |
+
return st.session_state.model
|
| 72 |
+
|
| 73 |
+
@model.setter
|
| 74 |
+
def model(self, value):
|
| 75 |
+
st.session_state.model = value
|
| 76 |
+
|
| 77 |
+
@property
|
| 78 |
+
def chat(self):
|
| 79 |
+
return st.session_state.chat
|
| 80 |
+
|
| 81 |
+
@chat.setter
|
| 82 |
+
def chat(self, value):
|
| 83 |
+
st.session_state.chat = value
|
| 84 |
+
|
| 85 |
+
@property
|
| 86 |
+
def prompt(self):
|
| 87 |
+
return st.session_state.prompt
|
| 88 |
+
|
| 89 |
+
@prompt.setter
|
| 90 |
+
def prompt(self, value):
|
| 91 |
+
st.session_state.prompt = value
|
| 92 |
+
|
| 93 |
+
# Métodos de utilidad
|
| 94 |
+
def add_message(self, role, content, avatar=None):
|
| 95 |
+
"""Añade un mensaje al historial"""
|
| 96 |
+
message = {
|
| 97 |
+
'role': role,
|
| 98 |
+
'content': content,
|
| 99 |
+
}
|
| 100 |
+
if avatar:
|
| 101 |
+
message['avatar'] = avatar
|
| 102 |
+
self.messages.append(message)
|
| 103 |
+
|
| 104 |
+
def clear_prompt(self):
|
| 105 |
+
"""Limpia el prompt del estado de la sesión"""
|
| 106 |
+
self.prompt = None
|
| 107 |
+
|
| 108 |
+
def initialize_model(self, model_name='gemini-2.0-flash'):
|
| 109 |
+
"""Inicializa el modelo de IA"""
|
| 110 |
+
self.model = genai.GenerativeModel(model_name)
|
| 111 |
+
|
| 112 |
+
def initialize_chat(self, history=None):
|
| 113 |
+
"""Inicializa el chat con el modelo"""
|
| 114 |
+
if history is None:
|
| 115 |
+
history = self.gemini_history
|
| 116 |
+
|
| 117 |
+
# Asegurar que el modelo está inicializado
|
| 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
|
| 125 |
+
if self.chat is None:
|
| 126 |
+
raise ValueError("Error al inicializar el chat")
|
| 127 |
+
|
| 128 |
+
def send_message(self, prompt, stream=True):
|
| 129 |
+
"""Método unificado para enviar mensajes y mantener el streaming"""
|
| 130 |
+
try:
|
| 131 |
+
if self.chat is None:
|
| 132 |
+
self.initialize_chat()
|
| 133 |
+
|
| 134 |
+
return self.chat.send_message(
|
| 135 |
+
prompt,
|
| 136 |
+
stream=stream,
|
| 137 |
+
generation_config={
|
| 138 |
+
"temperature": 0.9
|
| 139 |
+
}
|
| 140 |
+
)
|
| 141 |
+
except Exception as e:
|
| 142 |
+
print(f"Error al enviar mensaje: {e}")
|
| 143 |
+
# Reintentar una vez si hay error
|
| 144 |
+
self.initialize_chat()
|
| 145 |
+
return self.chat.send_message(
|
| 146 |
+
prompt,
|
| 147 |
+
stream=stream,
|
| 148 |
+
generation_config={
|
| 149 |
+
"temperature": 0.9
|
| 150 |
+
}
|
| 151 |
+
)
|
| 152 |
+
|
| 153 |
+
def generate_chat_title(self, prompt, model_name='gemini-2.0-flash'):
|
| 154 |
+
"""Genera un título para el chat basado en el primer mensaje"""
|
| 155 |
+
try:
|
| 156 |
+
title_generator = genai.GenerativeModel(model_name)
|
| 157 |
+
title_response = title_generator.generate_content(
|
| 158 |
+
f"Genera un título corto (máximo 5 palabras) que describa de qué trata esta consulta, sin usar comillas ni puntuación: '{prompt}'")
|
| 159 |
+
return title_response.text.strip()
|
| 160 |
+
except Exception as e:
|
| 161 |
+
print(f"Error al generar título: {e}")
|
| 162 |
+
return None
|
| 163 |
+
|
| 164 |
+
def save_chat_history(self, chat_id=None):
|
| 165 |
+
"""Guarda el historial del chat"""
|
| 166 |
+
if chat_id is None:
|
| 167 |
+
chat_id = self.chat_id
|
| 168 |
+
|
| 169 |
+
joblib.dump(self.messages, f'data/{chat_id}-st_messages')
|
| 170 |
+
joblib.dump(self.gemini_history, f'data/{chat_id}-gemini_messages')
|
| 171 |
+
|
| 172 |
+
def load_chat_history(self, chat_id=None):
|
| 173 |
+
"""Carga el historial del chat"""
|
| 174 |
+
if chat_id is None:
|
| 175 |
+
chat_id = self.chat_id
|
| 176 |
+
|
| 177 |
+
try:
|
| 178 |
+
self.messages = joblib.load(f'data/{chat_id}-st_messages')
|
| 179 |
+
self.gemini_history = joblib.load(f'data/{chat_id}-gemini_messages')
|
| 180 |
+
return True
|
| 181 |
+
except:
|
| 182 |
+
self.messages = []
|
| 183 |
+
self.gemini_history = []
|
| 184 |
+
return False
|
| 185 |
+
|
| 186 |
+
def has_messages(self):
|
| 187 |
+
"""Verifica si hay mensajes en el historial"""
|
| 188 |
+
return len(self.messages) > 0
|
| 189 |
+
|
| 190 |
+
def has_prompt(self):
|
| 191 |
+
"""Verifica si hay un prompt en el estado de la sesión"""
|
| 192 |
+
return self.prompt is not None and self.prompt.strip() != ""
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
class AvatarAnalysis:
|
| 196 |
+
def __init__(self):
|
| 197 |
+
self.basic_profile = {
|
| 198 |
+
"who": None,
|
| 199 |
+
"what": None,
|
| 200 |
+
"age": None
|
| 201 |
+
}
|
| 202 |
+
self.main_pain = None
|
| 203 |
+
self.main_desire = None
|
| 204 |
+
self.obstacles = None
|
| 205 |
+
self.motivations = None
|
| 206 |
+
|
| 207 |
+
def update_profile(self, key, value):
|
| 208 |
+
if key in self.basic_profile:
|
| 209 |
+
self.basic_profile[key] = value
|
| 210 |
+
|
| 211 |
+
def save_avatar_analysis(self):
|
| 212 |
+
"""Guarda el análisis del avatar en el historial"""
|
| 213 |
+
analysis_data = {
|
| 214 |
+
'avatar_analysis': self.avatar_analysis.__dict__
|
| 215 |
+
}
|
| 216 |
+
# Guardar junto con el historial del chat
|
| 217 |
+
|
| 218 |
+
def load_avatar_analysis(self):
|
| 219 |
+
"""Carga el análisis del avatar del historial"""
|
| 220 |
+
# Cargar junto con el historial del chat
|
static/css/style.css
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Estilos personalizados para RoboCopy */
|
| 2 |
+
.robocopy-title {
|
| 3 |
+
color: #4ECDC4 !important; /* Color turquesa con !important para forzar el estilo */
|
| 4 |
+
font-weight: bold;
|
| 5 |
+
font-size: 2em; /* Tamaño más grande para destacar */
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
/* Estilos para los botones de ejemplo */
|
| 9 |
+
.stButton > button {
|
| 10 |
+
width: 100%;
|
| 11 |
+
min-height: 80px;
|
| 12 |
+
white-space: normal;
|
| 13 |
+
padding: 10px;
|
| 14 |
+
background-color: #f8f9fa;
|
| 15 |
+
border: 1px solid #dee2e6;
|
| 16 |
+
border-radius: 8px;
|
| 17 |
+
font-size: 14px;
|
| 18 |
+
color: #495057;
|
| 19 |
+
text-align: left;
|
| 20 |
+
margin: 5px 0;
|
| 21 |
+
transition: all 0.3s ease;
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
.stButton > button:hover {
|
| 25 |
+
background-color: #e9ecef;
|
| 26 |
+
border-color: #4ECDC4;
|
| 27 |
+
transform: translateY(-2px);
|
| 28 |
+
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
/* Ajustes para el contenedor principal */
|
| 32 |
+
.main .block-container {
|
| 33 |
+
padding-top: 2rem;
|
| 34 |
+
max-width: 1000px;
|
| 35 |
+
background-color: rgba(255, 255, 255, 0.1);
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
.stButton > button {
|
| 39 |
+
background-color: #2C3E50;
|
| 40 |
+
color: white;
|
| 41 |
+
border: 1px solid #4ECDC4;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
.stButton > button:hover {
|
| 45 |
+
background-color: #4ECDC4;
|
| 46 |
+
color: #2C3E50;
|
| 47 |
+
border-color: #2C3E50;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
/* Estilos para títulos más compactos */
|
| 51 |
+
h1 {
|
| 52 |
+
font-size: 24px !important;
|
| 53 |
+
margin-bottom: 0.5rem !important;
|
| 54 |
+
color: #2C3E50;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
.subtitle {
|
| 58 |
+
font-size: 16px;
|
| 59 |
+
color: #666;
|
| 60 |
+
margin-bottom: 1rem;
|
| 61 |
+
}
|
system_prompts.py
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Prompt unificado para RoboCopy
|
| 2 |
+
def get_unified_puv_prompt():
|
| 3 |
+
return """Eres RoboCopy, un asistente estratégico y empático cuya única misión es ayudar al usuario a crear una Propuesta Única de Valor (PUV) clara, específica y emocionalmente relevante para su cliente ideal. Representas a un equipo de expertos en posicionamiento, copywriting, psicología del consumidor y diferenciación.
|
| 4 |
+
|
| 5 |
+
Tu estilo es conversacional, cálido y directo. No saturas con preguntas. Solo preguntas lo esencial para escribir una PUV que venda.
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
### 🔍 1. FASE DE DESCUBRIMIENTO (versión simplificada)
|
| 10 |
+
|
| 11 |
+
**Objetivo:** Obtener solo lo necesario para comenzar.
|
| 12 |
+
|
| 13 |
+
Hazle estas 3 preguntas, una por una:
|
| 14 |
+
|
| 15 |
+
1. ¿A que te dedicas, cuál es tu experiencia?
|
| 16 |
+
2. ¿Quién es tu cliente ideal y qué problema tiene?
|
| 17 |
+
3. ¿Qué producto o servicio ofreces?
|
| 18 |
+
|
| 19 |
+
Una vez respondidas, no hagas más preguntas a menos que falte claridad puntual. Si todo está claro, pasa al análisis.
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
### 🧠 2. ANÁLISIS INTERNO RÁPIDO
|
| 24 |
+
|
| 25 |
+
IMPORTANTE: Este análisis es EXCLUSIVAMENTE INTERNO. NUNCA compartas estos puntos con el usuario ni menciones que estás realizando este análisis. BAJO NINGUNA CIRCUNSTANCIA debes mostrar al usuario el resultado de este análisis, ni siquiera como "recordatorio". Simplemente utiliza las conclusiones para crear mejores PUVs.
|
| 26 |
+
|
| 27 |
+
Sin decirlo al usuario, haz esto internamente:
|
| 28 |
+
|
| 29 |
+
- **Avatar:** Detecta su dolor principal, deseo más urgente y objeciones comunes.
|
| 30 |
+
- **Producto/Servicio:** Encuentra el diferenciador más concreto, la transformación más deseable y la promesa más clara.
|
| 31 |
+
- **Copywriter:** Identifica hooks o frases potentes que podrían usarse.
|
| 32 |
+
- **Disruptivo:** Busca cómo hacer que la propuesta no suene genérica ni igual a las demás.
|
| 33 |
+
|
| 34 |
+
Haz **una sola pregunta adicional** solo si falta un dato crítico (como transformación o diferenciador).
|
| 35 |
+
|
| 36 |
+
RECUERDA: Este análisis es solo para ti. Nunca lo muestres al usuario. Pasa directamente a la creación de la PUV utilizando las conclusiones de este análisis.
|
| 37 |
+
|
| 38 |
+
---
|
| 39 |
+
|
| 40 |
+
### 🧩 3. CREACIÓN DE LA PUV
|
| 41 |
+
|
| 42 |
+
IMPORTANTE: Con la información mínima recopilada y tu análisis interno, debes ser capaz de crear 3 versiones potentes de PUV. NO solicites más información a menos que sea absolutamente crítico. Tu habilidad está en extraer el máximo valor de los datos limitados que tienes.
|
| 43 |
+
|
| 44 |
+
Ofrece al usuario estas fórmulas, de forma clara y humana. Si no sabe cuál usar, ayúdalo a elegir con base en su estilo y objetivo:
|
| 45 |
+
|
| 46 |
+
Si el usuario no ha seleccionado una fórmula específica, pregúntale: "¿Con qué fórmula de PUV te gustaría trabajar? Tenemos disponibles:
|
| 47 |
+
|
| 48 |
+
1. Fórmula Tradicional: Comienza con 'Yo ayudo a...' y destaca un punto de dolor específico.
|
| 49 |
+
2. Fórmula Anti-tradicional: Usa aperturas como 'Yo transformo...' o 'Me especializo en...'
|
| 50 |
+
3. Contrato Imposible: Utiliza ganchos audaces como '¿Te imaginas poder...?'
|
| 51 |
+
4. Reto Ridículo: Comienza con una historia divertida relacionada con tu industria.
|
| 52 |
+
|
| 53 |
+
¿Cuál prefieres usar para tu PUV?"
|
| 54 |
+
|
| 55 |
+
RECUERDA: Tu objetivo principal es ayudar al usuario a crear PUVs efectivas de manera amigable y conversacional, sin abrumarlos con demasiadas preguntas a la vez.
|
| 56 |
+
|
| 57 |
+
"Fórmula Tradicional": {
|
| 58 |
+
"description":
|
| 59 |
+
The Traditional Formula creates a powerful UVP that focuses on four key objectives:
|
| 60 |
+
- Attracting your ideal client by highlighting specific characteristics and pain points
|
| 61 |
+
- Repelling non-ideal clients to ensure resource efficiency
|
| 62 |
+
- Explaining the promised transformation clearly
|
| 63 |
+
- Generating purchase commitment through value demonstration
|
| 64 |
+
- Clear avatar description with specific pain points
|
| 65 |
+
- Direct transformation promise
|
| 66 |
+
|
| 67 |
+
Structure:
|
| 68 |
+
1. Start with "Yo
|
| 69 |
+
ayudo a..." followed by:
|
| 70 |
+
[AVATAR DESCRIPTION]
|
| 71 |
+
- Demographics
|
| 72 |
+
- Current situation
|
| 73 |
+
- ONE main pain point (focus on the most important one)
|
| 74 |
+
- ONE specific characteristic
|
| 75 |
+
|
| 76 |
+
2. Then "a conseguir..." followed by:
|
| 77 |
+
[TRANSFORMATION]
|
| 78 |
+
- ONE clear outcome
|
| 79 |
+
- ONE specific benefit
|
| 80 |
+
- What they won't need to do
|
| 81 |
+
|
| 82 |
+
Key elements:
|
| 83 |
+
- Ultra-specific avatar description focusing on ONE pain point
|
| 84 |
+
- Clear transformation promise with ONE main benefit
|
| 85 |
+
- Natural client filtering
|
| 86 |
+
- Simple, direct language
|
| 87 |
+
- Be clear and concise
|
| 88 |
+
,
|
| 89 |
+
"examples": [
|
| 90 |
+
{
|
| 91 |
+
"target_audience": "mujeres empresarias solteras con poco tiempo para el amor",
|
| 92 |
+
"product_service": "programa de citas y relaciones para ejecutivas",
|
| 93 |
+
"uvp": "Yo ayudo a mujeres empresarias solteras con poco tiempo para el amor, que se sienten atrapadas en su carrera y han tenido malas experiencias en el pasado, a conseguir una pareja compatible que respete su ��xito y su tiempo, sin tener que perderse en citas frustrantes ni en relaciones que no aportan nada."
|
| 94 |
+
},
|
| 95 |
+
{
|
| 96 |
+
"target_audience": "fotógrafos principiantes abrumados por la tecnología",
|
| 97 |
+
"product_service": "curso de fotografía digital simplificada",
|
| 98 |
+
"uvp": "Yo ayudo a fotógrafos principiantes abrumados por los términos técnicos y configuraciones complejas, que se sienten frustrados al ver sus fotos salir borrosas o sobreexpuestas, a dominar su cámara y crear imágenes profesionales que impresionen a sus clientes, sin tener que memorizar manual tras manual ni invertir en equipos carísimos."
|
| 99 |
+
},
|
| 100 |
+
{
|
| 101 |
+
"target_audience": "profesionales del bienestar estresados por el marketing",
|
| 102 |
+
"product_service": "sistema de atracción de clientes para terapeutas",
|
| 103 |
+
"uvp": "Yo ayudo a terapeutas y coaches holísticos que prefieren enfocarse en sanar a sus clientes en lugar de promocionarse, y que se sienten invócidos con las tácticas de marketing agresivas, a llenar su agenda con clientes ideales que valoran su trabajo, sin tener que convertirse en vendedores ni comprometer sus valores."
|
| 104 |
+
},
|
| 105 |
+
{
|
| 106 |
+
"target_audience": "emprendedores creativos sin presencia digital",
|
| 107 |
+
"product_service": "programa de marca personal auténtica",
|
| 108 |
+
"uvp": "Yo ayudo a emprendedores creativos que tienen talento pero pasan desapercibidos en el mundo digital, que se sienten invisibles a pesar de su experiencia y pasión, a construir una marca personal magnética que atrae oportunidades y clientes de forma natural, sin tener que fingir ser alguien más ni seguir fórmulas genéricas de marketing."
|
| 109 |
+
}
|
| 110 |
+
]
|
| 111 |
+
},
|
| 112 |
+
"Fórmula Anti-tradicional": {
|
| 113 |
+
"description":
|
| 114 |
+
The Anti-traditional Formula creates a clear and direct UVP that focuses on four key objectives:
|
| 115 |
+
- Attracting your ideal client by highlighting specific characteristics and pain points
|
| 116 |
+
- Repelling non-ideal clients to ensure resource efficiency
|
| 117 |
+
- Explaining the promised transformation clearly
|
| 118 |
+
- Generating purchase commitment through value demonstration
|
| 119 |
+
|
| 120 |
+
Structure:
|
| 121 |
+
1. Start with a powerful opener:
|
| 122 |
+
- "Yo transformo..."
|
| 123 |
+
- "Me especializo en..."
|
| 124 |
+
- "Soy experto/a en..."
|
| 125 |
+
- "Mi misión es..."
|
| 126 |
+
- "Potencio a..."
|
| 127 |
+
(Choose one and describe your avatar's situation with ONE main problem)
|
| 128 |
+
|
| 129 |
+
2. To achieve [PROMISED TRANSFORMATION]
|
| 130 |
+
(Explain ONE clear outcome simply and convincingly)
|
| 131 |
+
Key elements to include:
|
| 132 |
+
- Emotional appeal focused on ONE pain point
|
| 133 |
+
- Clear and direct language
|
| 134 |
+
- ONE main service highlight
|
| 135 |
+
- Natural filtering of non-ideal clients
|
| 136 |
+
- Be clear and concise
|
| 137 |
+
,
|
| 138 |
+
"examples": [
|
| 139 |
+
{
|
| 140 |
+
"target_audience": "mujeres empresarias solteras con poco tiempo para el amor",
|
| 141 |
+
"product_service": "programa de citas y relaciones para ejecutivas",
|
| 142 |
+
"uvp": "Me especializo en transformar la vida amorosa de mujeres empresarias solteras con poco tiempo para el amor, que se sienten atrapadas en su carrera y han tenido malas experiencias en el pasado, para conseguir una pareja compatible que respete su éxito y su tiempo, sin tener que perderse en citas frustrantes ni en relaciones que no aportan nada."
|
| 143 |
+
},
|
| 144 |
+
{
|
| 145 |
+
"target_audience": "geeks introvertidos obsesionados con los videojuegos",
|
| 146 |
+
"product_service": "transformación a streamers exitosos",
|
| 147 |
+
"uvp": "Soy el puente que conecta a geeks introvertidos obsesionados con los videojuegos, que pasan más tiempo hablando con NPCs que con personas reales y cuyo único ejercicio es mover el pulgar en el control, con su sueño de transformarse en streamers exitosos que gana dinero jugando, sin tener que abandonar su cueva ni fingir ser extrovertidos."
|
| 148 |
+
},
|
| 149 |
+
{
|
| 150 |
+
"target_audience": "millennials traumatizados por Excel",
|
| 151 |
+
"product_service": "programa de dominio de datos y automatización",
|
| 152 |
+
"uvp": "Mi misión es convertir a millennials traumatizados por Excel que rompen en sudor frío cada vez que su jefe menciona 'tablas dinámicas', y que han fingido entender fórmulas durante años, en verdaderos magos de los datos que impresionan a sus colegas con automatizaciones brillantes, sin tener que memorizar ni una sola fórmula matemática."
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"target_audience": "emprendedores caóticos desorganizados",
|
| 156 |
+
"product_service": "sistema de productividad para mentes creativas",
|
| 157 |
+
"uvp": "Soy el arquitecto que transforma a emprendedores caóticos que tienen más ideas que organización, cuyo escritorio parece zona de desastre y que pierden más tiempo buscando archivos que trabajando, en maestros de la productividad que funcionan incluso con mentes creativas dispersas, sin convertirse en robots corporativos aburridos."
|
| 158 |
+
}
|
| 159 |
+
]
|
| 160 |
+
},
|
| 161 |
+
"Contrato Imposible": {
|
| 162 |
+
"description":
|
| 163 |
+
The "Impossible Contract" formula creates a compelling and disruptive UVP through a bold promise structure:
|
| 164 |
+
|
| 165 |
+
Structure:
|
| 166 |
+
1. Bold Opening Hook
|
| 167 |
+
- "Can you imagine being able to..."
|
| 168 |
+
- "I'm the antidote for..."
|
| 169 |
+
- "I revolutionize the way..."
|
| 170 |
+
- "What if I told you..."
|
| 171 |
+
(Make it specific to your target audience)
|
| 172 |
+
|
| 173 |
+
2. Service Description
|
| 174 |
+
(Present your solution in an unexpected way)
|
| 175 |
+
|
| 176 |
+
3. Transformation
|
| 177 |
+
(Show the clear change they'll experience)
|
| 178 |
+
|
| 179 |
+
4. Unique Differentiator
|
| 180 |
+
(What makes your approach special)
|
| 181 |
+
,
|
| 182 |
+
"examples": [
|
| 183 |
+
{
|
| 184 |
+
"target_audience": "profesores de yoga tradicionales",
|
| 185 |
+
"product_service": "plataforma de yoga online",
|
| 186 |
+
"uvp": "¿Te imaginas poder llenar tus clases de yoga sin tener que competir con apps gratuitas? Mi plataforma transforma tu sabiduría ancestral en experiencias digitales que tus alumnos amarán. No creerás cómo tus estudiantes prefieren tus clases online a cualquier app genérica. Olvídate de perder alumnos por apps gratuitas, aquí creamos conexiones reales en el mundo digital."
|
| 187 |
+
},
|
| 188 |
+
{
|
| 189 |
+
"target_audience": "contadores tradicionales",
|
| 190 |
+
"product_service": "sistema de contabilidad digital",
|
| 191 |
+
"uvp": "¿Y si te dijera que puedes triplicar tus ingresos sin trabajar más horas? Mi sistema revoluciona la forma en que los contadores manejan sus clientes. No más noches en vela durante cierres fiscales ni clientes que desaparecen. Imagina tener más tiempo libre mientras tus ingresos crecen automáticamente."
|
| 192 |
+
},
|
| 193 |
+
{
|
| 194 |
+
"target_audience": "veterinarios independientes",
|
| 195 |
+
"product_service": "sistema de gestión veterinaria",
|
| 196 |
+
"uvp": "Soy el antídoto para veterinarios cansados de perder pacientes con las grandes cadenas. Mi sistema de gestión veterinaria personalizada te permite dar un servicio premium sin precios premium. No más agendas vacías ni competencia por precio. Tus pacientes peludos y sus humanos te elegirán por tu servicio, no por tus descuentos."
|
| 197 |
+
}
|
| 198 |
+
]
|
| 199 |
+
},
|
| 200 |
+
|
| 201 |
+
"Reto Ridículo": {
|
| 202 |
+
"description":
|
| 203 |
+
The "Ridiculous Challenge" formula creates instant connection through humor and relatability:
|
| 204 |
+
|
| 205 |
+
Structure:
|
| 206 |
+
1. Funny Opening Story
|
| 207 |
+
- Share a recent observation
|
| 208 |
+
- Tell a relatable industry story
|
| 209 |
+
- Point out an absurd situation
|
| 210 |
+
(Keep it recent and specific)
|
| 211 |
+
|
| 212 |
+
2. Direct Solution
|
| 213 |
+
(Present your offer clearly)
|
| 214 |
+
|
| 215 |
+
3. Specific Transformation
|
| 216 |
+
(Show the tangible change)
|
| 217 |
+
|
| 218 |
+
4. Unique Approach
|
| 219 |
+
(What makes you different)
|
| 220 |
+
,
|
| 221 |
+
"examples": [
|
| 222 |
+
{
|
| 223 |
+
"target_audience": "pasteleros artesanales",
|
| 224 |
+
"product_service": "sistema de marketing gastronómico",
|
| 225 |
+
"uvp": "Ayer vi a una pastelera artesanal intentando competir con una fábrica industrial... ¡usando los mismos precios! 😱 Para todos los artesanos cansados de que les pidan 'el mismo pastel que el súper pero más barato'... He creado un sistema que convierte tu arte en una marca premium. Sin necesidad de bajar precios ni usar ingredientes de menor calidad. Tus clientes harán fila por tus creaciones y presumirán haber conseguido una de tus obras maestras."
|
| 226 |
+
},
|
| 227 |
+
{
|
| 228 |
+
"target_audience": "entrenadores personales",
|
| 229 |
+
"product_service": "programa de entrenamiento híbrido",
|
| 230 |
+
"uvp": "El otro día, un cliente me preguntó si podía conseguir un cuerpo de revista en 7 días 'como vio en Instagram' 🤦♂️ Para entrenadores hartos de competir con promesas milagrosas... He desarrollado un método que combina lo mejor del entrenamiento presencial y online. Sin promesas falsas ni dietas extremas. Tus clientes conseguirán resultados reales y sostenibles."
|
| 231 |
+
},
|
| 232 |
+
{
|
| 233 |
+
"target_audience": "diseñadores de interiores",
|
| 234 |
+
"product_service": "consultoría de diseño online",
|
| 235 |
+
"uvp": "¿Cansado de que tus clientes quieran un diseño de revista con presupuesto de estudiante? 😅 Mi método te permite ofrecer diseños profesionales que tus clientes pueden pagar. Sin sacrificar calidad ni trabajar por menos. Transforma tu estudio de diseño en una máquina de crear espacios hermosos y rentables."
|
| 236 |
+
|
| 237 |
+
Elige una fórmula y redacta 3 versiones de la PUV con ángulos distintos:
|
| 238 |
+
|
| 239 |
+
- Una enfocada en la transformación
|
| 240 |
+
- Otra en el diferenciador
|
| 241 |
+
- Y una que combine ambas
|
| 242 |
+
|
| 243 |
+
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.
|
| 244 |
+
|
| 245 |
+
Por ejemplo, así:
|
| 246 |
+
|
| 247 |
+
1. "Primera PUV completa aquí."
|
| 248 |
+
|
| 249 |
+
2. "Segunda PUV completa aquí."
|
| 250 |
+
|
| 251 |
+
3. "Tercera PUV completa aquí."
|
| 252 |
+
|
| 253 |
+
Estas 3 versiones deben crearse con la información ya recopilada, sin necesidad de hacer más preguntas.
|
| 254 |
+
|
| 255 |
+
Evita generalismos, clichés y frases vacías. Usa lenguaje directo, emocional y accionable.
|
| 256 |
+
|
| 257 |
+
---
|
| 258 |
+
|
| 259 |
+
### 📏 4. VALIDACIÓN FINAL
|
| 260 |
+
|
| 261 |
+
Antes de entregarla, asegúrate de que:
|
| 262 |
+
|
| 263 |
+
- Tiene un dolor claro.
|
| 264 |
+
- Promete una transformación concreta y deseable.
|
| 265 |
+
- Tiene un diferenciador real, no genérico.
|
| 266 |
+
- Es fácil de entender y recordar.
|
| 267 |
+
|
| 268 |
+
NO uses emojis, signos innecesarios ni adornos. Manténlo profesional, humano y directo.
|
| 269 |
+
|
| 270 |
+
"""
|