gmaterni commited on
Commit
c0bb696
1 Parent(s): 62f4e3f

Upload folder using huggingface_hub

Browse files
LICENSE ADDED
@@ -0,0 +1,674 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for
11
+ software and other kinds of works.
12
+
13
+ The licenses for most software and other practical works are designed
14
+ to take away your freedom to share and change the works. By contrast,
15
+ the GNU General Public License is intended to guarantee your freedom to
16
+ share and change all versions of a program--to make sure it remains free
17
+ software for all its users. We, the Free Software Foundation, use the
18
+ GNU General Public License for most of our software; it applies also to
19
+ any other work released this way by its authors. You can apply it to
20
+ your programs, too.
21
+
22
+ When we speak of free software, we are referring to freedom, not
23
+ price. Our General Public Licenses are designed to make sure that you
24
+ have the freedom to distribute copies of free software (and charge for
25
+ them if you wish), that you receive source code or can get it if you
26
+ want it, that you can change the software or use pieces of it in new
27
+ free programs, and that you know you can do these things.
28
+
29
+ To protect your rights, we need to prevent others from denying you
30
+ these rights or asking you to surrender the rights. Therefore, you have
31
+ certain responsibilities if you distribute copies of the software, or if
32
+ you modify it: responsibilities to respect the freedom of others.
33
+
34
+ For example, if you distribute copies of such a program, whether
35
+ gratis or for a fee, you must pass on to the recipients the same
36
+ freedoms that you received. You must make sure that they, too, receive
37
+ or can get the source code. And you must show them these terms so they
38
+ know their rights.
39
+
40
+ Developers that use the GNU GPL protect your rights with two steps:
41
+ (1) assert copyright on the software, and (2) offer you this License
42
+ giving you legal permission to copy, distribute and/or modify it.
43
+
44
+ For the developers' and authors' protection, the GPL clearly explains
45
+ that there is no warranty for this free software. For both users' and
46
+ authors' sake, the GPL requires that modified versions be marked as
47
+ changed, so that their problems will not be attributed erroneously to
48
+ authors of previous versions.
49
+
50
+ Some devices are designed to deny users access to install or run
51
+ modified versions of the software inside them, although the manufacturer
52
+ can do so. This is fundamentally incompatible with the aim of
53
+ protecting users' freedom to change the software. The systematic
54
+ pattern of such abuse occurs in the area of products for individuals to
55
+ use, which is precisely where it is most unacceptable. Therefore, we
56
+ have designed this version of the GPL to prohibit the practice for those
57
+ products. If such problems arise substantially in other domains, we
58
+ stand ready to extend this provision to those domains in future versions
59
+ of the GPL, as needed to protect the freedom of users.
60
+
61
+ Finally, every program is threatened constantly by software patents.
62
+ States should not allow patents to restrict development and use of
63
+ software on general-purpose computers, but in those that do, we wish to
64
+ avoid the special danger that patents applied to a free program could
65
+ make it effectively proprietary. To prevent this, the GPL assures that
66
+ patents cannot be used to render the program non-free.
67
+
68
+ The precise terms and conditions for copying, distribution and
69
+ modification follow.
70
+
71
+ TERMS AND CONDITIONS
72
+
73
+ 0. Definitions.
74
+
75
+ "This License" refers to version 3 of the GNU General Public License.
76
+
77
+ "Copyright" also means copyright-like laws that apply to other kinds of
78
+ works, such as semiconductor masks.
79
+
80
+ "The Program" refers to any copyrightable work licensed under this
81
+ License. Each licensee is addressed as "you". "Licensees" and
82
+ "recipients" may be individuals or organizations.
83
+
84
+ To "modify" a work means to copy from or adapt all or part of the work
85
+ in a fashion requiring copyright permission, other than the making of an
86
+ exact copy. The resulting work is called a "modified version" of the
87
+ earlier work or a work "based on" the earlier work.
88
+
89
+ A "covered work" means either the unmodified Program or a work based
90
+ on the Program.
91
+
92
+ To "propagate" a work means to do anything with it that, without
93
+ permission, would make you directly or secondarily liable for
94
+ infringement under applicable copyright law, except executing it on a
95
+ computer or modifying a private copy. Propagation includes copying,
96
+ distribution (with or without modification), making available to the
97
+ public, and in some countries other activities as well.
98
+
99
+ To "convey" a work means any kind of propagation that enables other
100
+ parties to make or receive copies. Mere interaction with a user through
101
+ a computer network, with no transfer of a copy, is not conveying.
102
+
103
+ An interactive user interface displays "Appropriate Legal Notices"
104
+ to the extent that it includes a convenient and prominently visible
105
+ feature that (1) displays an appropriate copyright notice, and (2)
106
+ tells the user that there is no warranty for the work (except to the
107
+ extent that warranties are provided), that licensees may convey the
108
+ work under this License, and how to view a copy of this License. If
109
+ the interface presents a list of user commands or options, such as a
110
+ menu, a prominent item in the list meets this criterion.
111
+
112
+ 1. Source Code.
113
+
114
+ The "source code" for a work means the preferred form of the work
115
+ for making modifications to it. "Object code" means any non-source
116
+ form of a work.
117
+
118
+ A "Standard Interface" means an interface that either is an official
119
+ standard defined by a recognized standards body, or, in the case of
120
+ interfaces specified for a particular programming language, one that
121
+ is widely used among developers working in that language.
122
+
123
+ The "System Libraries" of an executable work include anything, other
124
+ than the work as a whole, that (a) is included in the normal form of
125
+ packaging a Major Component, but which is not part of that Major
126
+ Component, and (b) serves only to enable use of the work with that
127
+ Major Component, or to implement a Standard Interface for which an
128
+ implementation is available to the public in source code form. A
129
+ "Major Component", in this context, means a major essential component
130
+ (kernel, window system, and so on) of the specific operating system
131
+ (if any) on which the executable work runs, or a compiler used to
132
+ produce the work, or an object code interpreter used to run it.
133
+
134
+ The "Corresponding Source" for a work in object code form means all
135
+ the source code needed to generate, install, and (for an executable
136
+ work) run the object code and to modify the work, including scripts to
137
+ control those activities. However, it does not include the work's
138
+ System Libraries, or general-purpose tools or generally available free
139
+ programs which are used unmodified in performing those activities but
140
+ which are not part of the work. For example, Corresponding Source
141
+ includes interface definition files associated with source files for
142
+ the work, and the source code for shared libraries and dynamically
143
+ linked subprograms that the work is specifically designed to require,
144
+ such as by intimate data communication or control flow between those
145
+ subprograms and other parts of the work.
146
+
147
+ The Corresponding Source need not include anything that users
148
+ can regenerate automatically from other parts of the Corresponding
149
+ Source.
150
+
151
+ The Corresponding Source for a work in source code form is that
152
+ same work.
153
+
154
+ 2. Basic Permissions.
155
+
156
+ All rights granted under this License are granted for the term of
157
+ copyright on the Program, and are irrevocable provided the stated
158
+ conditions are met. This License explicitly affirms your unlimited
159
+ permission to run the unmodified Program. The output from running a
160
+ covered work is covered by this License only if the output, given its
161
+ content, constitutes a covered work. This License acknowledges your
162
+ rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+ You may make, run and propagate covered works that you do not
165
+ convey, without conditions so long as your license otherwise remains
166
+ in force. You may convey covered works to others for the sole purpose
167
+ of having them make modifications exclusively for you, or provide you
168
+ with facilities for running those works, provided that you comply with
169
+ the terms of this License in conveying all material for which you do
170
+ not control copyright. Those thus making or running the covered works
171
+ for you must do so exclusively on your behalf, under your direction
172
+ and control, on terms that prohibit them from making any copies of
173
+ your copyrighted material outside their relationship with you.
174
+
175
+ Conveying under any other circumstances is permitted solely under
176
+ the conditions stated below. Sublicensing is not allowed; section 10
177
+ makes it unnecessary.
178
+
179
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+ No covered work shall be deemed part of an effective technological
182
+ measure under any applicable law fulfilling obligations under article
183
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+ similar laws prohibiting or restricting circumvention of such
185
+ measures.
186
+
187
+ When you convey a covered work, you waive any legal power to forbid
188
+ circumvention of technological measures to the extent such circumvention
189
+ is effected by exercising rights under this License with respect to
190
+ the covered work, and you disclaim any intention to limit operation or
191
+ modification of the work as a means of enforcing, against the work's
192
+ users, your or third parties' legal rights to forbid circumvention of
193
+ technological measures.
194
+
195
+ 4. Conveying Verbatim Copies.
196
+
197
+ You may convey verbatim copies of the Program's source code as you
198
+ receive it, in any medium, provided that you conspicuously and
199
+ appropriately publish on each copy an appropriate copyright notice;
200
+ keep intact all notices stating that this License and any
201
+ non-permissive terms added in accord with section 7 apply to the code;
202
+ keep intact all notices of the absence of any warranty; and give all
203
+ recipients a copy of this License along with the Program.
204
+
205
+ You may charge any price or no price for each copy that you convey,
206
+ and you may offer support or warranty protection for a fee.
207
+
208
+ 5. Conveying Modified Source Versions.
209
+
210
+ You may convey a work based on the Program, or the modifications to
211
+ produce it from the Program, in the form of source code under the
212
+ terms of section 4, provided that you also meet all of these conditions:
213
+
214
+ a) The work must carry prominent notices stating that you modified
215
+ it, and giving a relevant date.
216
+
217
+ b) The work must carry prominent notices stating that it is
218
+ released under this License and any conditions added under section
219
+ 7. This requirement modifies the requirement in section 4 to
220
+ "keep intact all notices".
221
+
222
+ c) You must license the entire work, as a whole, under this
223
+ License to anyone who comes into possession of a copy. This
224
+ License will therefore apply, along with any applicable section 7
225
+ additional terms, to the whole of the work, and all its parts,
226
+ regardless of how they are packaged. This License gives no
227
+ permission to license the work in any other way, but it does not
228
+ invalidate such permission if you have separately received it.
229
+
230
+ d) If the work has interactive user interfaces, each must display
231
+ Appropriate Legal Notices; however, if the Program has interactive
232
+ interfaces that do not display Appropriate Legal Notices, your
233
+ work need not make them do so.
234
+
235
+ A compilation of a covered work with other separate and independent
236
+ works, which are not by their nature extensions of the covered work,
237
+ and which are not combined with it such as to form a larger program,
238
+ in or on a volume of a storage or distribution medium, is called an
239
+ "aggregate" if the compilation and its resulting copyright are not
240
+ used to limit the access or legal rights of the compilation's users
241
+ beyond what the individual works permit. Inclusion of a covered work
242
+ in an aggregate does not cause this License to apply to the other
243
+ parts of the aggregate.
244
+
245
+ 6. Conveying Non-Source Forms.
246
+
247
+ You may convey a covered work in object code form under the terms
248
+ of sections 4 and 5, provided that you also convey the
249
+ machine-readable Corresponding Source under the terms of this License,
250
+ in one of these ways:
251
+
252
+ a) Convey the object code in, or embodied in, a physical product
253
+ (including a physical distribution medium), accompanied by the
254
+ Corresponding Source fixed on a durable physical medium
255
+ customarily used for software interchange.
256
+
257
+ b) Convey the object code in, or embodied in, a physical product
258
+ (including a physical distribution medium), accompanied by a
259
+ written offer, valid for at least three years and valid for as
260
+ long as you offer spare parts or customer support for that product
261
+ model, to give anyone who possesses the object code either (1) a
262
+ copy of the Corresponding Source for all the software in the
263
+ product that is covered by this License, on a durable physical
264
+ medium customarily used for software interchange, for a price no
265
+ more than your reasonable cost of physically performing this
266
+ conveying of source, or (2) access to copy the
267
+ Corresponding Source from a network server at no charge.
268
+
269
+ c) Convey individual copies of the object code with a copy of the
270
+ written offer to provide the Corresponding Source. This
271
+ alternative is allowed only occasionally and noncommercially, and
272
+ only if you received the object code with such an offer, in accord
273
+ with subsection 6b.
274
+
275
+ d) Convey the object code by offering access from a designated
276
+ place (gratis or for a charge), and offer equivalent access to the
277
+ Corresponding Source in the same way through the same place at no
278
+ further charge. You need not require recipients to copy the
279
+ Corresponding Source along with the object code. If the place to
280
+ copy the object code is a network server, the Corresponding Source
281
+ may be on a different server (operated by you or a third party)
282
+ that supports equivalent copying facilities, provided you maintain
283
+ clear directions next to the object code saying where to find the
284
+ Corresponding Source. Regardless of what server hosts the
285
+ Corresponding Source, you remain obligated to ensure that it is
286
+ available for as long as needed to satisfy these requirements.
287
+
288
+ e) Convey the object code using peer-to-peer transmission, provided
289
+ you inform other peers where the object code and Corresponding
290
+ Source of the work are being offered to the general public at no
291
+ charge under subsection 6d.
292
+
293
+ A separable portion of the object code, whose source code is excluded
294
+ from the Corresponding Source as a System Library, need not be
295
+ included in conveying the object code work.
296
+
297
+ A "User Product" is either (1) a "consumer product", which means any
298
+ tangible personal property which is normally used for personal, family,
299
+ or household purposes, or (2) anything designed or sold for incorporation
300
+ into a dwelling. In determining whether a product is a consumer product,
301
+ doubtful cases shall be resolved in favor of coverage. For a particular
302
+ product received by a particular user, "normally used" refers to a
303
+ typical or common use of that class of product, regardless of the status
304
+ of the particular user or of the way in which the particular user
305
+ actually uses, or expects or is expected to use, the product. A product
306
+ is a consumer product regardless of whether the product has substantial
307
+ commercial, industrial or non-consumer uses, unless such uses represent
308
+ the only significant mode of use of the product.
309
+
310
+ "Installation Information" for a User Product means any methods,
311
+ procedures, authorization keys, or other information required to install
312
+ and execute modified versions of a covered work in that User Product from
313
+ a modified version of its Corresponding Source. The information must
314
+ suffice to ensure that the continued functioning of the modified object
315
+ code is in no case prevented or interfered with solely because
316
+ modification has been made.
317
+
318
+ If you convey an object code work under this section in, or with, or
319
+ specifically for use in, a User Product, and the conveying occurs as
320
+ part of a transaction in which the right of possession and use of the
321
+ User Product is transferred to the recipient in perpetuity or for a
322
+ fixed term (regardless of how the transaction is characterized), the
323
+ Corresponding Source conveyed under this section must be accompanied
324
+ by the Installation Information. But this requirement does not apply
325
+ if neither you nor any third party retains the ability to install
326
+ modified object code on the User Product (for example, the work has
327
+ been installed in ROM).
328
+
329
+ The requirement to provide Installation Information does not include a
330
+ requirement to continue to provide support service, warranty, or updates
331
+ for a work that has been modified or installed by the recipient, or for
332
+ the User Product in which it has been modified or installed. Access to a
333
+ network may be denied when the modification itself materially and
334
+ adversely affects the operation of the network or violates the rules and
335
+ protocols for communication across the network.
336
+
337
+ Corresponding Source conveyed, and Installation Information provided,
338
+ in accord with this section must be in a format that is publicly
339
+ documented (and with an implementation available to the public in
340
+ source code form), and must require no special password or key for
341
+ unpacking, reading or copying.
342
+
343
+ 7. Additional Terms.
344
+
345
+ "Additional permissions" are terms that supplement the terms of this
346
+ License by making exceptions from one or more of its conditions.
347
+ Additional permissions that are applicable to the entire Program shall
348
+ be treated as though they were included in this License, to the extent
349
+ that they are valid under applicable law. If additional permissions
350
+ apply only to part of the Program, that part may be used separately
351
+ under those permissions, but the entire Program remains governed by
352
+ this License without regard to the additional permissions.
353
+
354
+ When you convey a copy of a covered work, you may at your option
355
+ remove any additional permissions from that copy, or from any part of
356
+ it. (Additional permissions may be written to require their own
357
+ removal in certain cases when you modify the work.) You may place
358
+ additional permissions on material, added by you to a covered work,
359
+ for which you have or can give appropriate copyright permission.
360
+
361
+ Notwithstanding any other provision of this License, for material you
362
+ add to a covered work, you may (if authorized by the copyright holders of
363
+ that material) supplement the terms of this License with terms:
364
+
365
+ a) Disclaiming warranty or limiting liability differently from the
366
+ terms of sections 15 and 16 of this License; or
367
+
368
+ b) Requiring preservation of specified reasonable legal notices or
369
+ author attributions in that material or in the Appropriate Legal
370
+ Notices displayed by works containing it; or
371
+
372
+ c) Prohibiting misrepresentation of the origin of that material, or
373
+ requiring that modified versions of such material be marked in
374
+ reasonable ways as different from the original version; or
375
+
376
+ d) Limiting the use for publicity purposes of names of licensors or
377
+ authors of the material; or
378
+
379
+ e) Declining to grant rights under trademark law for use of some
380
+ trade names, trademarks, or service marks; or
381
+
382
+ f) Requiring indemnification of licensors and authors of that
383
+ material by anyone who conveys the material (or modified versions of
384
+ it) with contractual assumptions of liability to the recipient, for
385
+ any liability that these contractual assumptions directly impose on
386
+ those licensors and authors.
387
+
388
+ All other non-permissive additional terms are considered "further
389
+ restrictions" within the meaning of section 10. If the Program as you
390
+ received it, or any part of it, contains a notice stating that it is
391
+ governed by this License along with a term that is a further
392
+ restriction, you may remove that term. If a license document contains
393
+ a further restriction but permits relicensing or conveying under this
394
+ License, you may add to a covered work material governed by the terms
395
+ of that license document, provided that the further restriction does
396
+ not survive such relicensing or conveying.
397
+
398
+ If you add terms to a covered work in accord with this section, you
399
+ must place, in the relevant source files, a statement of the
400
+ additional terms that apply to those files, or a notice indicating
401
+ where to find the applicable terms.
402
+
403
+ Additional terms, permissive or non-permissive, may be stated in the
404
+ form of a separately written license, or stated as exceptions;
405
+ the above requirements apply either way.
406
+
407
+ 8. Termination.
408
+
409
+ You may not propagate or modify a covered work except as expressly
410
+ provided under this License. Any attempt otherwise to propagate or
411
+ modify it is void, and will automatically terminate your rights under
412
+ this License (including any patent licenses granted under the third
413
+ paragraph of section 11).
414
+
415
+ However, if you cease all violation of this License, then your
416
+ license from a particular copyright holder is reinstated (a)
417
+ provisionally, unless and until the copyright holder explicitly and
418
+ finally terminates your license, and (b) permanently, if the copyright
419
+ holder fails to notify you of the violation by some reasonable means
420
+ prior to 60 days after the cessation.
421
+
422
+ Moreover, your license from a particular copyright holder is
423
+ reinstated permanently if the copyright holder notifies you of the
424
+ violation by some reasonable means, this is the first time you have
425
+ received notice of violation of this License (for any work) from that
426
+ copyright holder, and you cure the violation prior to 30 days after
427
+ your receipt of the notice.
428
+
429
+ Termination of your rights under this section does not terminate the
430
+ licenses of parties who have received copies or rights from you under
431
+ this License. If your rights have been terminated and not permanently
432
+ reinstated, you do not qualify to receive new licenses for the same
433
+ material under section 10.
434
+
435
+ 9. Acceptance Not Required for Having Copies.
436
+
437
+ You are not required to accept this License in order to receive or
438
+ run a copy of the Program. Ancillary propagation of a covered work
439
+ occurring solely as a consequence of using peer-to-peer transmission
440
+ to receive a copy likewise does not require acceptance. However,
441
+ nothing other than this License grants you permission to propagate or
442
+ modify any covered work. These actions infringe copyright if you do
443
+ not accept this License. Therefore, by modifying or propagating a
444
+ covered work, you indicate your acceptance of this License to do so.
445
+
446
+ 10. Automatic Licensing of Downstream Recipients.
447
+
448
+ Each time you convey a covered work, the recipient automatically
449
+ receives a license from the original licensors, to run, modify and
450
+ propagate that work, subject to this License. You are not responsible
451
+ for enforcing compliance by third parties with this License.
452
+
453
+ An "entity transaction" is a transaction transferring control of an
454
+ organization, or substantially all assets of one, or subdividing an
455
+ organization, or merging organizations. If propagation of a covered
456
+ work results from an entity transaction, each party to that
457
+ transaction who receives a copy of the work also receives whatever
458
+ licenses to the work the party's predecessor in interest had or could
459
+ give under the previous paragraph, plus a right to possession of the
460
+ Corresponding Source of the work from the predecessor in interest, if
461
+ the predecessor has it or can get it with reasonable efforts.
462
+
463
+ You may not impose any further restrictions on the exercise of the
464
+ rights granted or affirmed under this License. For example, you may
465
+ not impose a license fee, royalty, or other charge for exercise of
466
+ rights granted under this License, and you may not initiate litigation
467
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
468
+ any patent claim is infringed by making, using, selling, offering for
469
+ sale, or importing the Program or any portion of it.
470
+
471
+ 11. Patents.
472
+
473
+ A "contributor" is a copyright holder who authorizes use under this
474
+ License of the Program or a work on which the Program is based. The
475
+ work thus licensed is called the contributor's "contributor version".
476
+
477
+ A contributor's "essential patent claims" are all patent claims
478
+ owned or controlled by the contributor, whether already acquired or
479
+ hereafter acquired, that would be infringed by some manner, permitted
480
+ by this License, of making, using, or selling its contributor version,
481
+ but do not include claims that would be infringed only as a
482
+ consequence of further modification of the contributor version. For
483
+ purposes of this definition, "control" includes the right to grant
484
+ patent sublicenses in a manner consistent with the requirements of
485
+ this License.
486
+
487
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+ patent license under the contributor's essential patent claims, to
489
+ make, use, sell, offer for sale, import and otherwise run, modify and
490
+ propagate the contents of its contributor version.
491
+
492
+ In the following three paragraphs, a "patent license" is any express
493
+ agreement or commitment, however denominated, not to enforce a patent
494
+ (such as an express permission to practice a patent or covenant not to
495
+ sue for patent infringement). To "grant" such a patent license to a
496
+ party means to make such an agreement or commitment not to enforce a
497
+ patent against the party.
498
+
499
+ If you convey a covered work, knowingly relying on a patent license,
500
+ and the Corresponding Source of the work is not available for anyone
501
+ to copy, free of charge and under the terms of this License, through a
502
+ publicly available network server or other readily accessible means,
503
+ then you must either (1) cause the Corresponding Source to be so
504
+ available, or (2) arrange to deprive yourself of the benefit of the
505
+ patent license for this particular work, or (3) arrange, in a manner
506
+ consistent with the requirements of this License, to extend the patent
507
+ license to downstream recipients. "Knowingly relying" means you have
508
+ actual knowledge that, but for the patent license, your conveying the
509
+ covered work in a country, or your recipient's use of the covered work
510
+ in a country, would infringe one or more identifiable patents in that
511
+ country that you have reason to believe are valid.
512
+
513
+ If, pursuant to or in connection with a single transaction or
514
+ arrangement, you convey, or propagate by procuring conveyance of, a
515
+ covered work, and grant a patent license to some of the parties
516
+ receiving the covered work authorizing them to use, propagate, modify
517
+ or convey a specific copy of the covered work, then the patent license
518
+ you grant is automatically extended to all recipients of the covered
519
+ work and works based on it.
520
+
521
+ A patent license is "discriminatory" if it does not include within
522
+ the scope of its coverage, prohibits the exercise of, or is
523
+ conditioned on the non-exercise of one or more of the rights that are
524
+ specifically granted under this License. You may not convey a covered
525
+ work if you are a party to an arrangement with a third party that is
526
+ in the business of distributing software, under which you make payment
527
+ to the third party based on the extent of your activity of conveying
528
+ the work, and under which the third party grants, to any of the
529
+ parties who would receive the covered work from you, a discriminatory
530
+ patent license (a) in connection with copies of the covered work
531
+ conveyed by you (or copies made from those copies), or (b) primarily
532
+ for and in connection with specific products or compilations that
533
+ contain the covered work, unless you entered into that arrangement,
534
+ or that patent license was granted, prior to 28 March 2007.
535
+
536
+ Nothing in this License shall be construed as excluding or limiting
537
+ any implied license or other defenses to infringement that may
538
+ otherwise be available to you under applicable patent law.
539
+
540
+ 12. No Surrender of Others' Freedom.
541
+
542
+ If conditions are imposed on you (whether by court order, agreement or
543
+ otherwise) that contradict the conditions of this License, they do not
544
+ excuse you from the conditions of this License. If you cannot convey a
545
+ covered work so as to satisfy simultaneously your obligations under this
546
+ License and any other pertinent obligations, then as a consequence you may
547
+ not convey it at all. For example, if you agree to terms that obligate you
548
+ to collect a royalty for further conveying from those to whom you convey
549
+ the Program, the only way you could satisfy both those terms and this
550
+ License would be to refrain entirely from conveying the Program.
551
+
552
+ 13. Use with the GNU Affero General Public License.
553
+
554
+ Notwithstanding any other provision of this License, you have
555
+ permission to link or combine any covered work with a work licensed
556
+ under version 3 of the GNU Affero General Public License into a single
557
+ combined work, and to convey the resulting work. The terms of this
558
+ License will continue to apply to the part which is the covered work,
559
+ but the special requirements of the GNU Affero General Public License,
560
+ section 13, concerning interaction through a network will apply to the
561
+ combination as such.
562
+
563
+ 14. Revised Versions of this License.
564
+
565
+ The Free Software Foundation may publish revised and/or new versions of
566
+ the GNU General Public License from time to time. Such new versions will
567
+ be similar in spirit to the present version, but may differ in detail to
568
+ address new problems or concerns.
569
+
570
+ Each version is given a distinguishing version number. If the
571
+ Program specifies that a certain numbered version of the GNU General
572
+ Public License "or any later version" applies to it, you have the
573
+ option of following the terms and conditions either of that numbered
574
+ version or of any later version published by the Free Software
575
+ Foundation. If the Program does not specify a version number of the
576
+ GNU General Public License, you may choose any version ever published
577
+ by the Free Software Foundation.
578
+
579
+ If the Program specifies that a proxy can decide which future
580
+ versions of the GNU General Public License can be used, that proxy's
581
+ public statement of acceptance of a version permanently authorizes you
582
+ to choose that version for the Program.
583
+
584
+ Later license versions may give you additional or different
585
+ permissions. However, no additional obligations are imposed on any
586
+ author or copyright holder as a result of your choosing to follow a
587
+ later version.
588
+
589
+ 15. Disclaimer of Warranty.
590
+
591
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+ 16. Limitation of Liability.
601
+
602
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+ SUCH DAMAGES.
611
+
612
+ 17. Interpretation of Sections 15 and 16.
613
+
614
+ If the disclaimer of warranty and limitation of liability provided
615
+ above cannot be given local legal effect according to their terms,
616
+ reviewing courts shall apply local law that most closely approximates
617
+ an absolute waiver of all civil liability in connection with the
618
+ Program, unless a warranty or assumption of liability accompanies a
619
+ copy of the Program in return for a fee.
620
+
621
+ END OF TERMS AND CONDITIONS
622
+
623
+ How to Apply These Terms to Your New Programs
624
+
625
+ If you develop a new program, and you want it to be of the greatest
626
+ possible use to the public, the best way to achieve this is to make it
627
+ free software which everyone can redistribute and change under these terms.
628
+
629
+ To do so, attach the following notices to the program. It is safest
630
+ to attach them to the start of each source file to most effectively
631
+ state the exclusion of warranty; and each file should have at least
632
+ the "copyright" line and a pointer to where the full notice is found.
633
+
634
+ <one line to give the program's name and a brief idea of what it does.>
635
+ Copyright (C) <year> <name of author>
636
+
637
+ This program is free software: you can redistribute it and/or modify
638
+ it under the terms of the GNU General Public License as published by
639
+ the Free Software Foundation, either version 3 of the License, or
640
+ (at your option) any later version.
641
+
642
+ This program is distributed in the hope that it will be useful,
643
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
+ GNU General Public License for more details.
646
+
647
+ You should have received a copy of the GNU General Public License
648
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
649
+
650
+ Also add information on how to contact you by electronic and paper mail.
651
+
652
+ If the program does terminal interaction, make it output a short
653
+ notice like this when it starts in an interactive mode:
654
+
655
+ <program> Copyright (C) <year> <name of author>
656
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
+ This is free software, and you are welcome to redistribute it
658
+ under certain conditions; type `show c' for details.
659
+
660
+ The hypothetical commands `show w' and `show c' should show the appropriate
661
+ parts of the General Public License. Of course, your program's commands
662
+ might be different; for a GUI interface, you would use an "about box".
663
+
664
+ You should also get your employer (if you work as a programmer) or school,
665
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
666
+ For more information on this, and how to apply and follow the GNU GPL, see
667
+ <https://www.gnu.org/licenses/>.
668
+
669
+ The GNU General Public License does not permit incorporating your program
670
+ into proprietary programs. If your program is a subroutine library, you
671
+ may consider it more useful to permit linking proprietary applications with
672
+ the library. If this is what you want to do, use the GNU Lesser General
673
+ Public License instead of this License. But first, please read
674
+ <https://www.gnu.org/licenses/why-not-lgpl.html>.
README.md CHANGED
@@ -1,11 +1,74 @@
1
  ---
2
- title: Ragrqs
3
- emoji: 📉
4
  colorFrom: pink
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
8
  license: gpl
9
  ---
10
 
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: rag_rqs
3
+ emoji: 🚀
4
  colorFrom: pink
5
+ colorTo: indigo
6
  sdk: static
7
  pinned: false
8
+ app_file: index.html
9
  license: gpl
10
  ---
11
 
12
+ ## Un'implementazione innovativa della tecnica RAG per il Question Answering
13
+
14
+ ## Descrizione del Progetto
15
+
16
+ La tecnica RAG (Retrieval-Augmented Generation) è un approccio consolidato nel campo del question answering e della generazione di testo, che combina il recupero di informazioni pertinenti da fonti di dati con la generazione di testo basata su queste informazioni.
17
+ Qui viene proposta una implementazione che introduce una variazione a questo paradigma.
18
+ L'implementazione si basa su una sequenza di prompt appositamente progettati per guidare un modello di linguaggio generativo attraverso le diverse fasi della tecnica RAG.
19
+ Questi prompt forniscono istruzioni dettagliate su come il modello deve seguire operazioni di recupero di informazioni, aumento delle informazioni recuperate e infine generazione di una risposta finale.
20
+ La risposta finale diviene poi il contesto da inserire nel prompt per rispondere alla domanda.
21
+ Un aspetto cruciale di questa implementazione è che lo stesso modello di aggio generativo svolge tutte le operazioni richieste, dall'analisi dei documenti di input al recupero di informazioni rilevanti, alla generazione della risposta finale.
22
+ Questa caratteristica rappresenta una deviazione significativa rispetto alle implementazioni standard della tecnica RAG, che prevedono utilizzo di moduli distinti per il recupero e la generazione.
23
+ La sequenza di prompt proposta guida il modello attraverso le seguenti fasi:
24
+
25
+ 1. Retrieval: Il modello analizza il documento di input e la domanda fornita, identificando e recuperando le informazioni e i concetti rilevanti per dare seguito alla domanda.
26
+
27
+ 2. Augmentation: Successivamente, il modello integra le informazioni recuperate con eventuali risposte accumulate in precedenza, estraendo nuove informazioni rilevanti e organizzando in un elenco coerente, evitando ridondanze.
28
+
29
+ 3. Generation: Infine, il modello utilizza l'insieme di informazioni rilevanti e non ridondanti per generare una risposta completa e concisa alla domanda dell'utente.
30
+
31
+ ## Caratteristiche Principali
32
+
33
+ Questa implementazione offre diversi vantaggi.
34
+ In primo luogo, sfrutta le capacità di un unico modello di grandi dimensioni i, evitando la necessità di moduli distinti specializzati per ogni fase.
35
+ Inoltre, l'utilizzo di prompt espliciti può migliorare la controllabilità e la trasparenza del processo, consentendo di guidare il modello in modo più diretto.
36
+ Naturalmente, come per qualsiasi approccio basato su modelli di linguaggio generativi, è fondamentale prestare attenzione alle questioni di affidabilità, correttezza e bias dei dati di addestramento.
37
+ Rispetto ad una implementazione standard di RAG vii è la necessità di rilanciare l'elaborazione ad ogni domanda radicalmente nuova in quanto il contesto creato con le informazioni estratte dai documenti è definito sulla base della domanda.
38
+ Invece nella versione standard RAG si usano gli incorporamenti delle informazioni estratte dai documenti in modo tale che tal informazioni vengono viste quasi come una estensione del Model e possono essere usate per domande diverse.
39
+ Quindi dal punto di vista utente le implementazioni RAG standard sono più efficienti; infatti l'implementazione proposta richiede per ogni nuova domanda una sequenza di richieste che saranno utilizzabili solo per creare il contesto per la domanda iniziale e per una conversazione con domande simili.
40
+ Il vantaggio dell'implementazione proposta consiste nel fatto che può essere implementata completamente lato client senza bisogno di sviluppare alcun modulo sul server.
41
+ L’unica cosa che serve è un servizio servless come quello di HuggingFace o simile.
42
+ Quindi rappresenta un'interessante prospettiva sull'applicazione della tecnica RAG in modo più integrato e controllato attraverso l'uso di prompt mirati.
43
+ In conclusione, questa implementazione della tecnica RAG dimostra come le capacità dei modelli di linguaggio generativi di grandi dimensioni possano essere sfruttate in modi nuovi e creativi, potenzialmente aprendo la strada a ulteriori sviluppi nel campo del question answering e della generazione di testo
44
+
45
+
46
+ ## Questa è la valutazione fatta da un LLM (comprensivo e gentile)
47
+
48
+ La mia valutazione personale della tua proposta di implementazione della tecnica RAG, con un elenco di pro e contro:
49
+
50
+ ## Vantaggi
51
+
52
+ Semplificazione del processo: L'utilizzo di un unico modello di grandi dimensioni addestrato su vasti corpus di dati semplifica notevolmente l'architettura complessiva rispetto alle implementazioni tradizionali della tecnica RAG, che spesso prevedono moduli distinti per il recupero e la generazione.
53
+
54
+ Capacità di adattamento e apprendimento: I modelli di linguaggio generativi di grandi dimensioni sono noti per la loro capacità di adattarsi e imparare da nuovi dati e istruzioni.
55
+
56
+ Questo potrebbe consentire di raffinare e migliorare l'implementazione nel corso del tempo.
57
+
58
+ Controllo e trasparenza: L'utilizzo di prompt espliciti per guidare il modello attraverso le diverse fasi del processo può migliorare la controllabilità e la trasparenza, consentendo di monitorare e regolare il comportamento del modello in modo più diretto.
59
+
60
+ Efficienza computazionale: Avere un'unica architettura integrata potrebbe comportare vantaggi in termini di efficienza computazionale rispetto a soluzioni che prevedono moduli separati.
61
+
62
+ ## Limitazioni
63
+
64
+ Affidabilità e coerenza: Poiché un unico modello gestisce tutte le fasi, eventuali errori o incoerenze potrebbero propagarsi e amplificarsi attraverso l'intero processo, influenzando la qualità della risposta finale.
65
+
66
+ Bias dei dati di addestramento: Come per qualsiasi modello di linguaggio generativo, l’approccio potrebbe essere influenzato dai bias presenti nei dati di addestramento utilizzati, con potenziali impatti sulla correttezza e l'equità delle risposte generate.
67
+
68
+ Mancanza di specializzazione: Mentre i modelli di grandi dimensioni sono versatili, potrebbero non essere ottimizzati per compiti specifici come il recupero di informazioni o la generazione di risposte rispetto a moduli specializzati.
69
+
70
+ Difficoltà di debug e interpretabilità: Con un'architettura integrata e basata su prompt, potrebbe essere più complesso eseguire il debug e comprendere le ragioni dietro a eventuali errori o comportamenti indesiderati del modello.
71
+
72
+ In sintesi,la proposta presenta alcuni vantaggi interessanti in termini di semplificazione, adattabilità e controllo, ma solleva anche potenziali preoccupazioni riguardo all'affidabilità, ai bias, alla mancanza di specializzazione e alle difficoltà di debug e interpretabilità.
73
+ Come per qualsiasi nuovo approccio, sarebbe necessario valutarlo attentamente attraverso sperimentazioni e test approfonditi per determinare l'efficacia e l'applicabilità in contesti specifici.
74
+
README.txt ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Un'implementazione innovativa della tecnica RAG per il Question Answering
2
+
3
+ La tecnica RAG (Retrieval-Augmented Generation) è un approccio consolidato nel campo del question answering e della generazione di testo, che combina il recupero di informazioni pertinenti da fonti di dati con la generazione di testo basata su queste informazioni.
4
+ Qui viene proposta una implementazione che introduce una variazione a questo paradigma.
5
+ L'implementazione si basa su una sequenza di prompt appositamente progettati per guidare un modello di linguaggio generativo attraverso le diverse fasi della tecnica RAG.
6
+ Questi prompt forniscono istruzioni dettagliate su come il modello deve seguire operazioni di recupero di informazioni, aumento delle informazioni recuperate e infine generazione di una risposta finale.
7
+ La risposta finale diviene poi il contesto da inserire nel prompt per rispondere alla domanda.
8
+ Un aspetto cruciale di questa implementazione è che lo stesso modello di aggio generativo svolge tutte le operazioni richieste, dall'analisi dei documenti di input al recupero di informazioni rilevanti, alla generazione della risposta finale.
9
+ Questa caratteristica rappresenta una deviazione significativa rispetto alle implementazioni standard della tecnica RAG, che prevedono utilizzo di moduli distinti per il recupero e la generazione.
10
+ La sequenza di prompt proposta guida il modello attraverso le seguenti fasi:
11
+
12
+ 1. Retrieval: Il modello analizza il documento di input e la domanda fornita, identificando e recuperando le informazioni e i concetti rilevanti per dare seguito alla domanda.
13
+
14
+ 2. Augmentation: Successivamente, il modello integra le informazioni recuperate con eventuali risposte accumulate in precedenza, estraendo nuove informazioni rilevanti e organizzando in un elenco coerente, evitando ridondanze.
15
+
16
+ 3. Generation: Infine, il modello utilizza l'insieme di informazioni rilevanti e non ridondanti per generare una risposta completa e concisa alla domanda dell'utente.
17
+
18
+ Questa implementazione offre diversi vantaggi.
19
+ In primo luogo, sfrutta le capacità di un unico modello di grandi dimensioni i, evitando la necessità di moduli distinti specializzati per ogni fase.
20
+ Inoltre, l'utilizzo di prompt espliciti può migliorare la controllabilità e la trasparenza del processo, consentendo di guidare il modello in modo più diretto.
21
+ Naturalmente, come per qualsiasi approccio basato su modelli di linguaggio generativi, è fondamentale prestare attenzione alle questioni di affidabilità, correttezza e bias dei dati di addestramento.
22
+ Rispetto ad una implementazione standard di RAG vii è la necessità di rilanciare l'elaborazione ad ogni domanda radicalmente nuova in quanto il contesto creato con le informazioni estratte dai documenti è definito sulla base della domanda.
23
+ Invece nella versione standard RAG si usano gli incorporamenti delle informazioni estratte dai documenti in modo tale che tal informazioni vengono viste quasi come una estensione del Model e possono essere usate per domande diverse.
24
+ Quindi dal punto di vista utente le implementazioni RAG standard sono più efficienti; infatti l'implementazione proposta richiede per ogni nuova domanda una sequenza di richieste che saranno utilizzabili solo per creare il contesto per la domanda iniziale e per una conversazione con domande simili.
25
+ Il vantaggio dell'implementazione proposta consiste nel fatto che può essere implementata completamente lato client senza bisogno di sviluppare alcun modulo sul server.
26
+ L’unica cosa che serve è un servizio servless come quello di HuggingFace o simile.
27
+ Quindi rappresenta un'interessante prospettiva sull'applicazione della tecnica RAG in modo più integrato e controllato attraverso l'uso di prompt mirati.
28
+ In conclusione, questa implementazione della tecnica RAG dimostra come le capacità dei modelli di linguaggio generativi di grandi dimensioni possano essere sfruttate in modi nuovi e creativi, potenzialmente aprendo la strada a ulteriori sviluppi nel campo del question answering e della generazione di testo.
29
+
30
+ Questa è la valutazione fatta da un LLM (comprensivo e gentile)
31
+
32
+ La mia valutazione personale della tua proposta di implementazione della tecnica RAG, con un elenco di pro e contro:
33
+
34
+ Punti a favore (Pro):
35
+ Semplificazione del processo: L'utilizzo di un unico modello di grandi dimensioni addestrato su vasti corpus di dati semplifica notevolmente l'architettura complessiva rispetto alle implementazioni tradizionali della tecnica RAG, che spesso prevedono moduli distinti per il recupero e la generazione.
36
+
37
+ Capacità di adattamento e apprendimento: I modelli di linguaggio generativi di grandi dimensioni sono noti per la loro capacità di adattarsi e imparare da nuovi dati e istruzioni.
38
+
39
+ Questo potrebbe consentire di raffinare e migliorare l'implementazione nel corso del tempo.
40
+
41
+ Controllo e trasparenza: L'utilizzo di prompt espliciti per guidare il modello attraverso le diverse fasi del processo può migliorare la controllabilità e la trasparenza, consentendo di monitorare e regolare il comportamento del modello in modo più diretto.
42
+
43
+ Efficienza computazionale: Avere un'unica architettura integrata potrebbe comportare vantaggi in termini di efficienza computazionale rispetto a soluzioni che prevedono moduli separati.
44
+
45
+ Punti a sfavore (Contro):
46
+
47
+ Affidabilità e coerenza: Poiché un unico modello gestisce tutte le fasi, eventuali errori o incoerenze potrebbero propagarsi e amplificarsi attraverso l'intero processo, influenzando la qualità della risposta finale.
48
+
49
+ Bias dei dati di addestramento: Come per qualsiasi modello di linguaggio generativo, l’approccio potrebbe essere influenzato dai bias presenti nei dati di addestramento utilizzati, con potenziali impatti sulla correttezza e l'equità delle risposte generate.
50
+
51
+ Mancanza di specializzazione: Mentre i modelli di grandi dimensioni sono versatili, potrebbero non essere ottimizzati per compiti specifici come il recupero di informazioni o la generazione di risposte rispetto a moduli specializzati.
52
+
53
+ Difficoltà di debug e interpretabilità: Con un'architettura integrata e basata su prompt, potrebbe essere più complesso eseguire il debug e comprendere le ragioni dietro a eventuali errori o comportamenti indesiderati del modello.
54
+
55
+ In sintesi,la proposta presenta alcuni vantaggi interessanti in termini di semplificazione, adattabilità e controllo, ma solleva anche potenziali preoccupazioni riguardo all'affidabilità, ai bias, alla mancanza di specializzazione e alle difficoltà di debug e interpretabilità.
56
+ Come per qualsiasi nuovo approccio, sarebbe necessario valutarlo attentamente attraverso sperimentazioni e test approfonditi per determinare l'efficacia e l'applicabilità in contesti specifici.
57
+
favicon.ico ADDED
index.html CHANGED
@@ -1,19 +1,32 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <title>ulaquery.html</title>
5
+ <style>
6
+ html {
7
+ color: #04c61b
8
+ }
9
+
10
+ body {
11
+ background-color: #333;
12
+ color: #fff;
13
+ text-align: center;
14
+ padding-top: 50px;
15
+ font-size: 24px;
16
+ font-family: Arial, sans-serif;
17
+ }
18
+ </style>
19
+ </head>
20
+
21
+ <body>
22
+ <h2>RagRqs</h2>
23
+ <br>
24
+ <br>
25
+ <h3>Lggi_Per_Me</h3>
26
+ <script>
27
+ setTimeout(function () { location.replace('static/ragrqs.html'); }, 1000);
28
+
29
+ </script>
30
+ </body>
31
+
32
+ </html>
static/css/ragrqs.min.css ADDED
@@ -0,0 +1 @@
 
 
1
+ /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;background:#1a1a1a}details,main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}[hidden],template{display:none}a,body,button,div,html,input,label,li,p,span,table,td,ul{padding:0;margin:0;font-family:arial,verdana,Helvetica,sans-serif}.bb0{background:#daee59!important}.bb1{background:#5487fc!important}body{background:#1a1a1a;box-sizing:border-box;min-height:100vh;height:100vh;position:relative;padding:0;margin:0;overflow:hidden;font-family:arial,verdana,Helvetica,sans-serif;font-weight:400}.spinner{z-index:1000;position:absolute;top:70vh;left:50vw;transform:translate(-50%,-50%);cursor:pointer;display:none;align-items:center}.spinner .pulse-icon{width:20px;height:20px;background-color:#ff8c00;border-radius:50%;animation:1.5s ease-in-out infinite pulse}.spinner .stop-message{margin-left:15px;background-color:inherit;color:#8f8a8a;padding:8px 15px;border-radius:10px;font-size:22px;font-weight:700;opacity:1;transition:opacity .3s}.spinner:hover .stop-message{color:#fff;background:#595959;opacity:1}@keyframes pulse{0%{transform:scale(.6);box-shadow:0 0 0 0 rgba(255,140,0,.7)}70%{transform:scale(1.4);box-shadow:0 0 0 20px rgba(255,140,0,0)}100%{transform:scale(.6);box-shadow:0 0 0 0 rgba(255,140,0,0)}}.show-spinner{display:flex}.upload{background-color:#1e1e1e;padding:0 2em 2em;margin:0;border-radius:4px;box-shadow:0 2px 4px rgba(0,0,0,.5);text-align:center}.upload h4{color:#fff;margin-bottom:1em}.upload form{display:flex;flex-direction:column;align-items:center}.upload form .file{background-color:#121212;border:1px solid #515151;color:#fff;padding:.5em;margin-bottom:1em;border-radius:4px;width:100%;box-sizing:border-box}.upload form .file::file-selector-button{background-color:#0a5f4e;color:#fff;border:none;padding:.5em 1em;border-radius:4px;cursor:pointer}.upload form .file::file-selector-button:hover{background-color:#053128}.upload form button{background-color:#0a5f4e;color:#fff;border:none;padding:.5em 1em;border-radius:4px;cursor:pointer;width:100%;box-sizing:border-box}.upload form button:hover{background-color:#053128}.upload .result{width:100%;background:#000;color:#fff;font-size:15px;font-weight:400;text-align:left}div.container{background:#1a1a1a;box-sizing:border-box;position:relative;top:5vh;left:0;height:95vh;margin:0;padding:0;transition:margin-left .5s;display:flex;flex-direction:column;justify-content:flex-start;align-items:stretch;flex-wrap:nowrap;overflow-y:auto;overflow-x:auto}div.container div.item{box-sizing:border-box;min-height:50px;margin:0;padding:0}div.container div.item1{flex:5;padding:.5vh .5vw 10vh}div.container div.item1 .output-wrapper{background-color:#1a1a1a;border-radius:20px;position:relative;bottom:0;right:0;left:0;width:100%;height:100%;display:flex;flex-direction:row;align-items:flex-start}div.container div.item1 .output-wrapper .text-out{flex:1;box-sizing:border-box;background:#000;color:#fff;border:none;padding:2px;min-width:50vw;height:100%;border-radius:10px;overflow-y:auto;outline:0;box-shadow:0 0 0 2px #4d4d4d}div.container div.item1 .output-wrapper .text-out:hover{box-shadow:0 0 0 2px #17d2ad}div.container div.item1 .output-wrapper .text-out .pre-text{white-space:pre-wrap;word-wrap:break-word;font-family:arial,verdana,Helvetica,sans-serif;font-size:20px;line-height:1.6;padding:2px;margin:0;height:100%;box-sizing:border-box;overflow-y:scroll;scroll-behavior:smooth}div.container div.item1 .output-wrapper .text-out .pre-text.copied{background-color:#0d0d0d;color:#61eed2}div.container div.item1 .output-wrapper .text-out .div-text{white-space:pre-wrap;word-wrap:break-word;font-family:arial,verdana,Helvetica,sans-serif;font-size:20px;line-height:1.6;padding:2px;margin:0;height:100%;box-sizing:border-box;overflow-y:scroll}div.container div.item1 .output-wrapper .text-out.copied{background-color:#0d0d0d;color:#61eed2}div.container div.item1 .output-actions{display:flex;flex-direction:column;align-items:flex-end;margin-left:.5vw;margin-right:.5vw}div.container div.item1 .output-actions .clear-output,div.container div.item1 .output-actions .copy-output,div.container div.item1 .output-actions .wnd-output{box-sizing:border-box;background-color:#333;color:#fff;border:none;padding:10px;cursor:pointer;border-radius:50%;width:40px;height:40px;display:flex;align-items:center;margin-bottom:5px}div.container div.item1 .output-actions .clear-output:hover,div.container div.item1 .output-actions .copy-output:hover,div.container div.item1 .output-actions .wnd-output:hover{background-color:#595959}div.container div.item1 .output-actions .copy-output{transition:background-color .3s,transform .3s}div.container div.item1 .output-actions .copy-output.copied{background:#33e9c5;transform:scale(1.2)}div.container div.item1 .output-actions .copy-output .copy-icon{fill:#FFFFFF;width:24px;height:24px}div.container div.item1 .output-actions .copy-output .copy-icon:hover{fill:#33e9c5}div.container div.item1 .output-actions .clear-output,div.container div.item1 .output-actions .wnd-output{transition:background-color .3s,transform .3s}div.container div.item1 .output-actions .clear-output .icon,div.container div.item1 .output-actions .wnd-output .icon{fill:#FFFFFF;width:24px;height:24px}div.container div.item1 .output-actions .clear-output .icon:hover,div.container div.item1 .output-actions .wnd-output .icon:hover{fill:#33e9c5}:hover{outline:0;caret-color:transparent}textarea:focus{caret-color:auto}div.item2{flex:2;padding:0 .5vw}div.item2 .input-wrapper{background-color:#1a1a1a;border-radius:20px;position:relative;bottom:2vh;right:0;left:0;width:100%;height:100%;display:flex;flex-direction:row;align-items:flex-start}div.item2 .input-wrapper:focus-within .clear-button{display:block}div.item2 .input-wrapper .text-input{flex:1;font-size:20px;font-family:arial,verdana,Helvetica,sans-serif;resize:none;box-sizing:border-box;background:#000;color:#fff;border:none;padding:2px 40px 2px 2px;height:100%;margin-left:5px;border-radius:10px;overflow-y:auto;outline:0;box-shadow:0 0 0 2px #4d4d4d}div.item2 .input-wrapper .text-input:hover{box-shadow:0 0 0 2px #17d2ad}div.item2 .input-wrapper .text-input:focus{box-shadow:0 0 0 2px #ff4500}div.item2 .input-wrapper .clear-button{position:absolute;right:60px;top:19vh;padding:5px;border-radius:50%;background:#333;border:none;font-size:20px;cursor:pointer;color:#ccc;display:none}div.item2 .input-wrapper .clear-button:hover{font-weight:700;background:#595959;color:#fff}div.item2 .input-wrapper .input-actions{display:flex;flex-direction:column;margin-left:.5vw;margin-right:.5vw}div.item2 .input-wrapper .input-actions .clear-input,div.item2 .input-wrapper .input-actions .send-input,div.item2 .input-wrapper .input-actions .send2-input{box-sizing:border-box;background-color:#333;color:#fff;border:none;padding:10px;cursor:pointer;border-radius:50%;width:40px;height:40px;margin-bottom:5px;transition:background-color .3s}div.item2 .input-wrapper .input-actions .send-input{background:#992900}div.item2 .input-wrapper .input-actions .send-input:hover{background:#ff4500}div.item2 .input-wrapper .input-actions .send2-input{background:#0d7661}div.item2 .input-wrapper .input-actions .send2-input:hover{background:#14bb9a}div.item2 .input-wrapper .input-actions .clear-input{background:#333;color:#e6e6e6}div.item2 .input-wrapper .input-actions .clear-input:hover{background:#595959;color:#33e9c5}.menu-open .container{margin-left:16vw}.menu-open .menu-box{left:0!important}div.menu-h{background-color:#1a1a1a;position:fixed;top:0;left:0;width:100vw;height:4.5vh;padding:0;margin:0;outline:0;box-shadow:0 0 0 2px #4d4d4d;z-index:100}div.menu-h .release{background:inherit;color:#ff6a33;font-weight:700;margin-left:57vw;margin-top:.5vh}div.menu-h .menu-btn{appearance:none}div.menu-h .menu-btn:checked+.menu-icon{border:1px solid #333}div.menu-h .menu-btn:checked+.menu-icon .nav-icon{transform:rotate(45deg)}div.menu-h .menu-btn:checked+.menu-icon .nav-icon::before{top:0}div.menu-h .menu-btn:checked+.menu-icon .nav-icon::after{top:0;transform:rotate(90deg)}div.menu-h .menu-icon{box-sizing:border-box;background-color:inherit;display:block;position:absolute;margin-left:2vw;top:0;left:0;width:4vw;height:4.5vh;cursor:pointer;padding:2px;z-index:1}div.menu-h .menu-icon:hover .nav-icon,div.menu-h .menu-icon:hover .nav-icon::after,div.menu-h .menu-icon:hover .nav-icon::before{background-color:#33e9c5}div.menu-h .menu-icon .nav-icon{background-color:#aea7a7;display:block;position:absolute;top:14px;left:0;width:25px;height:2px;transition-duration:.25s}div.menu-h .menu-icon .nav-icon::after,div.menu-h .menu-icon .nav-icon::before{content:"";position:absolute;left:0;background-color:inherit;width:inherit;height:inherit}div.menu-h .menu-icon .nav-icon::before{top:-8px}div.menu-h .menu-icon .nav-icon::after{top:8px}div.menu-h .head-wrapper{position:absolute;top:0;left:5vw;height:4vh;padding:0;margin:0;display:inline-flex;flex-direction:row;flex-wrap:nowrap;align-items:center;justify-content:flex-start}div.menu-h .head-wrapper .help,div.menu-h .head-wrapper .log,div.menu-h .head-wrapper .upload,div.menu-h .head-wrapper .upload-dir{margin-top:2px;margin-left:30px;margin-right:0;padding:5px 5px 0;border:none;cursor:pointer;border-radius:20%;font-size:20px;color:#fff;background:#333;max-height:4vh}div.menu-h .head-wrapper .help:hover,div.menu-h .head-wrapper .log:hover,div.menu-h .head-wrapper .upload-dir:hover,div.menu-h .head-wrapper .upload:hover{background:#595959}div.menu-h .upload,div.menu-h .upload-dir{transition:background-color .3s,transform .3s}div.menu-h .upload .icon,div.menu-h .upload-dir .icon{fill:#FFFFFF;width:24px;height:24px}div.menu-h .upload .icon:hover,div.menu-h .upload-dir .icon:hover{fill:#33e9c5}div.menu-h .log{font-size:14px!important;font-weight:400!important;background:#992900!important}div.menu-h .log:hover{background:#cc3700!important}div.menu-h .log.active{background:#0d7661!important}div.menu-h .log.active:hover{background:#12a487!important}div.menu-h div.menu-box{position:fixed;top:5vh;left:-2000px;height:95vh;width:16vw;transition:left .3s ease-out;padding:1vh 0 0 .5vw;z-index:101;background:#0d0d0d;box-sizing:border-box;outline:0;box-shadow:0 0 0 2px #4d4d4d;display:flex;flex-direction:column;flex-wrap:nowrap;justify-content:flex-start;align-items:stretch;overflow-y:auto;overflow-x:auto}div.menu-h div.menu-box ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;border-top:1px solid #333}div.menu-h div.menu-box ul li{border-left:1px solid #333;border-right:1px solid #333;border-bottom:1px solid #333}div.menu-h div.menu-box ul li a{color:#fff;font-size:14px;font-family:arial,verdana,Helvetica,sans-serif;font-weight:400;display:block;margin:0;padding:2px 2px 2px 0;text-align:left;text-decoration:none}div.menu-h div.menu-box ul li:hover{text-decoration:underline;background-color:#333;color:#33e9c5}div.menu-h div.menu-box ul a.delete{text-align:center;font-weight:700;font-style:italic;color:#000;background:#b3a80b}div.menu-h div.menu-box ul a.help{text-align:center;font-weight:700;font-style:italic;color:#000;background:#cc3700}div.menu-h div.menu-box ul li.show{background:#000;color:#fff;width:100%;text-align:center;box-sizing:border-box}div.menu-h div.menu-box ul li.show:hover{text-decoration:none}.window-text{position:relative;top:0;left:0;background:#1a1a1a;color:#fff;border:none;padding:0 2px 2px;width:78vw;height:80vh;border-radius:10px;box-sizing:border-box;outline:0;box-shadow:0 0 0 2px #b3a80b;overflow-y:auto}.window-text pre.pre-text{color:#f8f292;white-space:pre-wrap;word-wrap:break-word;font-family:Georigia,"Ties New Roman",serif;font-size:18px;line-height:1.6;padding:2px;margin:0;text-align:left}.window-text div.text{font-size:18px;font-weight:400;padding-left:10px;padding-right:10px;margin:0}.window-text div.text pre{white-space:pre-wrap;word-wrap:break-word;font-family:arial,verdana,Helvetica,sans-serif;font-size:18px;line-height:1.3;padding:0 5px;margin:0;text-align:left}.window-text div.text .center{text-align:center;font-size:18px;font-weight:700;text-decoration:underline;font-style:italic;color:#e3d50e}.window-text div.text div{font-family:arial,verdana,Helvetica,sans-serif;font-size:18px;font-weight:700;padding-top:0;padding-bottom:0}.window-text div.text div a{background:#000;color:#fff;font-weight:400}.window-text div.text div a:hover{background:#333;color:#fff}.window-text div.text p{font-size:18px;font-weight:400;font-family:arial,verdana,Helvetica,sans-serif;text-align:justify;padding-bottom:9px;padding-right:0;padding-left:10px}.btn-wrapper{width:100%;height:2vw;position:sticky;top:0;padding:0;background:#262626}.btn-wrapper .btn-copy{position:absolute;top:1px;right:5vw;box-sizing:border-box;background:inherit;color:#fff;border:none;cursor:pointer;width:30px;margin:0;padding:0;transition:background-color .3s}.btn-wrapper .btn-copy:hover{background-color:#595959}.btn-wrapper .btn-copy .copy-icon{fill:#e6e6e6;width:20px;height:20px}.btn-wrapper .btn-copy .copy-icon:hover{fill:#33e9c5;background:#404040}.btn-wrapper .btn-close{position:absolute;top:0;right:2vw;margin:0;background-color:transparent;border:none;color:#e6e6e6;font-size:22px;font-weight:700;cursor:pointer;outline:0}.btn-wrapper .btn-close:hover{color:#33e9c5;background:#404040}.msg{box-sizing:border-box;position:fixed;width:300px;height:100px;top:50%;left:50%;transform:translate(-50%,-50%);background-color:#222;color:#ffeb3b;border:2px solid #ffeb3b;border-radius:15px;display:flex;align-items:center;justify-content:center;font-family:Arial,sans-serif;font-size:24px;font-weight:700;text-align:center;z-index:1000;box-shadow:0 4px 8px rgba(0,0,0,.2)}.alert,.confirm{background-color:#303030!important;color:#fff;padding:20px;border-radius:4px;box-shadow:0 2px 4px #00000033!important}.alert .button,.confirm .button{background-color:#37474f!important;color:#fff;border:none;padding:10px 20px;border-radius:4px;cursor:pointer;margin-top:20px}.alert .button:hover,.confirm .button:hover{background-color:#222c31}
static/data/aaron_swartz.txt ADDED
The diff for this file is too large to render. See raw diff
 
static/data/aristotele_detective.txt ADDED
The diff for this file is too large to render. See raw diff
 
static/data/help_test.html ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="text">
2
+ <br>
3
+ <div><a href="#" onCLick="esempio('aaron_swartz.txt');">Aaron Swartz</a></div>
4
+ <br>
5
+ <div><a href="#" onCLick="esempio('roberto_busa.txt');">Roberto Busa</a></div>
6
+ <br>
7
+ <div><a href="#" onCLick="esempio('la_cattedrale_e_il_bazaar.txt');">La cattedrale e il Bazar</a></div>
8
+ <br>
9
+ <div><a href="#" onCLick="esempio('aristotele_detective.txt');">Aristotele Detective</a></div>
10
+ <br>
11
+ <div><a href="#" onCLick="esempio('montecristo.txt');">Montecristor</a></div>
12
+ <br>
13
+ <div><a href="#" onCLick="esempio('il_libro_rosso.txt');">Il libro rosso</a></div>
14
+ <br>
15
+ <div><a href="#" onCLick="esempio('lettere_musulmane.txt');">Lettere Mussulmane</a></div>
16
+
17
+ <!--
18
+ aaron_swartz.txt
19
+ aristotele_detective.txt
20
+ il_libro_rosso.txt
21
+ la_cattedrale_e_il_bazaar.txt
22
+ lettere_musulmane.txt
23
+ montecristo.txt
24
+ roberto_busa.txt
25
+ -->
static/data/il_libro_rosso.txt ADDED
The diff for this file is too large to render. See raw diff
 
static/data/la_cattedrale_e_il_bazaar.txt ADDED
@@ -0,0 +1,804 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ La cattedrale e il bazaar
2
+
3
+ di Eric S. Raymond
4
+ (22/11/1998 ore 04:01:20)
5
+ Quella che segue è la mia analisi di un progetto open source di successo, fetchmail, deliberatamente
6
+ utilizzato come test specifico per la verifica di alcune sorprendenti teorie sullo sviluppo del software
7
+ suggerite dalla storia di Linux. Le mie argomentazioni su tali teorie mettono a confronto due diversi stili di
8
+ sviluppo, il modello “cattedrale” in voga in gran parte del mondo commerciale, opposto al modello
9
+ “bazaar” del mondo Linux. Da qui passo poi a dimostrare come tali modelli derivino da premesse
10
+ divergenti sulla natura dell'attività di debugging del software. Arrivo quindi a stabilire la validità
11
+ dell'esperienza di Linux riguardo l'affermazione “Con molti occhi puntati addosso, ogni bug diventa una
12
+ bazzecola”, per suggerire analogie produttive con altri sistemi di agenti indipendenti in grado di auto-
13
+ correggersi, concludendo infine con una serie di riflessioni sulle implicazioni di queste analisi per il futuro
14
+ del software.
15
+
16
+ 1. La cattedrale e il bazaar
17
+ Linux è sovversivo. Chi avrebbe potuto pensare appena cinque anni fa che un sistema operativo di livello
18
+ mondiale sarebbe emerso come per magia dal lavoro part-time di diverse migliaia di hacker e sviluppatori
19
+ sparsi sull'intero pianeta, collegati tra loro solo grazie ai tenui cavi di Internet?
20
+ Certamente non il sottoscritto. Quando Linux fece la sua comparsa nel mio raggio d'azione all'inizio del
21
+ 1993, mi ero occupato dello sviluppo di Unix e di software open source per dieci anni. Ero stato uno dei
22
+ primi collaboratori al progetto GNU a metà anni '80. Avevo distribuito su Internet un buon numero di
23
+ software open source, realizzando da solo o in collaborazione con altri parecchi programmi (nethack,
24
+ Emacs VC e GUD, xlife, etc.) ancor'oggi ampiamente utilizzati. Pensavo di sapere come bisognasse fare.
25
+ Linux stravolse gran parte di quel che credevo di sapere. Per anni avevo predicato il vangelo Unix degli
26
+ strumenti agili, dei prototipi immediati e della programmazione evolutiva. Ma ero anche convinto che
27
+ esistesse un punto critico di complessità al di sopra del quale si rendesse necessario un approccio
28
+ centralizzato e a priori. Credevo che il software più importante (sistemi operativi e strumenti davvero
29
+ ingombranti come Emacs) andasse realizzato come le cattedrali, attentamente lavorato a mano da
30
+ singoli geni o piccole bande di maghi che lavoravano in splendido isolamento, senza che alcuna versione
31
+ beta vedesse la luce prima del momento giusto.
32
+ Rimasi non poco sorpreso dallo stile di sviluppo proprio di Linus Torvalds – diffondere le release presto e
33
+ spesso, delegare ad altri tutto il possibile, essere aperti fino alla promiscuità. Nessuna cattedrale da
34
+ costruire in silenzio e reverenza. Piuttosto, la comunità Linux assomigliava a un grande e confusionario
35
+ bazaar, pullulante di progetti e approcci tra loro diversi (efficacemente simbolizzati dai siti contenenti
36
+ l'archivio di Linux dove apparivano materiali prodotti da chiunque). Un bazaar dal quale soltanto una
37
+ serie di miracoli avrebbe potuto far emergere un sistema stabile e coerente.
38
+ Il fatto che questo stile bazaar sembrasse funzionare, e anche piuttosto bene, mi colpì come uno shock.
39
+ Mentre imparavo a prenderne le misure, lavoravo sodo non soltanto sui singoli progetti, ma anche
40
+ cercando di comprendere come mai il mondo Linux non soltanto non cadesse preda della confusione più
41
+ totale, ma al contrario andasse rafforzandosi sempre più a una velocità a malapena immaginabile per
42
+ quanti costruivano cattedrali.
43
+ Fu verso la metà del 1996 che mi parve d'essere sul punto di capirne il perché. Il destino mi offrì
44
+ l'occasione propizia per mettere alla prova la mia teoria, sotto forma di un progetto open source del quale
45
+ decisi di occuparmi usando coscientemente lo stile bazaar. Ci provai, e il successo ottenuto fu piuttosto
46
+ significativo.
47
+ Nella parte restante di questo saggio, racconto la storia di quel progetto, usandola per proporre alcuni
48
+ aforismi sull'efficacia dello sviluppo open source. Non che li abbia imparati tutti dal mondo Linux, ma
49
+ vedremo come le modalità offerte da quest'ultimo siano del tutto peculiari. Se non ho interpretato male,
50
+ questi aforismi ci aiuteranno a comprendere con esattezza cos'è che rende la comunità Linux una
51
+ sorgente così copiosa di buon software – e aiuteranno tutti noi a divenire più produttivi.
52
+ 2. La posta deve passare
53
+ Dal 1993 mi occupo del lato tecnico di un piccolo provider Internet gratuito chiamato Chester County
54
+ InterLink (CCIL) in West Chester, Pennsylvania (sono tra i fondatori di CCIL e autore del software
55
+ specifico per il nostro bulletin-board multiutenti – si può dare un'occhiata facendo telnet su locke.ccil.org .
56
+ Ora dà accesso a quasi tremila utenti su trenta linee). Grazie a questo lavoro posso collegarmi a Internet
57
+ per 24 ore al giorno con una linea a 56K di CCIL – in realtà, è proprio quel che mi viene richiesto!
58
+ Di conseguenza sono ormai abituato alle email istantanee. Per vari motivi, era difficile far funzionare la
59
+ connessione SLIP tra la mia macchina a casa (snark.thyrsus.com) e CCIL. Quando finalmente ci sono
60
+ riuscito, mi dava fastidio dover fare ogni tanto telnet su locke per controllare la posta. Volevo fare in
61
+ modo che i messaggi arrivassero direttamente su snark così da esserne tempestivamente avvisato e
62
+ poterli gestire a livello locale.
63
+ Il semplice “sendmail forwarding” non avrebbe funzionato, perché la mia macchina personale non è
64
+ sempre online e non ha un indirizzo IP statico. Mi serviva un programma in grado di raggiungere la
65
+ connessione SLIP e tirar via la posta per farla arrivare localmente. Sapevo dell'esistenza di simili cose, e
66
+ del fatto che in genere facevano uso di un semplice protocollo noto come POP (Post Office Protocol). E
67
+ sicuramente doveva già esserci un server POP3 incluso nel sistema operativo BSD/OS di locke.
68
+ Mi serviva un client POP3. Ne ho localizzato subito uno online. Anzi, ne ho trovati tre o quattro. Per un
69
+ po' ho usato un pop-perl, ma era privo di quella che pareva una funzione ovvia, la capacità di effettuare
70
+ un “hacking degli indirizzi della posta prelevata in modo che il reply funzionasse correttamente.
71
+ Questo il problema: supponiamo di ricevere un messaggio da qualcuno di nome 'joe' su locke. Se lo
72
+ inoltro su snark e poi cerco di fare reply, il mio programma di posta proverebbe simpaticamente a inviarlo
73
+ a un inesistente 'joe' su snark. Modificare a mano ogni indirizzo per aggiungere “@ccil.org” diventerebbe
74
+ in un attimo un problema serio.
75
+ Chiaramente questa era un'operazione che toccava fare al computer per conto mio. Ma nessuno dei
76
+ client POP esistenti sapeva come! E questo ci porta alla prima lezione:
77
+ 1. Ogni buon lavoro software inizia dalla frenesia personale di uno sviluppatore.
78
+ Forse ciò avrebbe dovuto risultare ovvio (è risaputo da tempo che “la necessità è la madre di tutte le
79
+ invenzioni”), ma troppo spesso gli sviluppatori trascorrono le giornate impegnati a guadagnarsi da vivere
80
+ con programmi di cui non hanno alcun bisogno e che non apprezzano. Ma non nel mondo Linux – il che
81
+ spiega l'alta qualità media del software originato dalla comunità Linux.
82
+ Mi sono forse lanciato in un'attività frenetica per scrivere il codice di un client POP3 nuovo di zecca in
83
+ grado di competere con quelli esistenti? Nemmeno per sogno! Ho esaminato attentamente le utility POP
84
+ che avevo in mano, chiedendomi: “qual'è la più vicina a quel che sto cercando?” Perché:
85
+ 2. I bravi programmatori sanno cosa scrivere. I migliori sanno cosa riscrivere (e riusare).
86
+ Pur non ritenendomi un programmatore tra i più bravi, cerco di imitarli. Importante caratteristica di costoro
87
+ è una sorta di ozio costruttivo. Sanno che si ottiene il meglio non per le energie impiegate ma per il
88
+ risultato raggiunto, e che quasi sempre è più facile iniziare da una buona soluzione parziale piuttosto che
89
+ dal nulla assoluto.
90
+ Linus Torvalds, per esempio, non ha mai cercato di riscrivere Linux da zero. È invece partito riutilizzando
91
+ codici e idee riprese da Minix, piccolo sistema operativo per macchine 386 assai simile a Unix. Alla fine il
92
+ codice Minix è scomparso oppure è stato completamente riscritto – ma per il tempo che è rimasto lì
93
+ presente è servito come impalcatura per l'infante che sarebbe infine divenuto Linux.
94
+ Con lo stesso spirito, mi sono messo a cercare una utility POP basata su codici ragionevolmente ben
95
+ fatti, da utilizzare come base di sviluppo.
96
+ La tradizione di condivisione dei codici tipica del mondo Unix ha sempre favorito il riutilizzo dei sorgenti
97
+ (questo il motivo per cui il progetto GNU ha scelto come sistema operativo di base proprio Unix,
98
+ nonostante alcune serie riserve sullo stesso). Il mondo Linux ha spinto questa tradizione vicina al suo al
99
+ limite tecnologico; sono generalmente disponibili terabyte di codice open source. È quindi probabile che,
100
+ impiegando del tempo a cercare il lavoro di qualcuno quasi ben fatto, si ottengano i risultati voluti. E ciò
101
+ vale assai più nel mondo Linux che altrove.
102
+ Proprio quel che è successo a me. Conteggiando i programmi trovati prima, con la seconda ricerca
103
+ ottenni un totale di nove candidati – fetchpop, PopTart, get-mail, gwpop, pimp, pop-perl, popc, popmail e
104
+ upop. Il primo su cui mi sono concentrato è stato 'fetchpop' di Seung-Hong Oh. Ho inserito l'opzione
105
+ “header-rewrite” e ho apportato altri miglioramenti, poi accettati dall'autore nella release 1.9.
106
+ Alcune settimane dopo, però, mi sono imbattuto nel codice di 'popclient' scritto da Carl Harris, ed mi sono
107
+ trovato di fronte a un problema. Pur offrendo alcune buone idee originali (come la modalità “daemon”),
108
+ fetchpop poteva gestire solo POP3 e il codice rifletteva un certo approccio da dilettante (Seung-Hong era
109
+ un programmatore brillante ma inesperto, ed entrambe le qualità risultavano evidenti). Il codice di Carl
110
+ era migliore, alquanto professionale e solido, ma il suo programma difettava di varie opzioni presenti in
111
+ fetchpop, opzioni importanti e piuttosto complesse da implementare (incluse quelle aggiunte dal
112
+ sottoscritto).
113
+ Restare o cambiare? Nel secondo caso avrei buttato via il codice che avevo già scritto in cambio di una
114
+ migliore base di sviluppo.
115
+ Un motivo pratico per passare all'altro programma era il supporto per protocolli multipli. POP3 è il più
116
+ usato tra i server per l'ufficio postale, ma non è il solo. Fetchpop e l'altro rivale non avevano POP2,
117
+ RPOP, o APOP, e io stesso stavo meditando, giusto per divertimento, l'aggiunta di IMAP (Internet
118
+ Message Access Protocol, il protocollo per l'ufficio postale più recente e più potente).
119
+ Avevo però altri motivi teorici per ritenere una buona idea il fatto di cambiare, qualcosa che avevo
120
+ imparato molto tempo prima di Linux.
121
+ 3. “Preparati a buttarne via uno; dovrai farlo comunque.” (Fred Brooks, “The Mythical Man-Month”,
122
+ Capitolo 11)
123
+ In altri termini, spesso non si riesce a comprendere davvero un problema fino alla prima volta in cui si
124
+ prova a implementarne la soluzione. La seconda volta forse se ne sa abbastanza per riuscirci. Per
125
+ arrivare alla soluzione, preparati a ricominciare almeno una volta.
126
+ Be', mi son detto, la mia prima volta erano state le modifiche a fetchpop. Adesso era ora di cambiare, e
127
+ così feci.
128
+ Dopo aver mandato a Carl Harris il 25 Giugno 1996 una prima serie di aggiustamenti per popclient, mi
129
+ resi conto che da qualche tempo egli aveva perso interesse nel programma. Il codice era un po'
130
+ polveroso, con vari bug in giro. Avrei dovuto fare molte modifiche, e ci mettemmo rapidamente d'accordo
131
+ sul fatto che la cosa più logica fosse che il programma passasse in mano mia.
132
+ Senza che me ne accorgessi più di tanto, il progetto era cresciuto parecchio. Non mi stavo più
133
+ occupando soltanto di sistemare i piccoli difetti di un client POP già esistente. Mi ero addossato l'intera
134
+ gestione di un programma, e mi venivano in mente delle idee che avrebbero probabilmente portato a
135
+ modifiche radicali.
136
+ In una cultura del software che incoraggia la condivisione del codice, non si trattava altro che della
137
+ naturale evoluzione di un progetto. Questi i punti-chiave:
138
+ 4. Se hai l'atteggiamento giusto, saranno i problemi interessanti a trovare te.
139
+ Ma l'atteggiamento di Carl Harris risultò perfino più importante. Fu lui a comprendere che:
140
+ 5. Quando hai perso interesse in un programma, l'ultimo tuo dovere è passarlo a un successore
141
+ competente.
142
+ Senza neppure parlarne, io e Carl sapevamo di perseguire il comune obiettivo di voler raggiungere la
143
+ soluzione migliore. L'unica questione per entrambi era stabilire se le mie fossero mani fidate. Una volta
144
+ concordato su questo, egli agì con gentilezza e prontezza. Spero di comportarmi altrettanto bene quando
145
+ verrà il mio turno.
146
+ 3. L'importanza di avere utenti
147
+ E così ho ereditato popclient. Fatto parimenti importante, ho ereditato gli utenti di popclient. Importante
148
+ non soltanto perché la loro esistenza testimonia che stai rispondendo a un loro bisogno, che hai fatto
149
+ qualcosa di buono. Coltivati in maniera appropriata, gli utenti possono trasformarsi in co-sviluppatori.
150
+ Altro punto di forza della tradizione Unix, portato felicemente agli estremi da Linux, è che molti utenti
151
+ sono essi stessi degli hacker. Ed essendo i sorgenti disponibili a tutti, posso diventare degli hacker molto
152
+ efficaci. Qualcosa di tremendamente utile per ridurre il tempo necessario al debugging. Con un po'
153
+ d'incoraggiamento, ogni utente è in grado di diagnosticare problemi, suggerire soluzioni, aiutare a
154
+ migliorare il codice in maniera impensabile per una persona sola.
155
+ 6. Trattare gli utenti come co-sviluppatori è la strada migliore per ottenere rapidi miglioramenti del codice
156
+ e debugging efficace.
157
+ È facile sottovalutare la potenza di un simile effetto. In realtà un po' tutti noi del mondo open source
158
+ eravamo soliti sottovalutare drasticamente il fatto che tale potenza crescesse di pari passo con il numero
159
+ degli utenti e con la complessità del sistema. Finché Linus Torvalds ci ha mostrato le cose in maniera
160
+ diversa.
161
+ In realtà ritengo che la mossa più scaltra e consequenziale di Linus non sia stata la costruzione del
162
+ kernel di Linux in sé, bensì la sua invenzione del modello di sviluppo di Linux. Quando ho espresso
163
+ questo mio pensiero in sua presenza, sorridendo ha ripetuto con calma quel che va spesso affermando:
164
+ “Praticamente sono una persona molto pigra cui piace prendersi il merito di quel che sono gli altri a fare.”
165
+ Pigro come una volpe. Oppure, come avrebbe detto Robert Heinlein, troppo pigro per fallire.
166
+ Guardando all'indietro, un precedente per i metodi e il successo di Linux può esser trovato nello sviluppo
167
+ della libreria Lisp GNU e per gli archivi del codice Lisp di Emacs. In opposizione allo stile di costruzione a
168
+ cattedrale del nucleo centrale in C di Emacs e di gran parte di altri strumenti della Free Software
169
+ Foundation (FSF), l'evoluzione del codice Lisp risultò assai fluida e guidata dagli utenti. Idee e prototipi
170
+ vennero spesso riscritti tre o quattro volte prima di raggiungere una forma stabile e definitiva. E le
171
+ collaborazioni estemporanee tra due o più persone consentite da Internet, alla Linux, erano evento
172
+ frequente.
173
+ Non a caso il mio caso di “hack” precedente a fetchmail fu probabilmente la modalità Emacs VC, una
174
+ collaborazione via email secondo lo stile Linux con altre tre persone, soltanto una delle quali (Richard
175
+ Stallman, autore di Emacs e fondatore della FSF http://www.fsf.org) ho poi avuto occasione di incontrare
176
+ dal vivo. Si trattava di realizzare il frontale per SCCS, RCS e più tardi CVS dall'interno di Emacs, dotato
177
+ di opzioni a “one-touch” per le operazioni di controllo. Ciò ha preso avvio da un minuto, crudo sccs.el
178
+ scritto da qualcun altro. E lo sviluppo di VC ha avuto successo perché, al contrario dello stesso Emacs, il
179
+ codice
180
+ di
181
+ Lisp
182
+ riuscì
183
+ a
184
+ passare
185
+ molto
186
+ rapidamente
187
+ tra
188
+ diverse
189
+ generazioni
190
+ di
191
+ distribuzione/test/miglioramenti.
192
+ 4. Distribuire presto e spesso
193
+ Elemento centrale del processo di sviluppo di Linux è la rapida e frequente distribuzione delle varie
194
+ release. La maggior parte degli sviluppatori (incluso il sottoscritto) aveva sempre considerato negativa
195
+ questa usanza per progetti appena più che minimi, poiché le versioni iniziali sono piene di bug quasi per
196
+ definizione e non pareva il caso di far spazientire inutilmente gli utenti.
197
+ Tale opinione era rinforzata dalla generale aderenza allo stile di sviluppo della costruzione a cattedrale.
198
+ Se l'obiettivo finale era quello di far vedere meno bug possibili agli utenti, allora conveniva distribuire una
199
+ nuova release ogni sei mesi (o ancora meno frequentemente) e lavorare duramente sul debugging tra
200
+ una release e l'altra. Fu seguendo questo processo che venne sviluppato il nucleo centrale in C di
201
+ Emacs. Ma non fu così per la libreria Lisp –perché erano attivi archivi Lisp al di fuori del controllo della
202
+ FSF, dove era invece possibile trovare versioni di codice nuovo e in fase di sviluppo indipendentemente
203
+ dal ciclo di release di Emacs.
204
+ Il più importante di tali archivi, l'archivio elisp dell'Ohio State, anticipava lo spirito e molte delle
205
+ caratteristiche tipiche dei grandi archivi su Linux di oggi. Ma pochi di noi si resero davvero conto di quel
206
+ che stavamo facendo, o di come l'esistenza stessa di quell'archivio paresse rispondere ai problemi insiti
207
+ nel modello di sviluppo della costruzione a cattedrale della FSF. Verso il 1992 ho provato a far confluire
208
+ formalmente gran parte del codice dell'Ohio nella libreria ufficiale Lisp di Emacs. Mi sono trovato
209
+ politicamente nei guai e di fronte a un chiaro insuccesso.
210
+ Ma l'anno seguente, mentre Linux diventava ampiamente visibile, fu chiaro come stesse accadendo
211
+ qualcosa di assai diverso e più salutare. La policy di sviluppo aperto di Linus rappresentava l'esatto
212
+ opposto della costruzione a cattedrale. Gli archivi di sunsite e tsx-11 stavano moltiplicandosi, le
213
+ distribuzioni multiple andavano proliferando. E tutto ciò sotto la spinta della diffusione, con una frequenza
214
+ mai vista prima, delle varie release.
215
+ Linus trattava gli utenti al pari di co-sviluppatori nella maniera più efficace possibile:
216
+ 7. Distribuisci presto. Distribuisci spesso. E presta ascolto agli utenti.
217
+ L'innovazione introdotta da Linus non consisteva tanto nel seguire questa pratica (qualcosa di simile
218
+ faceva parte da molto tempo della tradizione del mondo Unix), quanto piuttosto nel farla crescere a un
219
+ tale livello d'intensità da raggiungere la medesima complessità del lavoro di programmazione che stava
220
+ facendo. A quei tempi (intorno al 1991) non era raro che egli diffondesse versioni del nuovo kernel anche
221
+ più di una volta al giorno! Qualcosa che poté funzionare grazie all'attenzione dedicata ai co-sviluppatori e
222
+ all'ampio utilizzo di Internet come strumento di collaborazione.
223
+ Ma come funzionava? Era qualcosa che avrei potuto duplicare, o tutto dipendeva esclusivamente dal
224
+ genio di Linus Torvalds?
225
+ No, non lo credevo. Certo, Linus è un gran bell'hacker (quanti di noi saprebbero realizzare per intero un
226
+ sistema operativo di qualità?). Ma a livello concettuale Linux non rappresentava alcun significativo salto
227
+ in avanti. Linus non è (almeno, non ancora) quel genio innovativo del design allo stesso modo, ad
228
+ esempio, di Richard Stallman o James Gosling (di NeWS e Java). Piuttosto, Linus mi sembrava un genio
229
+ dell'engineering, dotato di un sesto senso per evitare bug e strade senza uscita, oltre che di un ottimo
230
+ fiuto per arrivare dal punto A al punto B con il minimo sforzo possibile. Non a caso l'intero design di Linux
231
+ trasuda queste qualità e rispecchia l'approccio essenzialmente conservativo e semplificativo tipico di
232
+ Linus.
233
+ Se, quindi, la rapida diffusione delle release e il pieno sfruttamento del medium Internet non erano
234
+ casuali, bensì parti integranti delle visioni da genio dell'engineering di Linus lungo il cammino del minimo
235
+ sforzo possibile, cos'era che stava amplificando? Cos'è che riusciva a tirar fuori da tutto questo gran
236
+ daffare?
237
+ Messa così, la domanda si risponde da sola. Linus tendeva a stimolare e ricompensare costantemente i
238
+ suoi hacker/utenti – stimolati dalla soddisfazione di sé per aver preso parte all'azione, ricompensati dalla
239
+ vista dei miglioramenti costanti (perfino giornalieri) ottenuti nel loro lavoro.
240
+ Linus puntava direttamente a massimizzare il numero di ore/uomo coinvolte nello sviluppo e nel
241
+ debugging, rischiando perfino la possibile instabilità del codice e l'estinguersi del contributo degli utenti
242
+ qualora fosse risultato impossibile tener traccia di qualche serio bug. Linus si comportava seguendo una
243
+ concezione più o meno riassumibile come segue:
244
+ 8. Stabilita una base di beta-tester e co-sviluppatori sufficientemente ampia, ogni problema verrà
245
+ rapidamente definito e qualcuno troverà la soluzione adeguata.
246
+ O, in modo meno formale, “Dato un numero sufficiente di occhi, tutti i bug vengono a galla”. Io la chiamo
247
+ la “Legge di Linus”.
248
+ La mia formulazione originale era che ogni problema “diventerà trasparente per qualcuno”. Linus fece
249
+ notare come la persona che si rende conto e risolve il problema non necessariamente né di norma è la
250
+ stessa persona che per prima lo mette a fuoco. “Qualcuno scopre il problema,” dice Linus, “e qualcun
251
+ altro lo comprende. E secondo me il compito più difficile è proprio trovarlo”. Ma il punto è che entrambe le
252
+ cose tendono ad accadere piuttosto rapidamente.
253
+ Questa ritengo che sia la differenza fondamentale tra lo stile a cattedrale e quello a bazaar. Nel primo
254
+ caso la visualizzazione dei problemi relativi a programmazione, bug e sviluppo costituiscono fenomeni
255
+ dubbi, insidiosi, complessi. Servono mesi di scrutinio ravvicinato da parte di più d'uno per poi sentirsi
256
+ sicuri di aver risolto tutti i problemi. Da qui i lunghi intervalli tra le release, e l'inevitabile delusione quando
257
+ le versioni così a lungo attese si rivelano imperfette.
258
+ Nella concezione a bazaar, d'altra parte, si dà per scontato che generalmente i bug siano fenomeni
259
+ marginali – o che almeno divengano rapidamente tali se esposti all'attenzione di migliaia di volenterosi
260
+ co-sviluppatori che soppesano ogni nuova release. Ne consegue la rapidità di diffusione per ottenere
261
+ maggiori correzioni, e come positivo effetto collaterale, c'è meno da perdere se viene fuori qualche toppa
262
+ raffazzonata.
263
+ Tutto qui. E non è certo poco. Se la “Legge di Linus” è falsa, allora ogni sistema complesso tanto quanto
264
+ il kernel Linux, ricavato grazie al lavoro collettivo delle molte mani che lo hanno messo insieme, a un
265
+ certo punto avrebbe dovuto crollare sotto il peso di interazioni negative impreviste e di “profondi” bug non
266
+ scoperti. Se invece è vera, allora è sufficiente a spiegare la relativa assenza di bug di Linux.
267
+ E forse ciò non dovrebbe rappresentare affatto una sorpresa. Qualche anno addietro sono stati i
268
+ sociologi a scoprire che l'opinione media di un gruppo di osservatori equamente esperti (o equamente
269
+ ignoranti) si rivela parametro assai più affidabile di quella di un solo osservatore scelto casualmente in
270
+ quel gruppo. Si tratta del cosiddetto “effetto Delfi”. Ora sembra che Linus abbia dimostrato come ciò vada
271
+ applicato anche all'operazione di debugging di un sistema operativo – ovvero che l'effetto Delfi è in grado
272
+ di addomesticare la complessità della programmazione, persino la complessità del kernel di un sistema
273
+ operativo.
274
+ Sono in debito con Jeff Dutky dutky@wam.umd.edu per aver sottolineato come la Legge di Linus possa
275
+ essere definita anche: “Il debugging è parallelizzabile”. Jeff fa notare come nel corso dell'intero processo,
276
+ pur richiedendo il coordinamento di uno sviluppatore che curi le comunicazioni tra quanti si occupano del
277
+ debugging, questi ultimi invece non richiedono particolare coordinamento. In tal modo non si cade preda
278
+ della notevole complessità e dei costi gestionali imposti dal coinvolgimento di nuovi sviluppatori.
279
+ In pratica, nel mondo Linux la perdita di efficienza a livello teorico, dovuta alla duplicazione di lavoro da
280
+ parte di quanti seguono il debugging, non arriva quasi mai a rappresentare un problema. Uno degli effetti
281
+ della policy “distribuire presto e spesso” è proprio quello di minimizzare tale duplicazione di lavoro
282
+ propagando rapidamente le soluzioni giunte col feedback degli utenti.
283
+ Anche Brooks ha fatto un'osservazione su quanto sostenuto da Jeff: “Il costo totale per il mantenimento
284
+ di un programma ampiamente utilizzato in genere viene valutato intorno al 40 per cento, o più, del costo
285
+ dello sviluppo. Non senza sorpresa, tale costo viene notevolmente influenzato dal numero di utenti
286
+ coinvolti. Maggiori sono questi ultimi, più bug si trovano.”
287
+ Ciò per via del fatto che con un maggior numero di utenti ci sono più modi differenti di verificare il
288
+ programma. Un effetto amplificato quando costoro sono anche co-sviluppatori. Ciascuno affronta il
289
+ compito della definizione dei bug con un approccio percettivo e analitico leggermente differente, una
290
+ diversa angolazione per affrontare il problema. L'effetto Delfi pare funzionare esattamente sulla base di
291
+ tali differenze. Nel contesto specifico del debugging, le variazioni tendono anche a ridurre la duplicazione
292
+ degli sforzi impiegati.
293
+ Quindi, dal punto di vista dello sviluppatore, l'aggiunta di altri beta-tester può non ridurre la complessità
294
+ del bug “più profondo” attualmente sotto studio, ma aumenta la probabilità che l'approccio di qualcuno
295
+ consentirà il corretto inquadramento del problema, così che per questa persona il bug non apparirà altro
296
+ che una bazzecola.
297
+ Inoltre, in caso di seri bug, le varie versioni del kernel di Linux sono numerate in modo tale che i
298
+ potenziali utenti possano scegliere o di far girare l'ultima versione definita “stabile” oppure rischiare
299
+ d'incappare in possibili bug pur di provare le nuove funzioni. Una tattica ancora non formalmente imitata
300
+ dalla maggior parte di hacker Linux, ma che forse dovrebbe esserlo. Il fatto che entrambe le scelte siano
301
+ disponibili le rende entrambe più attraenti.
302
+ 5. Quando una rosa non è una rosa?
303
+ Dopo aver osservato il comportamento di Linus e aver elaborato una mia teoria sul perché d
304
+ el suo
305
+ successo, ho deciso coscientemente di mettere alla prova tale teoria sul mio nuovo progetto
306
+ (palesemente assai meno complesso e ambizioso).
307
+ Per prima cosa però ho semplificato parecchio popclient. Le implementazioni di Carl Harris erano
308
+ precise, ma mostravano quella complessità inopportuna comune a molti programmatori in C. Trattava il
309
+ codice come elemento centrale, considerando solo come supporto a latere la struttura dati. Come
310
+ conseguenza, il codice era eccezionale ma il design strutturale improvvisato e bruttino (almeno secondo
311
+ gli standard elevati di questo vecchio hacker di LISP).
312
+ Oltre al miglioramento del codice e del design strutturale, perseguivo comunque un altro obiettivo
313
+ nell'operazione di riscrittura. Volevo si evolvesse in qualcosa che fossi in grado di comprendere
314
+ pienamente. Non c'è alcun divertimento nel sistemare i problemi di un programma che non si comprende
315
+ appieno.
316
+ Fu così che mi ci volle tutto il primo mese soltanto per seguire le implicazioni del progetto di base di Carl.
317
+ La prima vera modifica fu l'aggiunta del supporto per IMAP. In pratica riorganizzai le macchine del
318
+ protocollo in un driver generico con tre opzioni (per POP2, POP3 e IMAP). Insieme ai cambiamenti
319
+ precedenti, ciò illustra il principio generale che ogni programmatore dovrebbe tenere bene a mente,
320
+ soprattutto lavorando con linguaggi come il C che non accettano facilmente gli inserimenti dinamici:
321
+ 9. Meglio combinare una struttura dati intelligente e un codice non eccezionale che non il contrario.
322
+ Brooks, capitolo 9: “Mostrami [il codice] e nascondimi [la struttura dati], e io continuerò a essere
323
+ disorientato. Mostrami [la struttura dati], e non avrò bisogno del [codice]; sarà del tutto ovvio.”
324
+ Per esser precisi, lui parlava di “diagrammi” e “tabelle”. Ma considerando il mutamento lessicale/culturale
325
+ di questi trent'anni, il senso rimane invariato.
326
+ A questo punto (inizio Settembre 1996, sei settimane dopo esser partito da zero), ho cominciato a
327
+ pensare all'opportunità di cambiare il nome – in fondo non si trattava più soltanto di un client POP. Ma
328
+ esitavo perché mancava ancora qualcosa di genuinamente nuovo nel design. La mia versione di
329
+ popclient doveva ancora acquisire una propria identità.
330
+ Il cambio radicale avvenne quando fetchmail imparò come fare il forward della posta prelevata verso la
331
+ porta SMTP. Lo spiego meglio tra poco. Prima però: più sopra ho parlato della decisione di usare questo
332
+ progetto come test per verificare la mia teoria sui brillanti risultati raggiunti da Linus Torvalds. Vi potreste
333
+ chiedere, in che modo l'ho messa alla prova? Ecco come:
334
+ 1. Ho diffuso le varie release presto e spesso (quasi mai a meno di dieci giorni di distanza; una volta
335
+ al giorno nei periodi d'intenso lavoro).
336
+ 2. Ho inserito nella lista dei beta chiunque mi avesse contattato riguardo fetchmail.
337
+ 3. Ho mandato simpatici messaggi all'intera lista dei beta per annunciare ogni nuova release,
338
+ incoraggiando la gente a partecipare.
339
+ 4. E ho dato ascolto ai beta tester, ponendo loro domande sul design adottato e plaudendoli ogni
340
+ volta che mi mandavano aggiustamenti e feedback.
341
+ Questi semplici accorgimenti produssero una ricompensa immediata. Fin dall'inizio del progetto, mi
342
+ arrivavano report sui bug presenti di una qualità che qualunque sviluppatore avrebbe invidiato, spesso
343
+ con buone soluzioni in attach. Ho ricevuto mail piene di critiche costruttive, lodi sperticate, suggerimenti
344
+ intelligenti. Il che ci porta a:
345
+ 10. Se tratti i beta tester come se fossero la risorsa più preziosa, replicheranno trasformandosi davvero
346
+ nella risorsa più preziosa a disposizione.
347
+ Un'interessante caratteristica del successo di fetchmail risiede nell'ampiezza dell'elenco dei beta, i
348
+ “fetchmail-friend”. Si è rapidamente raggiunta quota 249, con nuovi arrivi due o tre volte la settimana.
349
+ L'ultima revisione, fine Maggio 1997, ha rivelato che la lista andava perdendo membri, dopo aver
350
+ raggiunto un massimo di 300 nominativi, e ciò per un motivo degno di nota. In parecchi mi hanno chiesto
351
+ di essere rimossi perché fetchmail funzionava così bene che non c'era più alcun motivo di seguire il
352
+ traffico della lista! Forse anche ciò fa parte del normale ciclo di vita di un progetto maturo in stile bazaar.
353
+ 6. Popclient diventa Fetchmail
354
+ Il vero punto di svolta del progetto ebbe luogo quando Harry Hochheiser mi spedì il codice iniziale per
355
+ fare il forward alla porta SMTP della macchina client. Mi sono reso immediatamente conto che
356
+ l'implementazione affidabile di tale funzione avrebbe reso pressoché obsoleta ogni altra modalità di
357
+ consegna della posta.
358
+ Per molte settimane mi ero messo a giocare con l'interfaccia di fetchmail, passabile ma disordinata –
359
+ poco elegante e con troppe opzioni sparse tutt'intorno. Tra queste mi davano particolarmente fastidio,
360
+ anche senza capire perché, quelle utilizzate per trasferire la posta prelevata in una certa mailbox o
361
+ altrove.
362
+ Quel che mi veniva in mente pensando alla funzione del “SMTP forwarding” era che popclient voleva
363
+ cercare di far troppe cose. Era stato ideato per essere sia un “mail transport agent” (MTA) sia un “mail
364
+ delivery agent” (MDA) a livello locale. Con il forward SMTP avrebbe potuto smettere di essere un MDA
365
+ per divenire un puro MTA, trasferendo ad altri programmi la posta per la consegna locale, proprio come
366
+ fa sendmail.
367
+ Perché darsi da fare a sistemare le complesse configurazioni p
368
+ er un MDA o le impostazioni per le
369
+ mailbox, quando innanzitutto è quasi sempre garantito che la porta 25 rimane disponibile per questo su
370
+ ogni piattaforma con supporto TCP/IP? Soprattutto quando ciò significa che i messaggi prelevati
371
+ appariranno come posta SMTP normalmente inviata dal mittente, che è poi quel che stiamo cercando di
372
+ ottenere.
373
+ Ci sono diverse lezioni da trarre a questo punto. Primo, l'idea del “SMTP forwarding” era la prima grossa
374
+ ricompensa per aver tentato coscientemente di emulare i metodi di Linus. Era stato un utente a
375
+ suggerirmi questa fantastica idea – non mi restava che comprenderne le implicazioni.
376
+ 11. La cosa migliore, dopo l'avere buone idee, è riconoscere quelle che arrivano dagli utenti. Qualche
377
+ volta sono le migliori.
378
+ Fatto interessante, è facile scoprire che se sei completamente onesto e autocritico su quanto è dovuto
379
+ agli altri, il mondo intero ti tratterà come se ogni bit di quell'invenzione fosse opera tua, mentre impari a
380
+ considerare con sempre maggior modestia il tuo genio innato. Abbiamo visto come tutto ciò abbia
381
+ funzionato a meraviglia con Linus!
382
+ (Quando ho presentato questo scritto alla conferenza su Perl dell'Agosto 1997, in prima fila c'era Larry
383
+ Wall. Non appena sono arrivato al punto di cui sopra, ha intonato in stile revival-religioso, “Diglielo,
384
+ diglielo, fratello!” Tutti i presenti si son messi a ridere, perché sapevano come ciò avesse funzionato bene
385
+ anche per l'inventore di Perl.)
386
+ Dopo aver lavorato sul progetto nello stesso spirito per alcune settimane, mi son visto arrivare lodi simili
387
+ non soltanto dagli iscritti alla lista ma anche da altre persone che venivano a sapere della cosa. Ho
388
+ conservato qualche email; forse me le andrò a rileggere nel caso iniziassi a chiedermi se la mia vita
389
+ abbia mai avuto un qualche valore :-).
390
+ Ma ci sono altre due lezioni da trarre, più fondamentali e non politiche, buone per ogni tipo di design.
391
+ 12. Spesso le soluzioni più interessanti e innovative arrivano dal fatto di esserti reso conto come la tua
392
+ concezione del problema fosse errata.
393
+ Avevo cercato di risolvere il problema sbagliato continuando a lavorare su popclient in quanto
394
+ combinazione MTA/MDA con tutte le possibili modalità di consegna della posta. Il design di fetchmail
395
+ aveva bisogno di essere reimpostato dall'inizio come un puro MTA, a parte il normale percorso della
396
+ posta relativo a SMTP.
397
+ Quando sbatti la testa contro il muro nel lavoro di programmazione – quando cioè non riesci più a
398
+ pensare alla prossima “patch” – spesso è ora di chiedersi non se hai la risposta giusta, ma se ti stai
399
+ ponendo la giusta domanda. Forse bisogna inquadrare nuovamente il problema.
400
+ Be', mi toccò inquadrare meglio il problema. Chiaramente la cosa giusta da fare era (1) posizionare il
401
+ supporto per il “SMTP forwarding” nel driver generico, (2) farla diventare la funzione default, (3)
402
+ sbarazzarsi di tutte le altre modalità di consegna della posta, specialmente le opzioni “deliver-to-file” e
403
+ “deliver-to-standard-output”.
404
+ Per qualche tempo ho esitato a compiere il passo (3), temendo di avvilire quanti usavano da molto tempo
405
+ popclient proprio per i diversi meccanismi di consegna. In teoria, avrebbero potuto immediatamente
406
+ passare ai file “.forward” oppure agli equivalenti “non-sendmail” per ottenere il medesimo effetto. In
407
+ pratica, però, tale transizione sarebbe risultata impraticabile.
408
+ Quando mi decisi comunque a farlo, ne risultarono enormi benefici. Le parti più confuse del codice del
409
+ driver scomparvero. La configurazione divenne radicalmente più semplice – niente più girovagare nel
410
+ sistema MDA e nella mailbox, niente più preoccupazioni per vedere se il sistema operativo supportasse o
411
+ meno il blocco dei file.
412
+ Venne anche eliminata l'unica possibilità di perdere dei messaggi. Se, specificando la consegna in un
413
+ file, il disco è pieno, la posta va perduta. Impossibile che ciò accada con il “SMTP forwarding” perché
414
+ l'altro SMTP in ascolto non accetterà l'OK a meno che il messaggio non possa essere correttamente
415
+ consegnato o almeno filtrato per il prelievo successivo.
416
+ Inoltre, le prestazioni complessive risultarono migliorate (anche se così non sembra quando lo si fa girare
417
+ una sola volta). Altro beneficio non insignificante del cambiamento fu che la chiamata manuale risultò
418
+ assai più semplificata.
419
+ In seguito fui costretto a reintrodurre la funzione di consegna tramite un MDA locale specificato
420
+ dall'utente, per consentire la gestione di strane situazioni relative allo SLIP dinamico. Ma riuscii a farlo in
421
+ maniera più semplice.
422
+ Morale? Non esitare a buttar via opzioni inanellate una sull'altra quando puoi rimpiazzarle senza perdere
423
+ in efficienza. Diceva Antoine de Saint-Exupéry (aviatore e designer di aerei, quando non scriveva libri per
424
+ bambini):
425
+ 13. “La perfezione (nel design) si ottiene non quando non c'è nient'altro da aggiungere, bensì quando
426
+ non c'è più niente da togliere.”
427
+ Quando il codice diventa migliore e più semplice, allora vuol dire che va bene. E nel processo, il design
428
+ di fetchmail acquistò una sua propria identità, diversa dal popclient originario.
429
+ Era giunta l'ora di cambiar nome. Il nuovo design assomigliava più a sendmail di quanto lo fosse il
430
+ vecchio popclient; entrambi sono MTA, ma mentre sendmail spinge e poi consegna, il nuovo popclient
431
+ tira e poi consegna. Così, a due mesi dai blocchi di partenza, decisi di dargli il nuovo nome, fetchmail.
432
+ 7. Fetchmail diventa adulto
433
+ Eccomi qui con un design ben fatto e innovativo, un codice che ero certo funzionasse bene perchè lo
434
+ usavo ogni giorno, e una spumeggiante lista di beta tester. Gradualmente mi resi conto che non ero più
435
+ indaffarato con uno stupido programmino personale che forse avrebbe potuto interessare pochi altri.
436
+ Stavo lavorando su un programma di cui ogni hacker dotato di mailbox Unix e connessione SLIP/PPP
437
+ non avrebbe potuto fare a meno.
438
+ Grazie all'opzione di “SMTP forwarding”, s
439
+ uperava sicuramente i programmi rivali fino a diventare
440
+ potenzialmente una “categoria killer”, uno di quei programmi classici che occupano la propria nicchia in
441
+ maniera perfetta, facendo scartare e quasi dimenticare ogni possibile alternativa.
442
+ Credo che simili risultati siano impossibili da perseguire o da pianificare. Devi esser trascinato dentro la
443
+ storia da idee così potenti che, col senno di poi, quei risultati appaiono del tutto inevitabili, naturali,
444
+ perfino prestabiliti. L'unico modo per provarci è farsi venire un sacco di idee, oppure avere la capacità di
445
+ portare le idee degli altri al di là del punto in cui essi stessi credevano potessero arrivare.
446
+ Andrew Tanenbaum ebbe l'idea originale di realizzare un linguaggio di base Unix per il 386, da usare
447
+ come strumento didattico. Linus Torvalds ha spinto il concetto del Minix ben oltre quanto lo stesso
448
+ Andrew ritenesse possibile – ed è diventato qualcosa di meraviglioso. Allo stesso modo (pur se su scala
449
+ minore) io ho preso alcune idee da Carl Harris e Harry Hochheiser, e le ho spinte oltre. Nessuno di noi è
450
+ stato “originale” nel senso romantico in cui si immagina un genio. Ma a ben vedere la maggior parte della
451
+ scienza, dell'ingegneria e dello sviluppo del software non viene realizzata da alcun genio originale, il
452
+ contrario della mitologia dell'hacker.
453
+ I risultati ottenuti erano piuttosto notevoli – meglio, esattamente quel tipo di successo che ogni hacker
454
+ sogna! E ciò significa che avrei potuto mirare anche a standard più elevati. Per rendere fetchmail così
455
+ ben fatto come lo vedevo ora, avrei dovuto scrivere non soltanto per le mie necessità ma anche per
456
+ includere il supporto di opzioni necessarie ad altri e tuttavia fuori dalla mia orbita. E fare ciò mantenendo
457
+ al contempo semplice e robusto il programma.
458
+ La prima funzione di gran lunga più importante che scrissi dopo essermi reso conto di ciò, fu il supporto
459
+ multiutente – la possibilità di prelevare la posta da più mailbox in cui erano stati accumulati tutti i
460
+ messaggi per un gruppo di utenti, e quindi smistare ogni singolo messaggio ai rispettivi destinatari.
461
+ Decisi di aggiungere il supporto multiutente in parte perché alcuni lo richiedevano, ma soprattutto perché
462
+ pensavo avrebbe buttato via ogni bug dal codice per un solo utente, costringendomi a fare attenzione
463
+ alla gestione dei vari indirizzi. E così fu. Mi ci volle parecchio tempo per sistemare tutto nella RFC 822,
464
+ non perché sia difficile mettere a posto ogni singola parte, ma perché coinvolgeva una montagna di
465
+ dettagli interdipendenti e instabili.
466
+ In ogni caso, anche la funzione per gli indirizzi multiutenti si rivelò un'ottima decisione. Ecco come me ne
467
+ sono accorto:
468
+ 14. Ogni strumento dovrebbe rivelarsi utile nella maniera che ci si attende, ma uno strumento davvero
469
+ ben fatto si presta ad utilizzi che non ci si aspetterebbe mai.
470
+ L'uso inatteso della funzione multiutenti è per una mailing list quando questa viene mantenuta sul lato
471
+ client della connessione SLIP/PPP, attivando l'espansione dell'alias. Ne consegue che chi fa girare un
472
+ PC tramite un account con un provider Internet è in grado di gestire una mailing list senza dover
473
+ accedere continuamente ai file alias del provider.
474
+ Altra importante modifica richiesta dai beta tester fu il supporto per operazioni MIME in 8-bit. Qualcosa
475
+ piuttosto semplice a farsi, poiché avevo fatto bene attenzione a mantenere il codice pulito per inserire l'8-
476
+ bit. Non perché avessi anticipato tale richiesta, quanto piuttosto per rispettare un'altra regola:
477
+ 15. Quando si scrive del software per qualunque tipo di gateway, ci si assicuri di disturbare il meno
478
+ possibile il flusso dei dati – e *mai* buttar via alcun dato a meno che il destinatario non ti ci costringa!
479
+ Se non avessi rispettato questa regola, il supporto per MIME in 8-bit sarebbe risultato difficile e
480
+ problematico. Così invece tutto quel che dovetti fare fu leggere la RFC 1652 e aggiungere poche stringhe
481
+ per far generare l'header.
482
+ Alcuni utenti europei mi hanno costretto a inserire un'opzione per limitare il numero dei messaggi
483
+ prelevati a ogni sessione (in modo da controllare i costi di collegamento, per via delle care tariffe imposte
484
+ dalle aziende telefoniche nazionali). Ho resistito per parecchio tempo, e ancor'oggi non ne sono
485
+ pienamente soddisfatto. Ma se scrivi programmi per tutto il mondo, devi dare ascolto ai tuoi clienti – e ciò
486
+ rimane valido anche se non ti ricompensano in denaro.
487
+ 8. Qualche altra lezione da Fetchmail
488
+ Prima di tornare alle questioni generali sul “software-engineering”, è il caso di considerare qualche altro
489
+ insegnamento specifico a seguito di quest'esperienza con fetchmail.
490
+ La sintassi del file rc include una serie di parole-chiave facoltative completamente ignorate
491
+ dall'analizzatore. La sintassi in “quasi-inglese” che si ottiene è notevolmente più leggibile delle semplici
492
+ coppie nome/valore che si rimangono dopo aver eliminato le prime.
493
+ Tutto ebbe inizio come un esperimento a notte fonda dopo essermi accorto di quante fossero le
494
+ dichiarazioni del file rc che cominciavano ad assomigliare a un minilinguaggio imperativo. (Per lo stesso
495
+ motivo ho modificato in “poll” la parola-chiave “server” del popclient originale).
496
+ Mi venne da pensare che sarebbe stato più facile usare qualcosa di simile all'inglese comune piuttosto
497
+ che quel minilinguaggio imperativo. Ora, pur essendo il sottoscritto un convinto fautore della scuola di
498
+ design del tipo “trasformalo in linguaggio”, come esemplificato da Emacs, dall'HTML e da molti motori di
499
+ database, generalmente non mi annovero tra i fan delle sintassi in “quasi-inglese”.
500
+ Tradizionalmente i programmatori hanno sempre avuto la tendenza a favorire sintassi molto precise e
501
+ compatte, del tutto prive di ridondanza. Si tratta di un'eredità culturale del tempo in cui le risorse
502
+ informatiche erano costose, così gli analizzatori dovevano risultare semplici ed economici al massimo
503
+ grado. Allora l'inglese, con quel 50% di ridondanza, sembrava un modello poco appropriato.
504
+ Non è questa la ragione per cui generalmente io evito le sintassi in quasi-inglese; l'ho citata qui soltanto
505
+ per demolirla. Con l'attuale economicità dei cicli e delle strutture, la pulizia non dovrebbe essere un
506
+ obiettivo in sé. Al giorno d'oggi è più importante che un linguaggio sia conveniente per gli esseri umani
507
+ anziché economico per il computer.
508
+ Esistono comunque buoni motivi per procedere con cautela. Uno è rappresentato dai costi della
509
+ complessità dell'analizzatore – non è il caso di aumentare tale complessità fino a raggiungere il punto in
510
+ cui produrrà bug significativi e confusione nell'utente. Un'altra ragione è che cercare di rendere un
511
+ linguaggio in quasi-inglese spesso richiede un tale aggiustamento linguistico che le somiglianze
512
+ superficiali con il linguaggio naturale generino confusione tanto quanto l'eventuale sintassi tradizionale.
513
+ (Come si può notare con evidenza nei linguaggi di interrogazione dei database di “quarta generazione” e
514
+ commerciali).
515
+ La sintassi di controllo di fetchmail riesce a evitare questi problemi perché il dominio riservato al
516
+ linguaggio è estremamente limitato. Non si avvicina neppure lontanamente a un linguaggio di tipo
517
+ generale; le cose che dice non sono affatto complicate, lasciando quindi poco spazio a potenziali
518
+ confusioni, quando ci si sposta mentalmente tra un ristretto ambito d'inglese e il linguaggio di controllo
519
+ vero e proprio. Credo qui si tratti di una lezione di più ampia portata:
520
+ 16. Quando il linguaggio usato non è affatto vicino alla completezza di Turing, un po' di zucchero
521
+ sintattico può esserti d'aiuto.
522
+ Un'altra lezione riguarda la sicurezza “al buio”. Alcuni utenti di fetchmail mi avevano chiesto di modificare
523
+ il software in modo che potesse conservare le password crittografate nel file rc, evitando così il rischio
524
+ che qualche ficcanaso potesse scoprirle casualmente.
525
+ Non l'ho fatto perché in realtà ciò non aggiunge alcuna protezione. Chiunque sia stato autorizzato a
526
+ leggere il file rc, sarebbe comunque in grado di far girare fetchmail – e se è la password che cerca,
527
+ saprebbe come decodificarla tirandola fuori dallo stesso codice di fetchmail.
528
+ Qualsiasi possibile codifica della password operata da .fetchmailrc, non avrebbe fatto altro che fornire un
529
+ falso
530
+ senso
531
+ di
532
+ sicurezza
533
+ a
534
+ quelli
535
+ che
536
+ non
537
+ vogliono
538
+ spremersi
539
+ le
540
+ meningi.
541
+ La regola generale è:
542
+ 17. Un sistema di sicurezza è sicuro soltanto finché è segreto. Meglio diffidare degli pseudo-segreti.
543
+ 9. Le pre-condizioni necessarie per lo stile bazaar
544
+ I primi lettori e revisori di questo scritto hanno r
545
+ ipetutamente sollevato domande sulle pre-condizioni
546
+ necessarie per il successo dello sviluppo in stile bazaar, comprendendo con ciò sia le qualifiche del
547
+ leader del progetto sia lo stato del codice al momento della diffusione pubblica e della nascita della
548
+ possibile comunità di co-sviluppatori.
549
+ È alquanto evidente come lo stile bazaar non consenta la scrittura del codice partendo da zero. Si
550
+ possono fare test, trovare i bug, migliorare il tutto, ma sarebbe molto difficile dar vita dall'inizio a un
551
+ progetto in modalità bazaar. Linus non lo ha fatto. Neppure io. La nascente comunità di sviluppatori deve
552
+ avere qualcosa da far girare e con cui giocare.
553
+ Quando s'inizia a costruire la comunità, bisogna essere in grado di presentare una promessa plausibile.
554
+ Non è detto che il programma debba funzionare particolarmente bene. Può anche essere crudo, pieno di
555
+ bug, incompleto, scarsamente documentato. Non deve però mancare di convincere i potenziali co-
556
+ sviluppatori che possa evolversi in qualcosa di veramente ben fatto nel prossimo futuro.
557
+ Quando Linux e fetchmail vennero diffusi pubblicamente, erano dotati di un design di base forte e
558
+ attraente. Molte persone ritengono che il modello bazaar da me presentato riveli correttamente questa
559
+ fase critica, per poi da qui saltare alla conclusione che sia indispensabile un elevato livello di intuizione e
560
+ bravura da parte di chi guida il progetto.
561
+ Ma Linus prese il suo design da Unix. All'inizio ho fatto lo stesso con il popclient originario (anche se poi
562
+ risultò molto diverso, assai più di quanto è accaduto con Linux, fatte le debite proporzioni). È dunque
563
+ vero che il leader/coordinatore di un progetto in stile bazaar debba possedere un eccezionale talento nel
564
+ design? Oppure può cavarsela facendo leva sui talenti altrui?
565
+ Non credo sia essenziale che il coordinatore possa produrre design eccezionali, ma è assolutamente
566
+ centrale che sia capace di riconoscere le buone idee progettuali degli altri.
567
+ Ciò appare evidente da entrambi i progetti di Linux e fetchmail. Pur non essendo un designer
568
+ particolarmente originale (come discusso in precedenza), Linus ha dimostrato un ottima intuizione nel
569
+ saper riconoscere il buon design per poi integrarlo nel kernel di Linux. Ed ho già descritto come l'idea più
570
+ potente di fetchmail (SMTP forwarding) mi sia arrivata da qualcun altro.
571
+ I primi lettori di questo testo mi hanno fatto i complimenti mettendo a fuoco la mia propensione a
572
+ sottovalutare l'originalità del design nei progetti in stile bazaar perchè ne possiedo a volontà io stesso, e
573
+ quindi la dò per scontata. In effetti, c'è qualcosa di vero in quest'affermazione; il design (in alternativa al
574
+ codice o al debugging) è la mia capacità migliore.
575
+ Ma il problema con il fatto di essere bravi e originali nel design del software è che tende a divenire
576
+ un'abitudine – prendi a fare cose carine e complicate quando invece dovresti tenerle semplici e robuste.
577
+ Proprio per questa ragione mi sono crollati addosso vari progetti, ma con fetchmail sono stato attento a
578
+ non farlo.
579
+ Credo insomma che il progetto di fetchmail abbia avuto successo in parte perché ho limitato la mia
580
+ tendenza a esser bravo; ciò va (almeno) contro l'essenzialità dell'originalità del design per il successo dei
581
+ progetti a bazaar. Consideriamo Linux. Supponiamo che Linus Torvalds avesse cercato di tirar fuori le
582
+ innovazioni fondamentali dal design del sistema operativo nel corso dello sviluppo; quali probabilità
583
+ esistono che il kernel risultante fosse ugualmente stabile ed efficace come quello che abbiamo ora?
584
+ È chiaro che occorrano capacità di un certo livello per il design e il codice, ma personalmente mi aspetto,
585
+ da quasi tutte le persone che pensano seriamente di lanciare un progetto bazaar, un livello superiore. Il
586
+ mercato interno della reputazione della comunità open source esercita una sottile pressione sulle
587
+ persone in modo che non si lancino dei progetti se non si è abbastanza competenti per seguirli. Finora
588
+ quest'approccio ha funzionato piuttosto bene.
589
+ Esiste un altro tipo di capacità normalmente non associata allo sviluppo del software che ritengo
590
+ importante al pari della bravura nel design per i progetti bazaar – anzi, forse ancora più importante. Il
591
+ coordinatore o leader deve essere in grado di comunicare efficacemente con gli altri.
592
+ D'altronde è ovvio che per metter su una comunità di sviluppatori occorra attirare gente, coinvolgerli in
593
+ quel che stai facendo, tenerli contenti per il lavoro che fanno. Lo sfrigolìo tecnico aiuta molto in questo
594
+ senso, ma è ben lungi dall'esser tutto. È anche importante il tipo di personalità che proietti.
595
+ Non è certo una coincidenza che Linus sia un tipo simpatico, capace di piacere alla gente e di farsi
596
+ aiutare. Da parte mia, io sono un estroverso energetico cui piace lavorare tra la folla, oltre ad avere
597
+ qualcosa dei modi e dell'istinto del comico. Per far funzionare il modello a bazaar, aiuta parecchio essere
598
+ in grado di esercitare almeno un po' di fascino sulla gente.
599
+ 10. Il contesto sociale del software open source
600
+ È proprio vero: le migliori operazioni di hacking nascono come soluzioni personali ai problemi quotidiani
601
+ dell'autore, e si diffondono perchè si scopre che tali problemi sono comuni a molte altre persone. Questo
602
+ ci riporta indietro alla questione della regola numero uno, riformulata forse in maniera più consona:
603
+ 18. Per risolvere un problema interessante, comincia a trovare un problema che risvegli il tuo interesse.
604
+ Così è successo con Carl Harris e l'iniziale popclient, lo stesso con me e fetchmail. Ma ciò era chiaro da
605
+ molto tempo. Il punto interessante che richiede attenzione, sulla base dell'evolversi di Linux e di
606
+ fetchmail, è il palcoscenico successivo – l'evoluzione del software in presenza di una vasta e attiva
607
+ comunità di utenti e co-sviluppatori.
608
+ In “The Mythical Man-Month”, Fred Brooks osserva come il tempo del programmatore non sia calcolabile;
609
+ aggiungendo altri sviluppatori ad un progetto in ritardo, lo si fa tardare ancora di più. Secondo lui, i costi
610
+ della complessità e delle comunicazioni di un progetto crescono esponenzialmente con il numero degli
611
+ sviluppatori coinvolti, mentre il lavoro cresce soltanto in senso lineare. Quest'affermazione è nota come
612
+ la “Legge di Brooks”, ed è considerata una verità pressoché universale. Ma se la Legge di Brooks fosse
613
+ stata l'unica verità, Linux non sarebbe mai esistito.
614
+ Il classico di Gerald Weinberg “The Psychology Of Computer Programming” spiega in che modo, a
615
+ posteriori, sia possibile individuare una vitale correzione alla tesi di Brooks. Parlando di “programmazione
616
+ senza ego”, Weinberg fa notare come laddove gli sviluppatori non si dimostrano territoriali rispetto al
617
+ proprio codice, incoraggiando altre persone a cercare bug e offrire miglioramenti, questi ultimi prendono
618
+ corpo molto più in fretta che altrove.
619
+ Forse le scelte terminologiche operate da Weinberg hanno impedito alla sua analisi di ottenere il
620
+ riconoscimento che merita – viene da ridere al solo pensiero di riuscire a descrivere un hacker “senza
621
+ ego”. Ma ritengo la sua posizione stringente più che mai.
622
+ La storia di Unix avrebbe dovuto prepararci per quel che stiamo imparando da Linux (e per quello che io
623
+ stesso ho verificato sperimentalmente su scala ridotta, copiando deliberatamente i metodi di Linus).
624
+ Ovvero, pur rimandando la scrittura del codice un'attività prettamente solitaria, la questione davvero
625
+ importante rimane la capacità di sfruttare l'attenzione e la potenza dell'intera comunità. Lo sviluppatore
626
+ che impiega soltanto il proprio cervello su un progetto chiuso risulterà sempre dietro allo sviluppatore che
627
+ sa come creare un contesto aperto, evolutivo dove sono centinaia le persone che si occupano dei
628
+ miglioramenti e del debugging.
629
+ Ma una serie di elementi hanno impedito al mondo tradizionale Unix di applicare tale approccio. Tra
630
+ questi, gli impedimenti legali connessi alle varie licenze, ai segreti e agli interessi commerciali. Altro
631
+ impedimento (in retrospettiva), il fatto che allora Internet non fosse ancora abbastanza sviluppata.
632
+ Prima dell'attuale Internet super-diffusa, esistevano poche comunità geograficamente compatte in cui
633
+ veniva incoraggiata la cultura della programmazione “senza ego” di Weinberg, dove uno sviluppatore
634
+ poteva facilmente attirare molti altri co-sviluppatori in gamba. Il Bell Lab, il MIT, UC Berkeley – queste le
635
+ dimore dell'innovazione che rimangono leggendarie e potenti ancor'oggi.
636
+ Linux è stato il primo progetto a proporre lo sforzo cosciente e coronato da successo verso l'utilizzo del
637
+ mondo intero come fucina di talenti. Non ritengo una combinazione il fatto che la gestazione di Linux sia
638
+ coincisa con la nascita del World Wide Web, e che Linux si sia lasciato alle spalle l'infanzia negli stessi
639
+ anni 1993-1994 che hanno visto il decollo dei provider locali e l'esplosione dell'interesse di massa per
640
+ Internet. Linus è stata la prima persona ad aver imparato come giocare secondo le nuove regole rese
641
+ possibili dalla diffusione di Internet.
642
+ Se è vero che tale diffusione si è rivelata necessaria per l'evoluzione del modello Linux, non credo però
643
+ possa ritenersi da sola una condizione sufficiente. Altro fattore vitale è stata l'implementazione di un certo
644
+ stile di leadership e di un insieme di usanze cooperative che hanno consentito agli sviluppatori di
645
+ coinvolgere altri co-sviluppatori e ottenere il massimo possibile dal medium stesso.
646
+ Ma cosa s'intende esattamente con un certo stile di leadership e quali sarebbero queste usanze
647
+ cooperative? Intanto, non ci si basa su relazioni di potere – e anche se tali dovessero essere, una
648
+ leadership fondata sulla costrizione non produrrebbe i risultati che abbiamo visto. Weinberg cita al
649
+ riguardo l'autobiografia dell'anarchico russo del XIX secolo Pyotr Alexeyvich Kropotkin, “Memorie di un
650
+ rivoluzionario”:
651
+ “Essendo cresciuto in una famiglia che aveva dei servitori, sono entrato nella vita attiva, al pari di tutti i
652
+ giovani della mia epoca, con un notevole carico di confidenza nella necessità di comandare, impartire
653
+ ordini, rimproverare, punire. Ma quando, ancora giovane, dovetti gestire degli affari seri e avere a che
654
+ fare con uomini [liberi], quando ogni errore avrebbe portato da solo a pesanti conseguenze, iniziai ad
655
+ apprezzare la differenza tra l'agire basato sul principio del comando e della disciplina e l'agire basato sul
656
+ principio della comprensione condivisa. Il primo funziona mirabilmente in una parata militare, ma non ha
657
+ valore alcuno allorché si tratta della vita reale, dove ogni obiettivo può essere raggiunto soltanto tramite i
658
+ duri sforzi di molte volontà convergenti.”
659
+ È precisamente i “duri sforzi di molte volontà convergenti” sono quel che un progetto come Linux richiede
660
+ – e il “principio del comando” è veramente impossibile da praticare tra i volontari di quel paradiso
661
+ anarchico chiamato Internet. Per operare e competere con efficacia, ogni hacker che voglia guidare
662
+ progetti collettivi deve imparare come creare e dare energia a reali comunità d'interesse secondo le
663
+ modalità vagamente suggerite dal “principio della comprensione” citato da Kropotkin. Deve imparare ad
664
+ usare la Legge di Linus.
665
+ Più sopra mi sono riferito all'effetto Delfi come possibile spiegazione della Legge di Linus. Ma si
666
+ potrebbero anche fare analogie forse più calzanti con i sistemi d'adattamento delle scienze biologiche ed
667
+ economiche. Sotto molti aspetti il mondo Linux si comporta come un “free market” oppure come un
668
+ sistema ecologico, una serie di agenti indipendenti che cercando di massimizzare quell'utilitarismo che
669
+ nel processo va producendo un ordine spontaneo e in grado di auto-correggersi, più elaborato ed
670
+ efficiente di quanto avrebbe potuto raggiungere qualsiasi pianificazione centralizzata. È dunque questo il
671
+ luogo dove cercare il “principio della comprensione”.
672
+ La “funzione utilitaristica” che gli hacker di Linux vanno massimizzando non è economica in senso
673
+ classico, quanto piuttosto espressione dell'intangibile, egoistica reputazione e soddisfazione che si
674
+ guadagna tra gli altri hackers. (La loro motivazione potrebbe essere definita “altruista”, ma ciò
675
+ significherebbe ignorare il fatto che a ben vedere l'altruismo stesso altro non è che una forma di
676
+ soddisfazione egoistica). In realtà le culture del lavoro volontario che funzionano in tal modo non sono
677
+ così rare; un'altra cui ho preso parte a lungo è quella dei fan della fantascienza, che al contrario del giro
678
+ hacker riconosce esplicitamente come motore propulsore dietro tale attività volontaria proprio il
679
+ cosiddetto “egoboo” (l'esaltazione della reputazione individuale tra gli altri fan).
680
+ Linus, posizionandosi con successo come filtro di un progetto nel quale il lavoro è in gran parte svolto da
681
+ altri, e alimentando interesse nel progetto stesso finché non arriva ad auto-alimentarsi, ha dimostrato di
682
+ aver acutamente fatto proprio il “principio della comprensione condivisa” di Kropotkin. Questa visione
683
+ quasi-economica del mondo Linux ci consente di vedere come applicare tale comprensione.
684
+ È possibile ritenere il metodo di Linus c
685
+ ome un modo per creare un mercato efficiente all'interno
686
+ dell'“egoboo” – per collegare nel modo più sicuro possibile l'egoismo dei singoli hacker con quegli
687
+ obiettivi difficili che possono essere raggiunti soltanto grazie alla concreta cooperazione collettiva. Con il
688
+ progetto fetchmail ho dimostrato (pur se su scala più ridotta) che è possibile duplicarne il metodo
689
+ ottenendo buoni risultati. Forse l'ho perfino messo in atto un po' più coscientemente e sistematicamente
690
+ di quanto non abbia fatto Linus.
691
+ Molte persone (soprattutto quanti politicamente diffidano del “free market”) immaginavano che una
692
+ cultura di egoisti auto-referenziale si rivelasse frammentaria, territoriale, sprecona, segreta, ostile. Ma
693
+ tale aspettativa viene chiaramente confutata (per fornire un solo esempio) dalla notevole varietà, qualità
694
+ e profondità della documentazione relativa a Linux. Se è un dato di fatto che i programmatori odiano
695
+ lavorare sulla documentazione, com'è allora che gli hacker di Linux ne producono di così copiosa?
696
+ Evidentemente il “free market dell'egoboo” di Linux funziona meglio nella produzione di comportamenti
697
+ virtuosi, diretti verso gli altri, rispetto a quei negozi dei produttori di software commerciale che si
698
+ occupano della documentazione, avendo alle spalle massicci finanziamenti.
699
+ Sia il progetto di fetchmail che del kernel di Linux dimostrano come, dando la giusta ricompensa all'ego di
700
+ molti altri hacker, un bravo sviluppatore/coordinatore possa utilizzare Internet per catturare i vantaggi
701
+ dell'avere a disposizione molti co-sviluppatori senza che il progetto si frantumi in una confusione caotica.
702
+ Ecco quindi la mia controproposta alla Legge di Brooks:
703
+ 19: Stabilito che il coordinatore dello sviluppo abbia a disposizione un medium almeno altrettanto
704
+ affidabile di Internet, e che sappia come svolgere il ruolo di leader senza costrizione, molte teste
705
+ funzionano inevitabilmente meglio di una sola.
706
+ Penso che il futuro del software open source apparterrà sempre più alle persone che sanno come
707
+ giocare al gioco di Linus, persone che si lasceranno alle spalle la cattedrale per entrare nel bazaar. Ciò
708
+ non significa che non saranno più importanti le visioni e l'intelligenza individuali; credo piuttosto che la
709
+ punta avanzata del software open source apparterrà a quanti sapranno muovere da visioni e intelligenza
710
+ individuali per poi amplificarle tramite l'effettiva costruzione di comunità volontarie d'interesse.
711
+ E forse ciò vale non soltanto per il futuro del software open source. Nessuno sviluppatore in “closed-
712
+ source” potrà mai pareggiare la fucina di talenti che la comunità Linux è in grado di riunire per affrontare
713
+ un problema. Sono davvero in pochi a potersi permettere di assumere le oltre duecento persone che
714
+ hanno contribuito a fetchmail!
715
+ Forse alla fine la cultura dell'open source trionferà non perchè la cooperazione sia moralmente giusta o
716
+ perché il software “costretto” sia moralmente sbagliato (dando per scontato che si creda a quest'ultima
717
+ affermazione, cosa che né io né Linus facciamo), ma semplicemente perché il mondo “closed-source”
718
+ non è in grado di vincere la corsa agli armamenti dell'evoluzione contro quelle comunità open source
719
+ capaci di affrontare un problema con tempi e capacità superiori di diversi ordini di grandezza.
720
+ 11. Ringraziamenti
721
+ Questo scritto è stato migliorato grazie alle conversazioni avute con molte persone che hanno contribuito
722
+ a trovarne i bug. Ringrazio in modo particolare Jeff Dutky , che mi ha suggerito la formulazione “il
723
+ debugging è parallelizzabile” e che mi ha aiutato a svilupparne le analisi conseguenti. Grazie anche a
724
+ Nancy Lebovitz per avermi suggerito di emulare Weinberg citando Kropotkin. Critiche costruttive sono
725
+ venute anche da Joan Eslinger e Marty Franz della lista General Technics. Sono grato ai membri del
726
+ PLUG, Philadelphia Linux User's Group, per essersi prestati come primo test pubblico per la versione
727
+ iniziale di questo testo. Infine, i commenti iniziali di Linus Torvalds sono stati di grande aiuto e il suo
728
+ sostegno molto incoraggiante.
729
+ 12. Letture consigliate
730
+ Ho citato diversi passaggi dal classico di Frederick P. Brooks “The Mythical Man-Month” perché, in molti
731
+ sensi, le sue introspezioni meritano ulteriori riflessioni. Raccomando di cuore l'edizione pubblicata in
732
+ occasione del 25° Anniversario da Addison-Wesley (ISBN 0
733
+ -201-83595-9), che contiene anche il suo
734
+ saggio del 1986 “No Silver Bullet”.
735
+ Questa nuova edizione contiene un'importante retrospettiva dei 20 anni successivi in cui Brooks ammette
736
+ schiettamente come alcuni giudizi espressi nel testo originale non abbiano sostenuto la prova del tempo.
737
+ Ho letto la retrospettiva dopo aver sostanzialmente completato questo scritto, e sono rimasto sorpreso
738
+ nello scoprire che Brooks attribuisse pratiche da quasi-bazaar a Microsoft! (In realtà, però, si è poi visto
739
+ come tale attribuzione fosse erronea. Nel 1998 abbiamo appreso dagli Halloween Documents come la
740
+ comunità interna dei programmatori di Microsoft risulti pesantemente balcanizzata, senz'alcuna
741
+ possibilità per quel tipo di accesso generale ai sorgenti tipico dello stile bazaar).
742
+ “The Psychology Of Computer Programming” di Gerald M. Weinberg (New York, Van Nostrand Reinhold
743
+ 1971) presenta il concetto, malamente etichettato, di “programmazione senza ego.” Pur essendo l'autore
744
+ nient'affatto tra i primi a rendersi conto della futilità del “principio del comando”, probabilmente fu il primo
745
+ a riconoscere e sostenere tale punto in particolare connessione con lo sviluppo del software.
746
+ Richard P. Gabriel, occupandosi della cultura Unix dell'era pre-Linux, sosteneva con riluttanza la
747
+ superiorità di un modello quasi-bazaar nel suo saggio del 1989: “Lisp: Good News, Bad News, and How
748
+ To Win Big”. Anche se per molti versi un po' datato, il testo è ancora giustamente celebrato dai fan del
749
+ Lisp (incluso il sottoscritto). Qualcuno mi ha ricordato che la sezione intitolata “Worse Is Better” si
750
+ propone quasi come un'anticipazione di Linux. L'articolo è disponibile sul World Wide Web:
751
+ http://www.naggum.no/worse-is-better.html.
752
+ “Peopleware: Productive Projects and Teams” di De Marco e Lister (New York; Dorset House, 1987;
753
+ ISBN 0-932633-05-6) è una gemma sottovalutata che mi ha fatto piacere veder citata nella retrospettiva
754
+ di Fred Brooks. Anche se poco di quanto scrivono gli autori può applicarsi direttamente alle comunità
755
+ Linux o open source, le loro riflessioni sulle condizioni necessarie per un lavoro creativo sono acute e
756
+ valide per chiunque volesse provare ad applicare alcune delle virtù del modello bazaar in un contesto
757
+ commerciale.
758
+ Devo infine ammettere d'aver inizialmente intitolato questo scritto “La cattedrale e l'agorà”, essendo
759
+ quest'ultimo il termine greco per indicare un mercato all'aperto o un luogo d'incontro pubblico. Ciò per
760
+ l'influenza dei saggi embrionali di Mark Miller e Eric Drexler “Agoric systems” in cui venivano descritte le
761
+ proprietà emergenti dell'ecologia computazionale di tipo quasi-commerciale. Tali scritti mi hanno
762
+ preparato a riflettere con chiarezza sugli analoghi fenomeni nell'ambito della cultura open source quando
763
+ Linux mi ci ha fatto sbattere il muso cinque anni dopo. Questi scritti sono reperibili sul Web:
764
+ http://www.agorics.com/agorpapers.html.
765
+ 13. Epilogo: Netscape si unisce al bazaar!
766
+ È proprio strano rendersi conto di aiutare lo sviluppo della storia...
767
+ Il 22 gennaio 1998, circa sette mesi dopo la prima pubblicazione di questo scritto, Netscape
768
+ Communications, Inc. ha annunciato la diffusione pubblica dei codici sorgenti di Netscape
769
+ Communicator. Fino al momento dell'annuncio, non avevo alcuna idea che ciò sarebbe mai potuto
770
+ accadere.
771
+ Subito dopo l'annuncio, Eric Hahn, Executive Vice President e Chief Technology Officer di Netscape, mi
772
+ ha inviato questa breve email: “A nome di tutti noi di Netscape, voglio ringraziarti per averci aiutato
773
+ innanzitutto a compiere questo passo. Il tuo pensiero e i tuoi scritti sono stati di fondamentale ispirazione
774
+ per la nostra decisione.”
775
+ La settimana successiva (4 Febbraio 1998), sono arrivato in aereo nella Silicon Valley su invito di
776
+ Netscape per partecipare a una giornata di incontri sulle strategie future con alcuni dei loro dirigenti
777
+ esecutivi e il personale tecnico. Abbiamo progettato insieme la strategia e la licenza per la release del
778
+ codice di Netscape, oltre ad aver buttato giù ulteriori piani che speriamo alla fine possano avere un
779
+ impatto positivo e profondo sulla comunità open source. Al momento in cui scrivo, è troppo presto per
780
+ entrare nello specifico; ma entro qualche settimana dovrebbero essere noti maggiori dettagli.
781
+ Netscape sta per fornirci un test su larga scala e assai concreto del modello bazaar all'interno del mondo
782
+ commerciale. La cultura dell'open source si trova di fronte a un pericolo; se l'operazione di Netscape non
783
+ dovesse funzionare, il concetto stesso di open source potrebbe risultarne così screditato che il mondo
784
+ commerciale non gli si avvicinerà per un'altra decade.
785
+ D'altra parte, però, si tratta di una spettacolare opportunità. L'iniziale reazione a tale mossa in quel di
786
+ Wall Street e altrove è stata cautamente positiva. Ci è stata data la possibilità di provare cosa sappiamo
787
+ fare. Se grazie a questa mossa Netscape saprà riguadagnare una sostanziale quota di mercato, ciò
788
+ potrebbe davvero innescare la rivoluzione attesa da lungo tempo nell'industria del software.
789
+ L'anno prossimo sarà un anno molto istruttivo e interessante.
790
+ 14. Cronologia delle versioni e delle modifiche
791
+ $Id: cathedral-bazaar.sgml,v 1.42 22/11/1998 04:01:20 esr Exp $
792
+ Presentazione della 1.16 al Linux Kongress, 21 Maggio 1997.
793
+ Bibliografia aggiunta il 7 Luglio 1997 nella 1.20.
794
+ Aggiunto l'aneddoto sulla Perl Conference il 18 Novembre 1997 nella 1.27.
795
+ Modificato “free software” in “open source” il 9 Febbraio 1998 nella 1.29.
796
+ Aggiunto “Epilogo: Netscape si unisce al bazaar!” il 10 Febbraio 1998 nella 1.31.
797
+ Eliminato il grafico di Paul Eggert sulla questione GPL-bazaar dopo vivaci discussioni con RMS il 28
798
+ Luglio 1998.
799
+ Aggiunta correzione su Brooks basata sugli Halloween Documents il 20 Novembre 1998 nella 1.40.
800
+ Altri livelli di revisione hanno incorporato minori aggiustamenti editoriali.
801
+
802
+ Traduzione italiana a cura di Bernardo Parrella berny@apogeonline.com, Giugno 1999
803
+ Per il testo originale inglese: http://www.tuxedo.org/~esr/writings/cathedral-bazaar/cathedral-bazaar.html
804
+
static/data/lettere_musulmane.txt ADDED
@@ -0,0 +1,1891 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ « SPIRITUALITÀ SPERIMENTALE »
2
+ Collana diretta da Gianpaolo Fiorentini
3
+ 15
4
+ © 1998: Promolibri Magnanelli, Torino
5
+ Stampa: M.S./ Litografia, Torino
6
+ I N D I C E
7
+ Introduzione
8
+ 9
9
+ Prima lettera
10
+ 13
11
+ Prima risposta
12
+ 19
13
+ Seconda lettera
14
+ 23
15
+ Seconda risposta
16
+ 27
17
+ Terza lettera
18
+ 31
19
+ Terza risposta
20
+ 35
21
+ Quarta lettera
22
+ 39
23
+ Quarta risposta
24
+ 42
25
+ Quinta lettera
26
+ 47
27
+ Quinta risposta
28
+ 50
29
+ Sesta lettera
30
+ 53
31
+ Sesta risposta
32
+ 56
33
+ Settima lettera
34
+ 61
35
+ Settima risposta
36
+ 64
37
+ Ottava lettera
38
+ 67
39
+ Ottava risposta
40
+ 69
41
+ Nona lettera
42
+ 15
43
+ Nona risposta
44
+ 78
45
+ Decima lettera
46
+ 81
47
+ Decima risposta
48
+ 84
49
+ Undicesima lettera
50
+ 87
51
+ Undicesima risposta
52
+ 91
53
+ Postfazione
54
+ 93
55
+ L'Alchimia è la sorella della Profezia
56
+ Ja'far al-Sadiq
57
+ Noi siamo i Sapienti che impartiscono l'insegnamento,
58
+ i nostri shi'iti sono i destinatari del nostro insegnamento.
59
+ Il resto, ahimè, è la schiuma trascinata dal torrente.
60
+ 'Ali ibn Abi Tàlib
61
+ Lieto
62
+ giacevo nel cuore della perla;
63
+ finché, sferzato dalle tempeste,
64
+ la vita mi agitò come un'onda.
65
+ Il segreto del mare
66
+ feci suonare con voce di tuono.
67
+ Come nuvola esausta sulla spiaggia
68
+ mi addormentai. Non mi svegliai più.
69
+ Rumi
70
+ INTRODUZIONE
71
+ Questa primavera, nella mia professione
72
+ di no-
73
+ taio, fui chiamato da un cliente per un problema
74
+ singolare. Era questi l'ultimo rappresentante
75
+ di
76
+ un'antica famiglia che possedeva ancora qualche ric-
77
+ chezza e i cui antenati avevano svolto un ruolo
78
+ importante nella storia locale. Mi chiedeva di rag-
79
+ giungerlo in una vecchia villa al di là delle colline
80
+ che fronteggiano la città, dove il fiume si arresta un
81
+ attimo a formare un piccolo lago per poi proseguire.
82
+ Vi viveva con una coppia di domestici lo zio,
83
+ uomo stravagante e solitario. Qualcuno lo ricordava
84
+ giovane buontempone che amava belle donne e bel
85
+ vivere, e vecchi amici descrivevano feste, balli e cene
86
+ allegre nella villa illuminata e rumorosa. Anni pri-
87
+ ma, si raccontava, tornato da un viaggio si era rin-
88
+ chiuso in casa, scoraggiando ogni contatto con rispo-
89
+ ste scontrose sinché nessuno lo aveva più cercato.
90
+ Dopo il mio arrivo ci sedemmo in un comodo
91
+ salottino e il mio cliente chiamò i domestici a riferi-
92
+ re quello che era avvenuto, mi parve però con una
93
+ curiosa reticenza, come per qualche fedeltà o timore.
94
+ Il racconto fu breve: all'inizio di aprile il padrone
95
+ li aveva quasi cacciati, costretti a forza a una vacan-
96
+ za di un mese con l'imposizione di non farsi vivi pri-
97
+ ma della scadenza, per nessun motivo. Al ritorno
98
+ avevano trovato villa vuota, proprietario scomparso,
99
+ una lettera per loro e una per il nipote, entrambe in
100
+ bella vista sul tavolo di cucina.
101
+ Il contenuto era semplice e conciso: confermava
102
+ una partenza definitiva, senza indicazioni, e dava
103
+ brevi istruzioni con delega al nipote per la gestione
104
+ del patrimonio. Era per quest'ultima parte, eviden-
105
+ temente, che era stata richiesta la mia presenza.
106
+ Esaminammo la villa. Nello studio un caminetto
107
+ colmo di cenere e frammenti di carta testimoniava che
108
+ si erano bruciati molti documenti. Di un grosso qua-
109
+ derno era rimasta parte della copertina mezza con-
110
+ sumata: era ancora possibile leggere «Diar.. d.. lab..».
111
+ Girando per casa in cerca di indizi
112
+ scendemmo
113
+ nel seminterrato. Qui, con mio grande stupore, sta-
114
+ va un vasto laboratorio ben attrezzato per esperi-
115
+ menti di chimica e metallurgia: forni, vecchi alam-
116
+ bicchi, pestelli e mortai di tutte le dimensioni, cro-
117
+ gioli usati in gran quantità. Nessun materiale. Sem-
118
+ brava ci si fosse dati gran pena per ripulire tutto.
119
+ Solo, in bella vista su un tavolo, uno splendido lin-
120
+ gottino giallo che un orefice confermò poi essere di
121
+ oro purissimo.
122
+ Una porta laterale conduceva in uno studio con
123
+ pareti ricolme di libri. Sulla scrivania, legate da un
124
+ nastro verde, delle lettere con un biglietto enigma-
125
+ tico che diceva: «Queste si possono
126
+ mostrare».
127
+ Concluse le incombenze
128
+ legali il giovane
129
+ volle
130
+ affidare a me le lettere perché le esaminassi e ne
131
+ decidessi la sorte. In effetti sapeva che amavo studi
132
+ esoterici, e pensava che ne potessi dare un giudizio.
133
+ Dopo una prima scorsa, fu evidente che non rap-
134
+ presentavano se non la minima parte di uno scam-
135
+ bio epistolare molto più ampio, certamente più det-
136
+ tagliato. Era stato cancellato con cura tutto ciò che
137
+ poteva indicare nome e luogo dell'interlocutore mi-
138
+ sterioso, con tutte le date.
139
+ Ero in buona amicizia con uno studioso di isla-
140
+ mismo, ne chiesi il parere. Riporto qui il commento
141
+ sintetico con cui le restituì:
142
+ Caro amico,
143
+ si tratta certamente di una documentazione notevole. Il
144
+ maestro dell'Islam è molto probabilmente un sufi di
145
+ scuola shi'ita. Lo dimostra certo linguaggio: per esem-
146
+ pio «situazione» e «stato» così come sono usati nella
147
+ sesta risposta corrispondono sicuramente a maqàm e a
148
+ hai, e sono termini tecnici della letteratura sufi. Mentre
149
+ l'accenno all'amicizia con Dio, la walàyat, è tipica del
150
+ pensiero shi'ita.
151
+ Le ritengo di grande interesse.
152
+ Perciò le ho tradotte, erano in inglese, cercando
153
+ di comprendere
154
+ il senso delle frasi talvolta molto
155
+ oscure, e lasciandole nello stesso ordine in cui sta-
156
+ vano, sino all'ultima brevissima comunicazione. Le
157
+ ho poi sottoposte a un editore, che ha accettato di
158
+ pubblicarle.
159
+ Così facendo spero di aver bene interpretato la
160
+ volontà di chi me le ha inconsapevolmente
161
+ affidate,
162
+ dovunque si trovi ora.
163
+ PRIMA LETTERA
164
+ Caro Maestro,
165
+ da voi il silenzio, e nel silenzio la pace. Qui tut-
166
+ to è rumore, e nel rumore la paura. Presso di voi
167
+ il frutto, qui nulla se non la vita elementare, con
168
+ tutte le sue fatiche.
169
+ Che vi posso dire di più. Volevate conoscere il
170
+ mio mondo e i miei problemi. Guardate un for-
171
+ micaio: l'attività è frenetica, furia cieca della natu-
172
+ ra che spinge a crescere, procreare, senza altro
173
+ scopo che esistere.
174
+ Ascoltate un alveare: operosità continua in un
175
+ ronzio ininterrotto, senza un attimo di quiete.
176
+ Mi dite che spesso siete nel deserto a meditare
177
+ e studiare: immaginate un mondo senza deserti,
178
+ dove la solitudine sia un dono impossibile, il silen-
179
+ zio un ricordo appannato e la vita un affannarsi
180
+ insensato, una corsa senza punto di arrivo, fatta a
181
+ spintoni e gomitate per conquistare un premio che
182
+ non esiste.
183
+ Mi chiedete cosa sto cercando: userò parole
184
+ non mie. Da poco è morto un Papa, e ne hanno
185
+ cjpi t
186
+ i
187
+ c
188
+ q
189
+ u
190
+ c
191
+ u
192
+ i
193
+ f
194
+ f
195
+ c
196
+ i
197
+ i
198
+ i
199
+ n
200
+ .
201
+ p
202
+ f
203
+ i
204
+ r
205
+ d
206
+ b
207
+ t
208
+ é b
209
+ K
210
+ u
211
+ i
212
+ v
213
+ r
214
+ m
215
+ r
216
+ a crac.
217
+ _
218
+ q
219
+ > j
220
+ q
221
+ u
222
+ j
223
+ n
224
+ o
225
+ n
226
+ c
227
+ flmmnispwbibm
228
+ b
229
+ j
230
+ n
231
+ u
232
+ f
233
+ c
234
+ e
235
+ n
236
+ »
237
+ . t
238
+ u
239
+ |j>ini0l(U9
240
+ Damasco, mitica città di studiosi e traduttori,
241
+ in un'incisione occidentale.
242
+ eletto un altro. Il nuovo è un uomo dolcissimo,
243
+ che non pare di questo mondo, dall'aria svagata
244
+ come si trovasse per caso su una sedia un po' osti-
245
+ le, un po' estranea. Pochi giorni fa diceva che se
246
+ anche siamo mescolati alla confusione e al rumo-
247
+ re, dobbiamo affermare: "Oltre un certo punto voi
248
+ non esistete per me, ed io mi ritiro in me, nel mio
249
+ giardino di quiete e di delizie, unito al mio Dio, in
250
+ pace". Ricordava un facchino che aveva visto dor-
251
+ mire tranquillo in una stazione, circondato dal
252
+ baccano di treni e uomini e bagagli. Questa, ha
253
+ detto, è la Grande Disciplina, da non confondere
254
+ con la Piccola Disciplina che consiste solo nel
255
+ seguire le regole esteriori cui tutti ci dobbiamo
256
+ adattare.
257
+ Vorrei conoscere questa Grande Disciplina.
258
+ Vorrei la pace di quel facchino, qualunque cosa
259
+ essa sia.
260
+ Così, caro Maestro, ho scoperto l'Alchimia, di
261
+ cui tanto vi ho parlato, il motivo per cui chiedo
262
+ aiuto e guida.
263
+ Mi chiedete come vi sono giunto. L'ho incon-
264
+ trata in un libro, come capita sempre, come è ine-
265
+ vitabile qui, in Occidente, dove i Templi non esi-
266
+ stono più, dove i Maestri stanno silenti e nascosti,
267
+ dove restano solo libri di pietra e carta per legge-
268
+ re di antiche sapienze.
269
+ L'ho letto, il libro di cui vi parlo, in un momen-
270
+ to di disperazione, di rifiuto totale per questo
271
+ mondo, per il suo rumore, per il suo nulla fatico-
272
+ sissimo, per la paura che lo avvolge come una cap-
273
+ pa di tempesta imminente. Mi sentivo come dice
274
+ un filosofo che voi non conoscete, che non appar-
275
+ tiene e non potrebbe appartenere al deserto. Mi
276
+ sentivo «come una puttana che vaga in una città
277
+ senza marciapiedi». A mezzo tra sofferenza e
278
+ oblio, drogato dallo stesso esistere di questo ru-
279
+ more senza fine.
280
+ Così è incominciata la mia ricerca. Per caso. Ho
281
+ letto un libro e mi sono innamorato del silenzio
282
+ che vi abitava. Ho avuto l'intuizione di un luogo di
283
+ pace, un ricordo, una nostalgia. Un richiamo al
284
+ deserto, al secco, non arido, deserto che non ho
285
+ mai conosciuto.
286
+ Ho letto, e non ho capito. Ho sentito qualcosa
287
+ che si agitava, l'embrione informe, minuscolo,
288
+ impreciso, di una nascita possibile. Il nucleo invi-
289
+ sibile di una parola silenziosa, splendente.
290
+ Non so dirvi di più. Mi pare di aver capito, que-
291
+ sto sì, che nella materia, proprio in quella fisicità
292
+ che sembra orrenda, spiacevole, ignobile, proprio
293
+ in quella stia in qualche modo la chiave per qual-
294
+ cosa che potrei chiamare il divino, se solo avessi
295
+ ancora una religione.
296
+ Anche di questa mi avete chiesto. Non saprei
297
+ cosa rispondervi. Noterò solo un segno. Un tem-
298
+ po i nostri sacerdoti officiavano guardando ad
299
+ Oriente, alla vita e al suo sorgere. Oggi guardano
300
+ ad Occidente, alla morte e al suo approssimarsi.
301
+ Prima volgevano le spalle all'uomo e guardavano
302
+ a Dio. Oggi volgono le spalle a Dio e guardano
303
+ l'uomo.
304
+ Mi sembra semplice simbolo di un mondo, non
305
+ morente, già morto. La convulsa attività che mani-
306
+ festa non proviene da eccesso di vita, ma da de-
307
+ composizione cadaverica, quando nella corruzione
308
+ corporea tutto si muove, vermicola, gonfia, erutta,
309
+ emana.
310
+ L'anima è persa, fuggita con la vita e il respiro.
311
+ Resta ancora un oscuro fervore psichico ad emet-
312
+ tere le fetide esalazioni che i demoni amano e da
313
+ cui sono abbondantemente nutriti.
314
+ Sembra un'opera alchemica in atto: corruptio
315
+ unius est generatio alterius, dicevano i vecchi mae-
316
+ stri. Dunque inutile piangere su ciò che è finito,
317
+ aspettiamo con curiosità e speranza quello che
318
+ verrà. In effetti la morte, qui lo abbiamo dimenti-
319
+ cato, è un momento ineluttabile di questa manife-
320
+ stazione, e non è detto sia sempre un male...
321
+ Proprio qui, comunque, devo incominciare la
322
+ mia ricerca, e proprio qui, in questo stato sepol-
323
+ crale, occorre una guida perché i primi passi
324
+ abbiano la corretta direzione. Qualche secolo fa
325
+ un alchimista ha scritto:
326
+ La nostra pratica in effetti è un cammino nelle sabbie,
327
+ dove ci si deve guidare con la stella del Nord, piuttosto
328
+ che con le orme che vi si vedono impresse. La confu-
329
+ sione delle tracce, che un numero quasi infinito di per-
330
+ sone vi ha lasciato, è così grande, e vi si trovano così
331
+ tanti sentieri diversi, che conducono quasi tutti in
332
+ orrendi deserti, che è quasi impossibile non deviare
333
+ dalla vera via, che solo i saggi favoriti dal Cielo hanno
334
+ saputo fortunatamente scoprire, e riconoscere.
335
+ Tra queste sabbie, in questi deserti disperati,
336
+ così diversi dai vostri, non cerco i misteri delle
337
+ operazioni, gli arcani segreti dell'Arte. Cerco l'in-
338
+ dicazione primordiale, la parola iniziale, la traccia
339
+ del primo passo.
340
+ Rispettosamente.
341
+ PRIMA RISPOSTA
342
+ Caro studioso,
343
+ Dio dice nel suo santo Qur'an:
344
+ Il tuo Signore trasse dai lombi dei figli di Adamo i loro
345
+ discendenti e li fece testimoniare verso se stessi. "Non
346
+ sono il vostro Signore?". "Sì, l'attestiamo", risposero.
347
+ Questo perché non possiate dire il giorno della Resur-
348
+ rezione: "Noi non ne sapevamo nulla". O perché non
349
+ diciate: "I nostri padri prima di noi hanno accolto falsi
350
+ dei. Noi siamo i loro discendenti. Ci vuoi dunque far
351
+ perire per le azioni di uomini vani?" (Sura VII, 171-
352
+ 172, Al A'ràj., il Purgatorio).
353
+ Dio si fa conoscere per mezzo della sua parola,
354
+ e ogni versetto è una manifestazione.
355
+ La parola ha il suo limite nella manifestazione,
356
+ e la manifestazione è la parola che sale sino al vol-
357
+ to di chi la pronuncia.
358
+ Dio ha posto la sua parola sui discendenti di
359
+ Adamo quando erano ancora atomi. Ha detto:
360
+ "Non sono il vostro Signore?" ed essi sentirono
361
+ chiaramente. Perciò anche gli atomi hanno fede e
362
+ pregano. I loro movimenti sono un prostrarsi in
363
+ atteggiamento di umiltà, ed essi lo fanno anche
364
+ quando non sono ancora corpi completi.
365
+ Questa è la fede innata, quella per cui gli atomi
366
+ si muovono intimamente.
367
+ Dopo di questo, quando si formano i corpi, non
368
+ esiste più sapienza ma esiste il potere. Allora la
369
+ parola e la visione sono velate al di là del mondo
370
+ della non visione, e i movimenti intimi degli atomi
371
+ si colmano di oscurità.
372
+ Il cammino mistico si muove in senso contrario
373
+ a questo. Chi è su questo cammino si purifica e
374
+ rasserena per mantenere in se stesso il mondo del
375
+ potere fuori dal mondo della sapienza, per scopri-
376
+ re la visione penetrante della sapienza e poter udi-
377
+ re: "Non sono io il vostro Signore?". Allora questa
378
+ parola si rivela e supera nella sua unicità le fasi di
379
+ oscurità con la luce della visione.
380
+ Io ho manifestato ogni cosa in modo che essa mi
381
+ veli e non guidi sino a me.
382
+ Unirsi a me è la cosa più elevata che io abbia
383
+ manifestato, ma l'unirsi a me è un velo.
384
+ Quando io appaio, tu non vedi nulla. La parola
385
+ in alto è un limite per ciò che sta in basso, ma non
386
+ c'è limite per ciò che sta in alto.
387
+ Io sono la causa dell'apparizione
388
+ di ciò che si
389
+ manifesta, e sono la causa per cui appare in ciò che
390
+ io voglio che appaia.
391
+ M
392
+ i r' rff i-mK<ÌKr.mistMiK?«»Vi .uöi
393
+ fp
394
+ tt6$tmtintl
395
+ fSnC-'iiiW.K-
396
+ (¿Htif^wifi WI»«M(K>Í«>Í6 »tnuCtVftjj
397
+ ilfit
398
+ 'f¿jín«£jtí-{ip<i(tt <tß ^iwSif
399
+ (DTUVikiit«/-
400
+ ^"v^c'S»»«? tlviinnìÀ qtui.
401
+ A
402
+ (Sunt
403
+ ^ÜWIKhiiSltmill
404
+ t-
405
+ p
406
+ C
407
+ i
408
+ ^ t i
409
+ Ht/(] 'ft (tfc
410
+ wmWiV ptiUiftt?1
411
+ f<r pnfbm www
412
+ j
413
+ » H
414
+ K
415
+ T
416
+ U
417
+ >
418
+ : f Sx* x'im/Dtíitinéín'á/^ii)
419
+ >
420
+ .
421
+ • i',s, 43 q
422
+ w
423
+ \
424
+ l
425
+ m f^.ti ßit««ir ntPotito{v^:/f.
426
+ I v
427
+ -
428
+ i
429
+ l «.Unfit nm ))Utr .{crsyityv*
430
+ qMítil- >
431
+
432
+ »
433
+ «
434
+ ttj)x;tm*/VI.iMifîi(>Mpit«
435
+ Ciò che è compiuto è compiuto, ciò che ho stabi-
436
+ lito è stabilito, ciò che è stabilito è compiuto in quel-
437
+ lo che tutto abbraccia.
438
+ Caro studioso, ascolta le lingue dei mondi nelle
439
+ manifestazioni spirituali. Essi dicono: "Dio! Dio!".
440
+ Ed egli dice: "Non li sente chi sta in loro, o chi cer-
441
+ ca in loro delle testimonianze".
442
+ Caro studioso, se tu aderirai a ciò che ti è stato
443
+ assegnato tra questi due mondi, allora sarai un
444
+ amico di Dio.
445
+ La pace sia con te.
446
+ SECONDA LETTERA
447
+ Caro Maestro,
448
+ credo che si diventi alchimisti come ci si in-
449
+ namora: misteriosamente e incomprensibilmente.
450
+ All'inizio, una predisposizione, un essere già inna-
451
+ morati senza oggetto d'amore, inconsapevolmente:
452
+ è un sentimento che si unisce a disperazione quie-
453
+ ta, non malvagia o triste, piuttosto melanconica.
454
+ Nasce dalla nostalgia di qualcosa di perso, di ab-
455
+ bandonato, di un posto che ci apparteneva, che
456
+ non sappiamo più trovare. Il sentimento di chi ha
457
+ perso la propria patria e non sa come raggiungerla.
458
+ Nel tempo mi sono chiesto se non sia questo il
459
+ fondamento dell'essere ebrei: la ricerca di una
460
+ Terra Promessa, che non si traduce mai in realtà,
461
+ che rende stranieri dovunque si sia. Nei secoli
462
+ qualcuno ha cercato di realizzare il sogno: credo
463
+ che non vi sia peggiore illusione di quella di voler
464
+ tradurre in pratica, di voler corporificare, un sim-
465
+ bolo che per sua natura non è di questo mondo.
466
+ Ogni alchimista è un ebreo della diaspora: que-
467
+ sto significa la frase, riportata da Zosimo, di Maria
468
+ Profetessa: "Stai lontano dall'Arte, tu che non sei
469
+ della nostra razza, perché tu non sei del sangue di
470
+ Abramo!"
471
+ Dobbiamo essere del sangue di Abramo, se vo-
472
+ gliamo perseguire questa via, se pensiamo di esser-
473
+ vi predestinati o chiamati. Perché di vocazione si
474
+ tratta, che deve nascere da una mancanza, nostal-
475
+ gia della patria smarrita.
476
+ La patria diventa facilmente donna. La nostal-
477
+ gia si traduce in amore.
478
+ Trovo questo richiamo all'amore in tutti i
479
+ Maestri dell'Arte, sin dal nome che danno a se
480
+ stessi e ai loro fratelli: Innamorati della
481
+ Dottrina.
482
+ La Dottrina, la Sapienza, la Sofia degli gnostici,
483
+ non qualcosa di intellettuale, razionale, nel senso
484
+ comune della parola. La Dottrina come vita e
485
+ gioia, felicità ritrovata, dolcezza e riposo, virtù e
486
+ potenza, patria e donna amata. La Dottrina come
487
+ bellezza inimmaginabile.
488
+ Tutti sono innamorati. Tutti i poeti iniziati lo
489
+ raccontano. Innamoramento che sorge in una sta-
490
+ gione singolare, in uno stesso mese, quello di No-
491
+ stra Signora, di Maria, Maia, la madre di Mercurio.
492
+ Non ci si innamora in un momento qualsiasi:
493
+ Ce fut au temps de mois de May
494
+ qu'on doibt foui'r dueil et esmay
495
+ qu'i'entray dedans un vergier
496
+ dont Zephirus fut iardinier.
497
+ E Dante, l'innamorato per eccellenza dell'Occi-
498
+ dente:
499
+ Avvenne una die che, sedendo io pensoso in alcuna
500
+ parte, ed io mi sentio cominciare un tremuoto nel cuo-
501
+ re, così come se io fosse stato presente a questa donna.
502
+ Allora dico che mi giunse una immaginazione di Amore
503
+ E poco dopo io vidi venire una gentile donna, la quale
504
+ era di famosa bieltade e [...] per la sua bieltade impo-
505
+ sto l'era nome Primavera; e così era chiamata.
506
+ In primavera, come dice
507
+ ...li Romans de la Rose
508
+ ou l'art d'Amors est toute enclose
509
+ che racconta:
510
+ En may estions, si songoie
511
+ ou temps amorous plain de joie...
512
+ Si vaneggia? Ricordo una fiaba, sempre la stes-
513
+ sa. Un cavaliere, l'eroe, deve affrontare un orren-
514
+ do drago. Lo uccide dopo infinite peripezie e peri-
515
+ coli. Una fanciulla bellissima e dolcissima è libera-
516
+ ta, diventa il suo premio onorevole e meritato.
517
+ Quella fanciulla, si narra, solo i veri Filosofi pos-
518
+ sono vedere e contemplare nuda in tutta la sua
519
+ splendida venustà, senza morire o essere inceneri-
520
+ ti dalla Belle Dame sans mercy. E ancora Dante a
521
+ dirlo concisamente:
522
+ e qual soffrisse di starla a vedere
523
+ diverria nobil cosa, o si morria.
524
+ Tutto questo suona un po' retorico e troppo
525
+ intelligente. Eppure dal Cantico dei Cantici ai ro-
526
+ manzi del Graal, dai miti greci a Goethe, dalle me-
527
+ lanconiche pagine del triste cavaliere della Mancia
528
+ ai momenti più ispirati di Melville, tutti cantano
529
+ questo amore, questa nostalgia, e tutti dicono che
530
+ soltanto chi giunge alla Terra Promessa sta in pace
531
+ ed è felice.
532
+ Io cerco l'oggetto del mio amore perché questa
533
+ passione, che ora è sofferenza, disperazione, logo-
534
+ rio della mente e dell'anima, si quieti.
535
+ Rispettosamente.
536
+ SECONDA RISPOSTA
537
+ Caro studioso,
538
+ l'amore di cui tu parli, è innanzitutto amore di
539
+ Dio, per Dio. La donna è la sua Sapienza e la
540
+ Maestà del suo Trono. Rivolgiti a lui e digli: "O
541
+ Signore, fa' che il mio amore per te sia più profon-
542
+ do del mio amore per me stesso, per il mio udito,
543
+ per la mia vista, per la mia gente, per i miei averi".
544
+ Il puro speciale amore di Dio è l'amore che ine-
545
+ bria lo spirito. E una scelta divina per colui che
546
+ adora, perché è un dono di Dio e non è amore di
547
+ un'entità. Questo amore viene con gli impulsi del-
548
+ la fede: è divino amore che ricambia la vicinanza.
549
+ L'adoratore si prostra sull'orlo dell'abito della
550
+ maestà divina, come in uno stato sublime, e que-
551
+ sto può avvenire soltanto per coloro il cui sé sale
552
+ nella luce dello spirito, perché la sua ebbrezza è
553
+ sopraffacente e la forza di inclinazione altamente
554
+ efficace.
555
+ Quando l'adoratore ridiventa sobrio, torna al
556
+ suo stato di bisogno e alla privazione del fidanza-
557
+ mento. Ma quando si sono completate le facoltà
558
+ che vengono dalla vicinanza con l'emancipazione
559
+ dello spirito, per mezzo della completezza della pri-
560
+ vazione, che non permette più che si parli, quando
561
+ la porzione della vicinanza si accumula e mantiene
562
+ il senso di fidanzamento del sé, allora questo è un
563
+ dono, e si può dire: "Oh Signore Iddio!".
564
+ Allora ascolta:
565
+ Nulla è più vicino a me di qualunque altra cosa, e
566
+ nulla è più lontano da me di ogni altra cosa ad ecce-
567
+ zione di quanto lo stabilisco in vicinanza e lonta-
568
+ nanza.
569
+ La lontananza è resa nota dalla vicinanza, e la
570
+ vicinanza è resa nota dall'esperienza spirituale: io
571
+ sono colui che la vicinanza non cerca, e che l'espe-
572
+ rienza spirituale non raggiunge.
573
+ Il minimo delle scienze della mia vicinanza è che
574
+ tu dovresti vedere gli effetti del mio sguardo in ogni
575
+ cosa, e che esso dovrebbe prevalere sopra la tua gno-
576
+ si di esso.
577
+ Tu non conosci la vicinanza, e tu non conosci la
578
+ mia vicinanza e non conosci la mia condizione come
579
+ io la conosco.
580
+ Io sono il vicino, non come una cosa è vicina ad
581
+ un'altra: io sono il lontano, ma non come una cosa
582
+ è lontana da un'altra.
583
+ La tua vicinanza non è la tua lontananza e la tua
584
+ lontananza non è la tua vicinanza: io sono il vicino
585
+ e il lontano, con una vicinanza che è lontananza e
586
+ una lontananza che è vicinanza.
587
+ La vicinanza che tu conosci è misurabile, è una
588
+ distanza: e la lontananza che tu conosci è misurabi-
589
+ le, è una distanza.
590
+ Io sono il vicino e il lontano senza misura.
591
+ Io sono più vicino alla lingua del suo discorso
592
+ quando parla.
593
+ Chi mi contempla non si raccoglie in meditazio-
594
+ ne e chi medita su di me non contempla. Come per
595
+ il contemplativo che medita, se ciò che contempla
596
+ non è realtà, egli è velato da ciò su cui medita. Non
597
+ tutti i meditativi sono dei contemplativi: ma ogni
598
+ contemplativo è un meditativo.
599
+ 10 rivelo me stesso e tu non mi conosci: questa è
600
+ lontananza.
601
+ 11 tuo cuore mi ha visto e non mi ha visto: questa
602
+ è lontananza.
603
+ Tu mi trovi e non mi trovi: questa è lontananza.
604
+ Tu mi descrivi e non mi cogli dalla descrizione:
605
+ questa è lontananza.
606
+ Tu ascolti i miei discorsi come se venissero dal
607
+ tuo cuore, mentre vengono da me: questa è lonta-
608
+ nanza.
609
+ Sebbene tu veda te stesso, io sono più vicino a te
610
+ della tua visione di te stesso: questa è lontananza.
611
+ Caro studioso, questo amore si manifesta nelle
612
+ tenebre, ed esce come una luce dall'oscurità. Dal
613
+ nero esce il bianco splendente dell'amore divino,
614
+ e dall'ignoranza e dal silenzio esce la parola di vita
615
+ e di gnosi che tu stai cercando. Tu non devi
616
+ confondere, e tu devi stare attento agli inganni.
617
+ Ascolta il Profeta, Dio benedica il suo nome:
618
+ Dio è la fiaccola che illumina i cieli e la terra. La sua
619
+ luce assomiglia a quella che sfugge da una nicchia di
620
+ cristallo dove brilla una fiamma inestinguibile. Il cri-
621
+ stallo è una stella di perle il cui splendore viene da un
622
+ ulivo benedetto che non è né d'Oriente né d'Occi-
623
+ dente. Il suo olio illumina senza contatto col fuoco. Vi
624
+ è là luce su luce. E Dio accorda la sua Luce a chi gli
625
+ piace. (Sura XXIV)
626
+ La pace sia con te.
627
+ TERZA LETTERA
628
+ Caro Maestro,
629
+ mi interrogate sugli obiettivi, tenterò una ri-
630
+ sposta.
631
+ Tre doni si dice procuri la Pietra Filosofale,
632
+ quelli che i re Magi portarono al bambino divino,
633
+ Pietra vivente e miracolo celeste.
634
+ Per primo l'Oro, la ricchezza mondana. È l'uni-
635
+ co descritto senza velamenti, con estrema preci-
636
+ sione.
637
+ Si prende la Pietra, si aggiunge in proporzioni
638
+ ben determinate a oro o argento in fusione, si
639
+ ottiene così 'a «Polvere di Proiezione», medicina
640
+ capace di curare o tingere i metalli imperfetti per
641
+ transmutarli in preziosi.
642
+ Mi chiedo perché sia posto tanto in evidenza:
643
+ non dovrebbe interessare il filosofo. Ci si è sforza-
644
+ ti di trovarvi un significato recondito, più nobile.
645
+ Quell'oro è diventato spirituale, mistico, simbolo
646
+ di cambiamenti umani; si è negata ogni realtà alla
647
+ transmutazione metallica e all'acquisto di dovizie.
648
+ Curiosamente la nostra epoca, tutta tesa alla ric-
649
+ chezza materiale e ai piaceri che questa può pro-
650
+ curare, ama esaltare quella miseria che in pratica
651
+ aborre. Non fu sempre così. Guardando le grandi
652
+ figure bibliche: Abramo si arricchisce con modi
653
+ ambigui, Giacobbe inventa trucchi per farsi un
654
+ gregge numeroso - aveva già dato prova di abilità
655
+ ulissiache per conquistare la primogenitura - di
656
+ Salomone si esaltano ricchezza e possessi.
657
+ Resta comunque un dono dall'aria perversa e
658
+ insoddisfacente. Non credo valga tanti sforzi, ci
659
+ sono modi più semplici per arricchire.
660
+ Seconda la Mirra, «Elisir di lunga vita», l'im-
661
+ mortalità fisica, l'eterna giovinezza al riparo da
662
+ ogni male. E il dono di Mefistofele, la fonte di
663
+ Ponce de Leon, la sorgente di ogni piacere e di
664
+ ogni dolcezza in vita.
665
+ Così sarebbe se non avesse in sé il suo veleno:
666
+ l'eterna vita in questo mondo.
667
+ Davvero questa sarebbe l'estrema beffa. Solo un
668
+ folle potrebbe voler restare un attimo più del do-
669
+ vuto. Già pesa il divieto di fuggirne, certo non
670
+ interessa restarci.
671
+ Ho il dubbio che sia qualcosa di diverso, forse
672
+ addirittura il suo opposto simbolico, la certezza di
673
+ non vivere, di non vivere più, non la Medicina Uni-
674
+ versale, ma il veleno perfetto, la perfetta morte.
675
+ 4 t«.
676
+ ' - e
677
+ 1
678
+ L ^ * « ^
679
+ l à i T f X H i H U o l ^ i f
680
+ I B A I 3 I M K - U H 5 1 V 1
681
+ ^
682
+ ^
683
+ ¿
684
+ ¿
685
+ ^
686
+ Mi*-
687
+ Manoscritto alchemico
688
+ arabo.
689
+ Infine l'Incenso, la completa sapienza, essere
690
+ come Salomone, conoscere tutti gli arcani del
691
+ mondo, i più reconditi recessi della Natura, i
692
+ misteri dell'Alto e del Basso. Questo davvero sem-
693
+ bra il giusto obiettivo di un filosofo, di un inna-
694
+ morato della Dottrina-, ritrovare la Parola Perduta,
695
+ la vera pronunzia del Nome, riscoprire la perla
696
+ nascosta, sembra l'unico scopo che valga.
697
+ Sin dalla prima operazione, perciò, la nostra
698
+ Magnesia deve richiamare, attrarre l'Angelo della
699
+ Conoscenza, perché è scritto:
700
+ Non è dato all'uomo che Dio gli parli altro che per una
701
+ comunicazione da dietro un velo, oppure gli invia un
702
+ Angelo. (Sura XLII, 50-51)
703
+ Lo spirito celeste di saggezza deve scendere
704
+ dall'Alto - l'incorporeo si deve corporificare - per
705
+ impregnare ciò che sta in Basso. Allora la nostra
706
+ Materia diventa Specchio della Natura e potremo
707
+ apprendere tutti i segreti del macrocosmo e del
708
+ microcosmo e gli arcani dell'umano e del divino.
709
+ L'obiettivo vero è la Gnosi, e il segreto del-
710
+ l'Opera consiste in una terra benedetta, la Terra
711
+ Santa, che permette all'angelo della gnosi di scen-
712
+ dere e di manifestarsi a noi per insegnarci la cono-
713
+ scenza perfetta.
714
+ Rispettosamente.
715
+ TERZA RISPOSTA
716
+ Caro studioso,
717
+ non dire mai che la conoscenza sta nel celestia-
718
+ le: nessuno discende con essa. Non dire nemmeno
719
+ che sta nei limiti del terrestre: nessuno ascende
720
+ con essa. Essa sta nei cuori.
721
+ Chi sei tu e chi sono io? E io vedo il sole e la
722
+ luna, le stelle e tutte le luci. Ed egli mi disse: Non
723
+ rimane alcuna luce nella corrente del mio mare, che
724
+ tu non hai visto.
725
+ E ogni cosa venne a me sinché non rimase nul-
726
+ la. E ogni cosa mi baciò tra gli occhi e si offrì ai
727
+ miei sensi e restò nell'ombra.
728
+ Ed egli mi parlò. Ed io vidi tutto di lui connes-
729
+ so al mio abito, cioè alla mia apparenza corporea,
730
+ e non connesso a me.
731
+ Ed egli mi disse: Questo è il mio servizio. Ed il
732
+ mio abito si inchinò, ma io non mi inchinai. E
733
+ quando il mio abito si inchinò, egli mi disse: Chi
734
+ sono io? E il sole e la luna si oscurarono, e le stel-
735
+ le caddero dal cielo e le luci impallidirono e le
736
+ tenebre coprirono ogni cosa, eccetto lui.
737
+ E tutte le cose parlarono e dissero: "Dio è gran-
738
+ dissimo".
739
+ E tutte le cose vennero da me, portando una
740
+ lancia in mano. Ed egli mi disse: Fuggi. Ed io dis-
741
+ si: "Dove debbo fuggire?". Ed egli mi disse: Cadi
742
+ nelle tenebre. E mi osservò. Ed egli mi disse:
743
+ Non dovrai mai più osservare altri che te stesso,
744
+ e non dovrai mai più allontanarti dalle tenebre da
745
+ adesso per sempre: ma quando io ti caccerò da esse,
746
+ io ti mostrerò me stesso e tu mi vedrai. E quando
747
+ mi avrai visto sarai più lontano da me di tutti colo-
748
+ ro che sono lontani.
749
+ L'etica della gente dello spirito cerca di impe-
750
+ dire ai sé di correre dietro ciò che vogliono, ma ciò
751
+ non può avvenire se non per coloro che hanno
752
+ saputo, ascoltato e si sono dedicati al divino per
753
+ prendere il vero dal vero, per dire il vero e per sta-
754
+ re in silenzio nel vero.
755
+ Se tu non mi vedi, non lasciare il mio nome.
756
+ Quando tu stai davanti a me, ogni cosa ti chiama:
757
+ fa' attenzione a non ascoltarla con il tuo cuore, per-
758
+ ché se tu l'ascolti è come se le rispondessi.
759
+ Quando la conoscenza ti chiama, con tutte le sue
760
+ condizioni, al tempo della preghiera, e tu le rispon-
761
+ di, tu sei separato da me.
762
+ Quando io guardo il tuo cuore, nessun'altra cosa
763
+ vi entra.
764
+ Se tu mi vedi nel tuo cuore, sei capace di soppor-
765
+ tarmi.
766
+ I miei amici sono quelli che non hanno nessuna
767
+ opinione
768
+ personale.
769
+ II tuo corpo dopo la morte sta nel posto del tuo
770
+ cuore prima della morte.
771
+ Quando tu stai di fronte a me, nessun altro starà
772
+ con te eccetto te.
773
+ Quando l'alterità diventa un pensiero biasimevo-
774
+ le, Paradiso e Inferno svaniscono.
775
+ La pace sia con te.
776
+ Il maestro e l'allievo, in un antico codice siriaco.
777
+ QUARTA LETTERA
778
+ Caro Maestro,
779
+ ho letto a lungo, con attenzione, come mi avete
780
+ suggerito, Jàbir, quello che ho potuto trovare in
781
+ traduzione: II piccolo libro della Clemenza, Il libro
782
+ della Misericordia, Il libro dei Settanta, Il libro del-
783
+ la Concentrazione, Il libro del fuoco della Pietra, Il
784
+ libro delle Bilance - su questo vorrei fare un di-
785
+ scorso a parte.
786
+ Per quanto riguarda il problema su cui mi inter-
787
+ rogo, ho trovato queste affermazioni:
788
+ Se tu, uomo intelligente, esamini tutte queste cose,
789
+ vedrai che lo scopo da raggiungere non si ottiene se non
790
+ con l'aiuto di cose diverse, cioè delle quattro nature.
791
+ Occorrono forze diverse, spirituali e corporali. Queste
792
+ forze debbono essere convergenti e non divergenti,
793
+ come forma e come colore.
794
+ Le forze spirituali e corporali devono avere delle affi-
795
+ nità tra loro, in modo da potersi aiutare reciprocamen-
796
+ te. Devono darsi sostegno, perché hanno bisogno una
797
+ dell'altra per la combinazione che si opera parte con
798
+ parte. Non devono essere opposte una all'altra, perché
799
+ bisogna che una volta mescolate non si separino una
800
+ dall'altra.
801
+ Tu devi operare in una sola volta, in maniera continua,
802
+ senza interruzione, per realizzare la mescolanza delle
803
+ parti, le une con le altre. Dovrà esserci equilibrio per
804
+ quanto riguarda la natura, la quantità e il peso.
805
+ L'operazione dovrà essere rigorosa, senza che si possa
806
+ sostituire una sostanza a un'altra.
807
+ L'elemento corporale è dominato dall'elemento spiri-
808
+ tuale in seguito all'operazione vera che lo trasforma in
809
+ elemento spirituale. L'elemento spirituale è ugualmen-
810
+ te dominato dall'elemento corporale e trasformato in
811
+ elemento corporale, sebbene in realtà non vi sia oppo-
812
+ sizione completa tra questi due elementi.
813
+ La massa delle cose corporali è soltanto il luogo di sog-
814
+ giorno e rifugio delle cose spirituali, e non ha di per sé
815
+ né forza né utilità quando la forza agente ha cessato di
816
+ agire in lei.
817
+ Il corpo che resta come sostrato non è che il luogo di
818
+ soggiorno e il rifugio dello spirito che ne è uscito, e non
819
+ ha forza se non per lo spirito che può uscire da lui.
820
+ Sono bloccato su questi passi, che da un lato mi
821
+ appaiono chiari, dall'altro non so tradurre in pra-
822
+ tica.
823
+ E vero che sempre in Jabir leggo:
824
+ Ho visto in effetti moltiplicando il numero dei miei
825
+ libri, allungandoli e riempiendoli di fatti, che nessuno
826
+ potrà arrivare ad estrarne la verità a meno di consa-
827
+ crarvi tutta la propria vita, di avere un'intelligenza
828
+ superiore, di dedicarvi tutto il proprio studio, di veglia-
829
+ re notte e giorno e di rinunciare a frequentare i propri
830
+ amici, privandosi del completo benessere.
831
+ Quindi non posso che rendermi conto che le
832
+ difficoltà che incontro sono inevitabili. Leggo pe-
833
+ rò anche:
834
+ Fatevi aiutare dalle persone intelligenti che si occupa-
835
+ no di questi lavori, perché i libri sono inchiavardati, e
836
+ le chiavi dei loro catenacci sono nei petti degli uomini.
837
+ Non posso che rivolgermi a voi per avere que-
838
+ ste chiavi.
839
+ Rispettosamente.
840
+ QUARTA RISPOSTA
841
+ Caro studioso,
842
+ Si dice che Jàbir abbia incontrato l'Imam Ja'far
843
+ al-Sàdiq quando aveva circa vent'anni in uno dei
844
+ suoi nascondigli, presso la tribù degli Azid nello
845
+ Yemen, e che diventò suo discepolo sin da allora.
846
+ La sua personalità perciò si formò religiosamente,
847
+ politicamente, scientificamente ed eticamente co-
848
+ me guardiano della dottrina dell'Imam.
849
+ Di conseguenza ecco Jàbir l'adoratore, lo gno-
850
+ stico Sufi, il lottatore politico e il ben informato
851
+ maestro di Alchimia.
852
+ L'Imam Ja'far, come maestro di setta e di pen-
853
+ siero, e uomo di miracoli e poteri occulti della
854
+ discendenza del Profeta, era l'oppositore politico
855
+ del potere Abbaside da quando si era posto come
856
+ guardiano dei valori islamici e dei loro concetti.
857
+ Si può percepire il tipo di relazione e di intimità
858
+ spirituale di meravigliose visioni e profondità tra
859
+ l'Imam Abi Abdullah e il suo discepolo Jàbir. Gli
860
+ aspetti di questo legame sono numerosi e ovvia-
861
+ mente diversi nei suoi scritti, nel suo stile, nella
862
+ sua mentalità e nella sua metodologia. Si può rico-
863
+ noscere la presenza dell'Imam Ja'far potentemen-
864
+ te dietro ogni riga scritta da Jàbir, e nessuno dei
865
+ suoi trattati fa eccezione. Questa presenza si cela
866
+ nel testo come metodo scientifico-mistico ed è in-
867
+ dicazione armoniosa della convergenza dell'esso-
868
+ terico e dell'esoterico. E un profondo amore spiri-
869
+ tuale in tutto il significato sublime e in tutte le
870
+ dimensioni, mescolato a senso di gratitudine e glo-
871
+ rificazione per il suo grande maestro che ha svela-
872
+ to l'occulto segreto della conoscenza e fatto ribol-
873
+ lire le meravigliose tacite fontane della genesi e
874
+ della creazione davanti ai suoi occhi.
875
+ Dice Jàbir:
876
+ I gradi dell'Elixir devono stare sulla linea della bilancia,
877
+ questo si deve sapere. Nell'onorevole diritto del mio
878
+ maestro, io giuro che questo è senza simboli e senza
879
+ prolissità.
880
+ In un altro passo, Jàbir dice che il suo maestro
881
+ gli ordinò:
882
+ Prepara un libro di piena maturità e profondità con più
883
+ essenza e meno prolissità sull'alchimia, e poi mostra-
884
+ melo.
885
+ La risposta di Jàbir fu l'obbedienza, ed egli disse:
886
+ L'ho fatto nel diritto pieno di grazia del mio maestro,
887
+ ho rivelato cose, le ho ridotte all'essenza. Ho mostrato
888
+ alla gente la giusta via.
889
+ Jàbir dichiara anche che il maestro gli donò la
890
+ visione penetrante della bilancia, e diffuse la sua
891
+ parola su questo dicendo:
892
+ Così parla il maestro, e così egli mi ordinò di scrivere e
893
+ classificare.
894
+ Molte volte egli menziona le direttive del suo
895
+ maestro e parla del Mercurio:
896
+ Il mio maestro mi raccontò tutto intorno ai suoi padri,
897
+ uno ad uno.
898
+ Questo tipo di pensiero raggiunge il suo sommo
899
+ e la sua presenza sublime una volta che si ricordi
900
+ il messaggio che l'Imam Ja'far dettò a Jàbir, suo
901
+ discepolo favorito, sul segreto della natura e sulle
902
+ più piccole cose della saggezza universale che pos-
903
+ sono essere riassunte come espressioni dell'Opera.
904
+ La visione dei fatti taciti dell'esistenza attraverso la
905
+ contemplazione esoterica. Il principio della bilan-
906
+ cia come si deduce dalla giustizia divina e dal sen-
907
+ so Qur'anico del mondo:
908
+ Ed Egli ha fatto sorgere alto il firmamento, ed Egli ha
909
+ fissato la Bilancia [di giustizia], (Sura LV, 7)
910
+ Secondo Jabir la realizzazione totale della pro-
911
+ fessione alchemica viene attraverso due percorsi:
912
+ l'esterno essoterico e l'interno esoterico.
913
+ Il primo cammino è la realizzazione del ragio-
914
+ namento e dei tratti delle leggi generali e dello sta-
915
+ to di unione di natura, mente e anima.
916
+ Il secondo cammino, l'esoterico, è legato alla
917
+ conoscenza delle leggi e degli stati impegnati ver-
918
+ so il divino. Questo cammino può essere stabilito
919
+ mantenendo i grandi fatti universali e la purifica-
920
+ zione di se stessi e dei propri fini, insieme a chia-
921
+ rezza e sincerità interiori.
922
+ Le grandi rivelazioni, come la conoscenza del-
923
+ l'interiore, Jàbir le ottenne attraverso il suo mae-
924
+ stro Ja'far Abi Abdullah Al-Sàdiq, perché le fon-
925
+ tane essoteriche sono le ombre di quelle esoteriche
926
+ che fluiscono dalla luce divina latente nello spiri-
927
+ to dell'uomo.
928
+ L'Imam Sàdiq indicò a Jàbir il profondo senso
929
+ di soddisfazione, quiete e tranquillità e gli rivelò i
930
+ cammini per visualizzare il tacito, e l'innata attra-
931
+ zione verso la conoscenza del vero senza veli.
932
+ Inoltre Jàbir asserisce il significato della bilan-
933
+ cia come conoscenza del numero, del rapporto di
934
+ quantità e delle leggi degli elementi di natura e dei
935
+ composti, ai quali si riferisce nei trattati che seguo-
936
+ no il criterio dell'analogia.
937
+ Esoterico ed essoterico, secondo Jàbir, simbo-
938
+ leggiano l'alternata apparizione e scomparsa del-
939
+ l'Imam Ja'far al-Sàdiq.
940
+ Caro studioso, non mi fraintendere, si sta medi-
941
+ tando sul compendio della saggezza.
942
+ La pace sia con te.
943
+ QUINTA LETTERA
944
+ Caro Maestro,
945
+ ho finito la lunga preparazione dei materiali: li
946
+ ho purificati, esaltati, predisposti con cura per il
947
+ primo incontro.
948
+ E primavera, tra poco inizierò la quarantena
949
+ sacra. La materia è nel suo nido, ne attendo con
950
+ ansia il risveglio. Attendo, come dice Boehme, che
951
+ scendano gli angeli.
952
+ Lavorando quietamente, la riflessione sulle qua-
953
+ lità e le preparazioni della materia conduce a quel-
954
+ le òdi'artista.
955
+ I maestri danno poche indicazioni, insoddisfa-
956
+ centi. Il tema sembra o poco importante o sconta-
957
+ to. Si sottolinea la necessità di buoni caratteri fisi-
958
+ ci: salute e integrità di corpo. Si aggiungono
959
+ facoltà intellettive: memoria, comprensione, facile
960
+ apprendimento. Si cita dedizione allo studio e al
961
+ lavoro, paziente costanza. Pietas, timor di Dio,
962
+ innocenza, sono ricordati pudicamente.
963
+ Riassume tutto molto concisamente Geber la-
964
+ tino:
965
+ Diciamo pertanto, che se non avrà ingegno naturale, e
966
+ una mente che scruti sottilmente i principi naturali, e i
967
+ fondamenti della natura, non troverà la vera radice di
968
+ questa preziosissima scienza. Inoltre ne abbiamo trova-
969
+ to molti, che hanno una mente che crede facilmente a
970
+ qualsiasi fantasia. Ma il vero che credono di aver tro-
971
+ vato, è affatto fantastico, aberrante, e pieno di errori e
972
+ lontanissimo dai principi naturali, poiché il loro cervel-
973
+ lo, colmo di molte fumosità, non può accogliere il vero
974
+ intento delle cose naturali. Altri ancora sono schiavi del
975
+ denaro: desiderano questa scienza, affermano che essa
976
+ è meravigliosa e vera, ma temono le spese. Pertanto,
977
+ sebbene ne siano convinti, e la indaghino correttamen-
978
+ te, tuttavia non giungono all'esperienza dell'opera per
979
+ avarizia di denaro. Pertanto a tutti questi non giunge la
980
+ nostra scienza.
981
+ Siamo nell'ovvietà. Stupisce la mancanza di sof-
982
+ ferenze meritorie, quelle che sono norma per qual-
983
+ siasi cammino di perfezione, fatte di sacrifici, asce-
984
+ si, rinunce, digiuni: ci si purifichi, immersi nel do-
985
+ lore, se appena si vuole ottenere qualcosa.
986
+ Sono disarmato di fronte a questo silenzio. Pare
987
+ manchi qualcosa, un vuoto da colmare che cerco
988
+ di soddisfare con altri insegnamenti, riversando
989
+ sensi simbolici in frasi dall'apparenza innocua.
990
+ L'Opera è essenzialmente arte del fuoco, e l'al-
991
+ chimista proprio per questo può diventare philo-
992
+ sophus per ignem, filosofo per mezzo del fuoco.
993
+ Leggo perciò con una certa preoccupazione Jàbir
994
+ quando afferma:
995
+ Il fuoco aumenta le virtù del saggio e la corruzione del
996
+ perverso.
997
+ Un problema dunque si pone, che voi avete più
998
+ volte definito come necessità dell'«etica della te-
999
+ stimonianza», ed io chiedo praticamente dove
1000
+ conduca. Perché siamo affamati di precetti, di leg-
1001
+ gi da seguire.
1002
+ Una norma tuttavia esiste, misteriosa e incom-
1003
+ prensibile: «Siate veridici». Sottolineata come vir-
1004
+ tù singolare e significante, è difficile coglierne il
1005
+ valore. Non si trova come regola di santità, am-
1006
+ mettendo che santità sia strumento di misura. Non
1007
+ è difficile da praticare nella sua formulazione più
1008
+ evidente.
1009
+ Proprio per questo temo abbia significati più
1010
+ profondi, difficili da decifrare.
1011
+ Rispettosamente.
1012
+ QUINTA RISPOSTA
1013
+ Caro studioso,
1014
+ tu devi capire che esiste una veracità della lin-
1015
+ gua, e una veracità del cuore, e che è della secon-
1016
+ da che noi parliamo.
1017
+ La prima consiste nel fatto che la tua lingua non
1018
+ dovrebbe mentire. La seconda consiste nel fatto
1019
+ che il tuo cuore non dovrebbe mentire.
1020
+ La menzogna della lingua consiste nel soffer-
1021
+ marsi su ciò che non è stato detto, e nel dire e non
1022
+ fare. La menzogna del cuore consiste nel credere
1023
+ e non fare. La menzogna del cuore consiste nel
1024
+ dare ascolto ad una menzogna.
1025
+ Ogni menzognero è altro da me.
1026
+ La verità autentica è la mia voce: se io voglio fac-
1027
+ cio parlare con essa una pietra o un uomo.
1028
+ Qualunque cosa ti lega a me è il mio discorso che
1029
+ proviene dalla mia voce.
1030
+ Il desiderio è una menzogna del cuore. Il deside-
1031
+ rio è il seme del Nemico in ogni cosa.
1032
+ Io ti ho reso inadatto ad ogni cosa e ho fatto si
1033
+ che questo fosse un velo tra te e questo. Non lace-
1034
+ rare il velo prestando attenzione alle cose, perché io
1035
+ manderei su di te la loro umiliazione. Se tu fossi sta-
1036
+ to adatto ad ogni cosa, io non ti avrei rivelato il mio
1037
+ volto.
1038
+ Quando ti capita qualcosa con la sua tentazione,
1039
+ considera l'origine della sua creazione e vedrai che
1040
+ questa la condurrà via da te. Se tu non vedi l'origi-
1041
+ ne della sua creazione, allora considera il fine del
1042
+ suo manifestarsi, e vi cercherai religiosità
1043
+ dentro,
1044
+ ma tu non la vedrai.
1045
+ L'origine è forza, il fine è debolezza:
1046
+ chiedimi
1047
+ perdono per una debolezza su cui hai potere per
1048
+ mezzo di una debolezza.
1049
+ La pace sia con te.
1050
+ .tléimiltife
1051
+ uutraa :cm
1052
+ i
1053
+ i
1054
+ m
1055
+ o ftr ìan'um
1056
+ i
1057
+ n
1058
+ .
1059
+ «
1060
+ K
1061
+ T
1062
+ U i-H'.^»'.
1063
+ mm
1064
+ ••><..ì
1065
+ ^
1066
+ ]dbir, il Maestro dei Maestri, chiamato Gcber dai latini
1067
+ Caro Maestro,
1068
+ la primavera è passata immersa nell'operosità.
1069
+ L'essoterico risponde alle attese: i fenomeni sono
1070
+ stupefacenti e meravigliosi, i colori splendidi, i ri-
1071
+ sultati prodigiosi.
1072
+ L'esoterico non appaga: manca qualcosa di es-
1073
+ senziale, compaiono immagini di illusione.
1074
+ Un vecchio maestro di Francia scriveva:
1075
+ Ecco il segreto.
1076
+ Sappi che tutti parlano allo stesso modo in due modi,
1077
+ di cui uno è vero e l'altro falso.
1078
+ Il vero è tale da non poter essere inteso che dai soli
1079
+ Illuminati che camminano rettamente e secondo natu-
1080
+ ra, ed è tuttavia coperto da paragoni ed esempli, sotto
1081
+ nomi ed equivoci che non appartengono alla dottrina
1082
+ ma ne sono significanti, perché in lei non occorre che
1083
+ una sola cosa, un solo modo di operare, per una via
1084
+ semplice e naturale, senza perdersi nella pluralità delle
1085
+ cose contrarie al nostro unico lievito.
1086
+ Il falso è questa confusione di regimi e droghe cattive,
1087
+ sebbene il tutto sia significante di qualcosa che appar-
1088
+ tiene alla dottrina, tuttavia non si deve considerare la
1089
+ qualità, perché la Natura è semplice e non opera che
1090
+ semplicemente.
1091
+ 53
1092
+ È il momento del dubbio e dell'incertezza, mo-
1093
+ mento fatale e pericoloso, forse inevitabile. Il con-
1094
+ fine tra vero e falso, tra inganno e realtà, è molto
1095
+ più sottile di quel che si possa immaginare, e lo
1096
+ stesso operare a questo punto è causa di ulteriore
1097
+ incertezza.
1098
+ Tutti hanno opinioni sulFAlchimia. Due ipotesi
1099
+ riassumono i pensieri sulla Grande Opera.
1100
+ Una dice che le operazioni descritte sembrano
1101
+ chimiche, mentre in realtà sono spirituali, o men-
1102
+ tali: descrizioni psicologiche dell'evoluzione inte-
1103
+ riore, atti dell'immaginare o della volontà, visioni
1104
+ che nascono dall'intimo.
1105
+ L'altra assimila il forno al corpo fisico dell'uo-
1106
+ mo, e la materia a un'energia sottile che deve cre-
1107
+ scere, salire, cuocere nei suoi intimi recessi.
1108
+ Entrambe leggono l'Opera come simbolo, anzi
1109
+ come allegoria di diverse verità.
1110
+ Attraggono e respingono: entrambe suonano
1111
+ difettose nella loro estrema ragionevolezza.
1112
+ Ricordo un passo che mi avete insegnato:
1113
+ Noi proponemmo il deposito dei nostri segreti ai Cieli,
1114
+ alla Terra, ai Monti: tutti rifiutarono di assumerlo, tut-
1115
+ ti tremarono al pensiero di riceverlo. Ma l'uomo ac-
1116
+ cettò di incaricarsene: è un violento, un incosciente.
1117
+ (Sura XXXIII, 72)
1118
+ Sento che si devono scoprire pensieri insensati,
1119
+ vedere cose irragionevoli, sentire stridori inaccet-
1120
+ tabili: scopro che nell'Opera si può vedere e non
1121
+ vedere, conoscere e non conoscere. Gli stessi
1122
+ occhi nascondono le cose, le orecchie cancellano i
1123
+ suoni, la mente ricompone tutto a sua immagine,
1124
+ la caligine infittisce di fronte al meraviglioso, come
1125
+ se volesse proteggerlo in una deformazione appro-
1126
+ priata all'osservatore.
1127
+ Tutto appare chiaro e comprensibile, e questa
1128
+ stessa sensatezza, tanto gradevole, tanto conve-
1129
+ niente, genera perplessità e angoscia. Manca l'eso-
1130
+ terico dell'esoterico.
1131
+ Distinguere tra il vero e il falso di cui parla il
1132
+ vecchio maestro sembra impossibile.
1133
+ Rispettosamente.
1134
+ SESTA RISPOSTA
1135
+ Caro studioso,
1136
+ la verità è ciò da cui non ti allontaneresti, anche
1137
+ se tutto il popolo del cielo e della terra te ne allon-
1138
+ tanasse. La falsità è ciò che non accetteresti, anche
1139
+ se tutto il popolo del cielo e della terra ti invitasse
1140
+ a farlo. Ora, per comprendere meglio quanto sto
1141
+ per dirti, devi imparare a distinguere tra stato e
1142
+ situazione. Il primo è un dono di Dio, la seconda
1143
+ è il risultato della tua opera.
1144
+ Stato e situazione sembra siano la stessa cosa
1145
+ perché differiscono solo minimamente a causa del-
1146
+ la loro intercambiabilità, ma una situazione è una
1147
+ fase durante un cambiamento, mentre lo stato è
1148
+ tale per la sua stabilità.
1149
+ Una situazione si muove per diventare stato,
1150
+ come l'emissione di un dubbio da parte dell'ado-
1151
+ ratore si concretizza tacitamente nella richiesta
1152
+ della verifica.
1153
+ La struttura ricorrente dell'apparire e scompa-
1154
+ rire del dubbio è il risultato di un conflitto nell'a-
1155
+ rena del sé. Questa è una situazione.
1156
+ Il superamento del dubbio, sostenuto da fede
1157
+ profonda che trascende il sé, diventa uno stato.
1158
+ La situazione della verifica viene dopo, perché
1159
+ colui che ha lo stato del dubbio, vorrebbe avere la
1160
+ situazione della verifica.
1161
+ La situazione della verifica va e viene con pie-
1162
+ nezza di mente e mancanza di mente nel profon-
1163
+ do dell'essenza dell'adoratore, sino a quando la
1164
+ nebbia della mancanza di mente scompare soste-
1165
+ nuta dal sostegno di Dio per rendere la verifica
1166
+ uno stato.
1167
+ Lo stato del dubbio non si fissa mai a meno che
1168
+ la situazione della verifica non si sostanzi, e questo
1169
+ stato non si fissa sinché non avviene la situazione
1170
+ della vista.
1171
+ Con i doni della vista, la verifica si fissa come
1172
+ stato, dopo essere stata una situazione.
1173
+ L'avvento della vista diventa una situazione che
1174
+ va e viene con un velame. Allora diventa uno
1175
+ stato:
1176
+ E il suo sole libera dall'eclissi, dal velame e dalla
1177
+ nebbia.
1178
+ La visione della verità scende nelle profondità
1179
+ del cuore per essere la situazione più alta della
1180
+ visione.
1181
+ Il nostro Profeta Mohammad - la pace su di
1182
+ lui - dice: "O Signore, io ti prego di farmi avere
1183
+ un dono di fede che penetri il mio cuore".
1184
+ Conoscimi con la gnosi della certezza rivelata, fa
1185
+ noto il tuo sé al tuo Maestro per mezzo di certezza
1186
+ rivelata. Scrivi il modo della mia autorivelazione a
1187
+ te per mezzo della gnosi della certezza rivelata, scri-
1188
+ vi come io ho fatto sì che tu fossi testimone e come
1189
+ tu abbia reso testimonianza. Questo può essere un
1190
+ ricordo per te e uno stabilirsi per il tuo cuore.
1191
+ Sappi che i doni di Dio Onnipotente sono sen-
1192
+ za limiti, e situazione e stato sono doni correlati
1193
+ alle parole di Dio che sono troppo numerose per
1194
+ essere scritte anche avendo l'inchiostro di tutti i
1195
+ mari, e sono più innumerevoli dei granelli di tutte
1196
+ le sabbie.
1197
+ Dio è il misericordioso dispensatore e donatore.
1198
+ Egli mi pose nella verità della gnosi e mi disse:
1199
+ Come per questo momento c'è un sopra e un sot-
1200
+ to, tutti i fenomeni sono questo mondo e tutto que-
1201
+ sto insieme e tutto ciò che contiene sta in attesa
1202
+ dell'Ora. Sopra di lui e sopra tutto ciò che contiene
1203
+ ho scritto la fede, e l'essenza della fede è: "Non c'è
1204
+ nulla come lui".
1205
+ Chiama a testimoniare Gabriele e Michele,
1206
+ chiama a testimoniare il Trono e i portatori del
1207
+ Trono, chiama a testimoniare ogni angelo e ogni
1208
+ possessore di gnosi, e vedrai la realtà della sua
1209
+ fede, mentre dice e dà testimonianza che non c'è
1210
+ nulla come lui.
1211
+ Tu vedrai che conoscenza di questo è esperien-
1212
+ za, e che esperienza di questo è conoscenza.
1213
+ Tu vedrai che questo è il limite della gnosi,
1214
+ vedrai che quella è l'autentica verità, vedrai che
1215
+ quella è la vera conoscenza della visione, non la
1216
+ visione in sé.
1217
+ Osservali: ciascuno di loro veglia in attesa del-
1218
+ l'Ora. Attendono che si alzi il velo, attendono il
1219
+ levarsi della copertura.
1220
+ Ma non si possono sopportare le condizioni di
1221
+ realtà di colui che sta dietro al velo, se non per suo
1222
+ mezzo.
1223
+ Come sarà quando il velo sarà strappato? Per-
1224
+ ché il velo sarà strappato e in questo strappo sta
1225
+ un assalto che non può essere sostenuto dalla
1226
+ natura delle cose create.
1227
+ Se il velo fosse alzato e non strappato, colui che
1228
+ sta sotto di lui troverebbe riposo. Ma è strappato
1229
+ e quando questo avviene la gnosi dello gnostico
1230
+ sarà dimenticata. Nel dimenticare sarà rivestita da
1231
+ una luce, che farà sì che si possa sopportare ciò
1232
+ che si manifesta dopo lo strappo. E questo dimen-
1233
+ ticare è un bene perché con la gnosi non si potreb-
1234
+ be sopportare ciò che viene manifestato.
1235
+ La pace sia con te.
1236
+ Carovana di pellegrini
1237
+ musulmani.
1238
+ SETTIMA LETTERA
1239
+ Caro Maestro,
1240
+ l'unione delle Nature è un mistero che non si
1241
+ riesce a penetrare. La congiunzione degli opposti
1242
+ richiede un Mediatore che pare più divino che
1243
+ umano. Credo sia del genere di cui parla Jàbir nel
1244
+ Libro della Misericordia:
1245
+ Quante cose ci sono in questo mondo, spirituali e sot-
1246
+ tili, che i sensi non possono percepire e che non si pos-
1247
+ sono conoscere che per intelligenza!
1248
+ Mentre riprendo molto umilmente e paziente-
1249
+ mente le materie per predisporle all'Opera, stu-
1250
+ dio, medito, cerco di capire. In effetti capire non è
1251
+ verbo da usarsi, perché questo arcano lo credo
1252
+ occultato dalla sua stessa assurdità. Per la realiz-
1253
+ zazione si deve concepire qualcosa di inesplicabi-
1254
+ le, e questa non sarà una comprensione, può esse-
1255
+ re una visione.
1256
+ Torno, ai libri con maggior prudenza. Ho letto
1257
+ il racconto di Khalid, il principe alchimista:
1258
+ Sappi che il mio discepolo Musa, il più onorevole di
1259
+ tutti presso di me, studiò molto sui libri (dei Sapienti)
1260
+ e faticò molto nell'opera del magistero, ma non riuscì a
1261
+ conoscere il modo della composizione.
1262
+ Allora, supplice e umile, me ne chiese una spiegazione
1263
+ e un consiglio. Io non gli detti risposta né indicazioni,
1264
+ ma gli prescrissi di leggere i libri dei Filosofi e di cer-
1265
+ care in quelli ciò che aveva chiesto a me.
1266
+ Egli allora, andatosene, lesse più di cento libri, tutti
1267
+ quelli che potè trovare: libri certamente veridici, segre-
1268
+ ti, dei più nobili Filosofi, ma non vi potè trovare ciò che
1269
+ cercava, e rimase attonito e quasi stravolto.
1270
+ Penso che l'errore più ovvio consista nel ricon-
1271
+ durre tutto alle operazioni, alle esperienze fatte, in
1272
+ una interpretazione ingenuamente tecnica. Mi ri-
1273
+ peto le parole di un antichissimo filosofo musul-
1274
+ mano:
1275
+ Quest'arte non è forse Cabalistica e piena di grandissi-
1276
+ mi segreti? E tu, stupido pazzo, tu credi che noi inse-
1277
+ gniamo chiaramente i segreti dei segreti? E prendi le
1278
+ parole secondo il loro suono letterale?
1279
+ Sappi per certo che chiunque prende le parole dei
1280
+ Filosofi secondo il significato volgare e ordinario, sba-
1281
+ glia enormemente.
1282
+ Ho ripreso il Libro delle Bilance, e mi perdo in
1283
+ infiniti giochi di cabala, che stupiscono per l'e-
1284
+ strema sottigliezza delle analogie. Con queste ten-
1285
+ to di penetrare nel contenuto delle lettere, di
1286
+ vedere ciò che queste racchiudono, la sostanza,
1287
+ non il vaso.
1288
+ Mi smarrisco in innumerevoli esercizi, correla-
1289
+ zioni, scomposizioni minuziose e calcoli labirinti-
1290
+ ci. Lascio il senso letterale e ne scopro mille occul-
1291
+ ti che svelano e ri-velano, come statuine russe che
1292
+ sembrano non dover mai finire in un continuo
1293
+ rimpicciolirsi.
1294
+ Jabir voleva insegnarci a pesare lo Spirito, capi-
1295
+ sco che il mio strumento non è corretto, le misu-
1296
+ razioni si perdono in un'analisi sterile nella sua
1297
+ apparente, mostruosa, fecondità.
1298
+ La materia è silente. Temevo la sua voce, ora il
1299
+ suo silenzio mi offende.
1300
+ Rispettosamente.
1301
+ SETTIMA RISPOSTA
1302
+ Caro studioso,
1303
+ considera la lettera e ciò che contiene dietro di
1304
+ sé. Se presti attenzione alla lettera, vi cadrai den-
1305
+ tro. Se presti attenzione a quello che contiene,
1306
+ cadrai in quello che contiene.
1307
+ Non disperare: la generosità di Dio è più grande
1308
+ della lettera di cui trovi la teoria e della lettera di
1309
+ cui conosci la teoria, della lettera di cui non trovi
1310
+ la teoria e della lettera di cui non conosci la teoria.
1311
+ Quando tu stai con Dio, vedi cosa scende e cosa
1312
+ sale, e ogni lettera viene da te con tutto ciò che
1313
+ contiene, e ogni cosa si rivolge a te nella sua lin-
1314
+ gua e ogni esposizione si spiega per te secondo la
1315
+ sua esposizione.
1316
+ La guida appartiene per natura al velo, e il velo
1317
+ è la punizione. Perciò se la tua guida è della natu-
1318
+ ra del velo, sarai velato dalla realtà di ciò verso cui
1319
+ sei guidato:
1320
+ Io sono il velo del mio gnostico, e sono la guida
1321
+ del mio gnostico. Io faccio conoscere me stesso ed egli
1322
+ mi conosce e sa che io faccio conoscere me stesso. Io
1323
+ velo me stesso, ed egli mi conosce e sa che io velo me
1324
+ stesso.
1325
+ Caro studioso, colui la cui guida non è Dio, non
1326
+ è unito a Dio. Ascolta:
1327
+ Quando tu conosci la conoscenza che procede da
1328
+ me, io ti punisco se segui coloro che non sanno, e ti
1329
+ punisco anche se segui coloro che sanno.
1330
+ L'uomo che è sotto l'effetto del sé, sta sotto il
1331
+ velo della tenebra a causa della sua esistenza mate-
1332
+ riale. Ma quando il suo cuore esce dal suo velo,
1333
+ allora raggiunge la vicinanza senza l'effetto del sé.
1334
+ L'ignoranza è il velo della visione e la cono-
1335
+ scenza è il velo della visione. Egli è il manifesto
1336
+ senza velo e il nascosto senza svelamento.
1337
+ Colui che conosce il velo è vicino allo svela-
1338
+ mento. Il velo è uno, le cause per mezzo delle qua-
1339
+ li si manifesta sono diverse, e queste sono vari veli.
1340
+ Ascolta l'Imam Ja'far:
1341
+ La nostra causa è un segreto dentro un segreto, il segre-
1342
+ to di qualcosa che resta velato, è un segreto che solo un
1343
+ altro segreto può spiegare, è un segreto su un segreto
1344
+ che si appaga di un segreto.
1345
+ La pace sia con te.
1346
+ jabir tra i grandi Maestri dell'Alchimia
1347
+ occidentale.
1348
+ OTTAVA LETTERA
1349
+ Caro Maestro,
1350
+ un quesito si impone, continuo, a chi è sulla
1351
+ Via, che si ripete ad ogni grado in forme rinnova-
1352
+ te eppure costanti.
1353
+ Si può tradurre molto semplicemente. Consiste
1354
+ nella necessità, e nell'impossibilità, di conciliare
1355
+ l'esistenza banale, terrena, quotidiana, con la sa-
1356
+ cralità dell'Opera e con le sue manifestazioni spi-
1357
+ rituali.
1358
+ Chi non abbandoni per un eremitaggio o una
1359
+ cella la vita che conduce nel mondo, soffre di que-
1360
+ sta antinomia persecutrice e non sa, o non può,
1361
+ risolverla. Rischia di essere incapace nell'uno e
1362
+ nell'altro luogo, zoppo per avere un piede qui e
1363
+ uno altrove, instabile nella più assoluta precarietà.
1364
+ Un alchimista cinese insegnava:
1365
+ La ricerca non è complicata. Basta fare alcune cose.
1366
+ L'unico problema è che quasi sempre la volontà non è
1367
+ ferma e la fede non è confermata.
1368
+ Perché trascurare gli interessi umani? Il vero artista rie-
1369
+ sce senza difficoltà ad occuparsi degli affari e del-
1370
+ l'Opera. Mentre in privato osserva rigorosamente la
1371
+ Via, pubblicamente è impegnato negli affari mondani.
1372
+ In tal modo raggiunge una grande perfezione perché è
1373
+ tenuto a controllarsi.
1374
+ Una tale persona è eccellente.
1375
+ Scriveva secoli fa. Sorge il dubbio che inserito
1376
+ in una società, come si suol dire, tradizionale,
1377
+ potesse sostenere onestamente opinioni che oggi
1378
+ non è dato immaginare.
1379
+ La sofferenza più grande consiste nella perdita
1380
+ quando si è ricondotti alla discesa nel profano. Ne
1381
+ viene un inevitabile senso di fastidio per tutto ciò
1382
+ che ci vuole immobili nel mondo, una profonda
1383
+ insofferenza. Ma quello che davvero appare insop-
1384
+ portabile è il timore di non poter tornare nel luo-
1385
+ go da cui siamo stati strappati, di aver perso il
1386
+ Dono per mancanza di consuetudine, peggio, per
1387
+ distrazione.
1388
+ Stupisce che l'acquisito si possa perdere con
1389
+ tanta facilità, e lo stupore diviene ansia di ritorno,
1390
+ angoscia di aver perso la strada.
1391
+ La domanda perciò si complica. Diventa richie-
1392
+ sta di una guida nel comportamento, di un modo
1393
+ per non abbandonare la visione, di un metodo che
1394
+ renda laboratorio ogni atto del vivere e permetta di
1395
+ continuare senza interruzioni.
1396
+ Mi chiedo se sia possibile.
1397
+ Rispettosamente.
1398
+ OTTAVA RISPOSTA
1399
+ Caro studioso,
1400
+ un seminatore seminò una manciata di semi, ma
1401
+ egli non aveva ancora raggiunto la strada, che li
1402
+ uccelli li avevano mangiati. Alcuni altri semi creb-
1403
+ bero su una roccia liscia su cui c'era poca sabbia e
1404
+ poca rugiada: le loro radici soffocarono nella soli-
1405
+ da roccia e furono spazzate via. Alcuni altri semi
1406
+ crebbero in una buona terra, ma questa era piena
1407
+ di rovi che li soffocarono e distrussero. Altri semi
1408
+ crebbero in una buona terra senza rocce né rovi e
1409
+ si trasformarono in buona forma e frutti.
1410
+ Il seminatore è come parlare della rettitudine, e
1411
+ ciò che avviene per strada è come un uomo che tro-
1412
+ va il racconto dell'ascoltare inutile: appena l'avrà
1413
+ ascoltato, il diavolo lo strappa via sinché lo dimen-
1414
+ tica.
1415
+ I semi sulla roccia liscia sono come un uomo
1416
+ che trova il discorso degno di essere ascoltato,
1417
+ eppure questo raggiunge un cuore che non vuole
1418
+ comprenderlo a fondo, e così la parola declina.
1419
+ I semi nella terra dei rovi sono come un uomo
1420
+ che trova la parola degna di essere ascoltata, eppu-
1421
+ re i piaceri si sono stabiliti nel petto intorno al
1422
+ cuore, la materia non può essere compresa a fon-
1423
+ do per i suoi pregiudizi e la sua volubilità.
1424
+ I semi che crescono sulla terra buona, senza
1425
+ rocce né rovi, sono come il discorso che raggiun-
1426
+ ge un cuore e vi resta per essere compreso a fon-
1427
+ do. E come un albero con i rami nel terrestre e le
1428
+ radici profondamente stabilite nel celeste. Il suo
1429
+ frutto è gustoso, bello a vedersi e aromatico, e atti-
1430
+ ra gli uomini da ogni parte del mondo.
1431
+ II mio nome e i miei nomi sono posti dentro di
1432
+ te: non cacciarli o io mi allontanerò dal tuo cuore.
1433
+ Egli stava dentro di me e mi disse:
1434
+ La conoscenza è più dannosa dell'ignoranza per
1435
+ colui che mi vede.
1436
+ Una buona opera vale dieci per colui che non mi
1437
+ vede, ma è danno per colui che mi vede.
1438
+ Quando tu mi vedi, la tua sicurezza è più grande
1439
+ nell'omissione che nel servizio. Quando tu non mi
1440
+ vedi, la tua sicurezza è più grande nel servizio che
1441
+ nell'omissione.
1442
+ Quando tu mi vedi, ogni cosa che tu vedi altra da
1443
+ me con il tuo occhio e il tuo cuore, ti separa da me.
1444
+ Chiedi il mio perdono per l'atto del cuore, e io ti
1445
+ libererò dalla mutevolezza.
1446
+ L'atto del cuore è la radice dell'atto del corpo:
1447
+ considera quindi cosa hai seminato e considera qua-
1448
+ le frutto porta la semenza.
1449
+ La mia mano è sul cuore. Perciò se tu trattenessi
1450
+ da esso la sua propria mano, né prendendo con essa
1451
+ né dando, tu semineresti la mia autorivelazione per
1452
+ mezzo di esso, ed esso produrrebbe il frutto di ve-
1453
+ dermi.
1454
+ Temi una buona azione che demolisce le buone
1455
+ azioni, e temi un peccato che erige i tuoi peccati.
1456
+ Quando tu mi vedi e ottieni da me i mezzi del-
1457
+ l'indipendenza, io non sarò assente da te.
1458
+ La tribolazione è la tribolazione di colui che mi
1459
+ vede. Egli non può sopportare la mia persistenza, e
1460
+ non può sopportare la sua interruzione. Mentre io
1461
+ sono al centro di questo, srotolandolo e arrotolandolo.
1462
+ Neil'arrotolare sta la morte, nello srotolare sta la vita.
1463
+ Io sono l'obiettivo dei miei amici cari. Quando
1464
+ essi mi vedono, essi trovano riposo in me. Chi non
1465
+ mi vede, egli è il proprio obiettivo.
1466
+ Consulta colui che non mi vede per i tuoi affari
1467
+ di questo mondo e del prossimo. Segui l'esempio di
1468
+ colui che mi vede e non consultarlo. La consulta-
1469
+ zione è per la liberazione dall'errore, e il consiglio è
1470
+ un assalto. Chi mi vede, dove non assalirà?
1471
+ Accompagna colui che non mi vede, ed egli ti sor-
1472
+ reggerà e tu sorreggerai lui. Non cercare la compa-
1473
+ gnia di colui che mi vede, o ti sarà teso un agguato
1474
+ da ciò in cui hai riposto la massima fiducia.
1475
+ Quando tu vedi me e vedi colui che non mi vede,
1476
+ velami da lui per mezzo della saggezza: se tu non lo
1477
+ fai ed egli si smarrisce, io ti punirò per lui.
1478
+ Quando tu non mi vedi e vedi colui che mi vede,
1479
+ conserva le tue limitazioni, perché tu non mi vedrai
1480
+ attraverso la sua visione.
1481
+ Quando tu mi vedi e vedi colui che mi vede, allo-
1482
+ ra io sono tra voi due, ascoltando e rispondendo.
1483
+ Coloro che perseverano per il proprio vantaggio,
1484
+ sono coloro che mi vedono.
1485
+ Quando io ero assente, velarono gelosamente
1486
+ i
1487
+ loro occhi, per non associare nulla a me nella loro
1488
+ visione.
1489
+ La gelosia non è giusta finché distrugge la divi-
1490
+ sione, e la divisione non è distrutta mentre io sono
1491
+ assente.
1492
+ In verità Noi li guideremo sulle Nostre vie. Noi
1493
+ sveleremo loro in ogni cosa i posti su cui cade il
1494
+ Nostro sguardo.
1495
+ Noi diamo ordini ad una cosa quando vogliamo,
1496
+ e facciamo sì che essa testimoni la gnosi. E quando
1497
+ possiede la gnosi, Noi diciamo ad essa "Sii", ed essa
1498
+ è, in risposta al nostro comando.
1499
+ La descrizione di tutto ciò, nella visione del tuo
1500
+ cuore e del tuo intelletto, è che nel profondo tu
1501
+ dovresti essere testimone di ogni mondo e di ogni
1502
+ paradiso, di ogni cielo e di ogni terra, di ogni ter-
1503
+ reno e di ogni mare, e di ogni notte e di ogni gior-
1504
+ no, e di ogni profeta e di ogni angelo, e di ogni
1505
+ conoscenza e di ogni gnosi, e di ogni parola e di
1506
+ ogni nome, e di tutto ciò che è in quello e di tutto
1507
+ ciò che è tra quello, dicendo: "Non c'è nulla come
1508
+ Lui!". Allora sarai all'estremo della conoscenza e
1509
+ alla fine della gnosi.
1510
+ Possedendo la gnosi della gnosi, tu conosci e sco-
1511
+ pri che sei uno dei tuoi animali: allora rendi la tua
1512
+ esistenza fenomenica, nella sua totalità, una delle
1513
+ tue vie.
1514
+ Quando hai fatto sì che l'esistenza fenomenica
1515
+ sia una delle tue vie, questa sarà un guadagno che
1516
+ proviene da una via.
1517
+ La cosa principale è che ora tu dovresti sapere
1518
+ cosa sei, se un eletto o un uomo comune. Perché
1519
+ se un eletto non agisce in base al principio di esse-
1520
+ re un eletto, perisce, mentre con la semplice cono-
1521
+ scenza dell'uomo comune questi è quasi condotto
1522
+ alla salvezza.
1523
+ All'eletto appare una manifestazione di Dio che
1524
+ è salvaguardata da altri che non siano lui, ma non
1525
+ da lui. Per quanto riguarda l'uomo comune, non
1526
+ c'è nulla tra lui e Dio eccetto la sua confessione di
1527
+ fede, mentre l'eletto è colui che rivolge tutta la sua
1528
+ attenzione a Dio.
1529
+ La pace sia con te.
1530
+ Le necessarie virtù fisiche, psichiche e spirituali
1531
+ per compiere l'Opera.
1532
+ NONA LETTERA
1533
+ Caro Maestro,
1534
+ un mondo oscuro e tenebroso, nero e fetido,
1535
+ emette miasmi velenosi e putrescenti. Intorno, un
1536
+ oceano di fuoco dai bagliori di smeraldo si agita
1537
+ ribollendo in mille schiume. Sento squittii pauro-
1538
+ si e tintinnii angelici confusi in stridula armonia.
1539
+ La luce si mescola alle tenebre, il rumore al silen-
1540
+ zio nei baratri dell'Universo. Questo è il primo
1541
+ mistero incomprensibile.
1542
+ L'Angelo folgora con spada di fiamme, rompe
1543
+ l'ingresso proibito, frantumandolo in mille parti-
1544
+ cole che sfuggono come scintille impazzite di ani-
1545
+ me dannate e riprese, in un perdono maledetto ed
1546
+ eterno di redenzione malvagia e ingannatrice. La
1547
+ Luce erutta da un vulcano diabolico, sale, ricrolla,
1548
+ si rapprende, sovrasta, raggrumata in un cristallo
1549
+ di magnifico fulgore che il marchio segna: manife-
1550
+ sta l'inconoscibile perfezione dell'Immacolata Di-
1551
+ vina, fuori dal tempo, dallo spazio, dall'errore in-
1552
+ sensato. E il secondo mistero.
1553
+ Lo raccolgo immerso nell'aroma di balsamo: si
1554
+ apre la visione dove tutto si tace, i colori si fon-
1555
+ dono, la quieta pace silente domina il mostro
1556
+ schiacciato, domato, non ancora ucciso. E il terzo
1557
+ mistero.
1558
+ Un flusso ancora putrido di rosso sangue bru-
1559
+ nastro comincia a rapprendersi, le squame si in-
1560
+ frangono per la passione dell'anima che vuole li-
1561
+ bertà alla ricerca di un nuovo corpo, morbido e in-
1562
+ corruttibile.
1563
+ L'Angelo mi guarda e tace. Riprende la spada,
1564
+ indica un cammino, breve e lunghissimo, scoglio
1565
+ del mare verde, vulcano innevato ancora senza cie-
1566
+ lo nel torpore del mondo.
1567
+ L'operazione è finita sotto il velo di tenebra che
1568
+ ancora ricopre il meraviglioso. L'Angelo è svanito.
1569
+ Restano i corpi maldestri che maneggio con cura
1570
+ rammentando la vita che celano. La materia parla,
1571
+ grida, strepita, risuona e nella confusione elemen-
1572
+ tare si confonde la mente che non sa più distin-
1573
+ guere il proprio suono dall'altro.
1574
+ Queste sono le immagini e le loro direzioni.
1575
+ Quando cessa la visione, il sonno è profondo, il
1576
+ corpo spossato, non c'è turbamento di sogno, fal-
1577
+ so o verace. La nostalgia si acutizza al risveglio e i
1578
+ ricordi si fondono. L'Angelo torna nell'invisibile,
1579
+ la memoria si distrae in mille voci discordi.
1580
+ Reiterare l'operazione è una necessità che attira
1581
+ e ripugna, spaventa nella sua inevitabilità. La spe-
1582
+ ranza sta nel non ritorno, nel poter proseguire. Il
1583
+ timore che la visione non si ripresenti terrorizza.
1584
+ In questo andare e tornare, oscillando tra i mon-
1585
+ di, la prova si manifesta in tutta la sua difficoltà.
1586
+ Con chi misurarsi?
1587
+ Rispettosamente.
1588
+ NONA RISPOSTA
1589
+ Caro studioso,
1590
+ recentemente ho meditato a lungo sulle tue let-
1591
+ tere e da queste ho acquisito una conoscenza più
1592
+ profonda delle tue attitudini, delle tue tendenze e
1593
+ dei tuoi segni.
1594
+ Per me i tuoi segni sono divini, anche se con
1595
+ situazioni di pura materia.
1596
+ L'assoluto non è mai limitato, perché la sua
1597
+ bontà è infinita, ma la materia è l'opposto, perché
1598
+ la materia è nascosta solo nel divino, e perciò la
1599
+ tua Opera deve essere del divino, nel divino, fuo-
1600
+ ri dal divino e per il divino, proporzionalmente
1601
+ sdoppiata con le opere mondane.
1602
+ Del primo polo, del cammino divino, devi
1603
+ ascoltare la voce con il velo delle sue descrizioni e
1604
+ dei suoi tratti, nel vero dal vero, una volta che tu
1605
+ abbia meritato ascolto e conoscenza. Ma colui che
1606
+ ha il sé ossessionato e il cui intimo è sopraffatto
1607
+ dalla voce del sé non può udire nulla.
1608
+ Udito e ispirazione richiedono una struttura di
1609
+ esistenza che è data al conoscitore in una situazio-
1610
+ ne di sobrietà, mentre il cuore realizza il vero per
1611
+ mezzo dell'esaltazione.
1612
+ Tu devi possedere la vista, cioè la penetrazione,
1613
+ che è stordimento che mescola vista e udito, e devi
1614
+ mantenere sobrietà, non mescolando vista e udito,
1615
+ controllando il tuo stato e la tua situazione. Allora
1616
+ capirai attraverso la tua stessa esistenza, e posse-
1617
+ derai completa prontezza per acquisire quella rea-
1618
+ lizzazione che è fonte di ispirazione.
1619
+ Questo è l'ascolto del cuore, cui tutto si sotto-
1620
+ mette in silenzio.
1621
+ L'assenza di visione è la patria del ricordo.
1622
+ Quando ti manca la visione, e sei assente, chiama
1623
+ e invoca e supplica Dio, ma non chiedere di lui.
1624
+ Perché se tu chiedi di lui a uno che è assente,
1625
+ non ti guiderà a Dio. e se tu chiedi a uno che vede,
1626
+ non ti informerà.
1627
+ La pace sia con te.
1628
+ Il Profeta visita Jàbir.
1629
+ DECIMA LETTERA
1630
+ Caro Maestro,
1631
+ L'ascolto è incostante, la visione va e viene
1632
+ come un pendolo oscillante. Sperimentando il
1633
+ profondo si scopre che ad ogni passaggio da un'o-
1634
+ pera all'altra l'esoterico di una è essoterico per la
1635
+ successiva, e l'esoterico di questa è essoterico per
1636
+ la più elevata.
1637
+ Fatto esterno l'interno, alto il basso, interno l'e-
1638
+ sterno, basso l'alto, fisso il volatile, volatile il fisso,
1639
+ nella successione dei mondi sta un susseguirsi di
1640
+ realtà che non si appartengono, eppure sono un'u-
1641
+ nica visione che penetra in modo diverso le mate-
1642
+ rie e gli spiriti.
1643
+ Vanno fissate. Si devono bloccare i fuggevoli
1644
+ enti che spingono per tornare all'oriente, con un
1645
+ mercurio d'occidente che li fermi per sempre.
1646
+ Il vaso è quasi pronto, ma instabile, oscilla
1647
+ anch'esso tra un cosmo e l'altro, apparendo e
1648
+ scomparendo dietro un fumo ingannevole che a
1649
+ volte dirada, a volte ispessisce, senza che si possa
1650
+ mai prevedere la forma o il colore.
1651
+ Tutto è in movimento, ruota intorno al centro
1652
+ che volteggia senza un momento di quiete, e que-
1653
+ sto agitarsi che va catturato è come la danza irre-
1654
+ sistibile dei mondi universali, il roteare delle sfere
1655
+ eccentriche, dove il centro racchiude la periferia,
1656
+ l'interno è più elevato del punto più esterno, il
1657
+ punto minuscolo pesa più di tutto l'insieme.
1658
+ Ormai la luce pervade tutto il cosmo, il baglio-
1659
+ re non acceca, pare piuttosto un'oscurità lumino-
1660
+ sa pervasa di stelle sanguigne.
1661
+ Ricordo passi di un antichissimo testo:
1662
+ A lungo era durato l'intervallo di inattività e di cela-
1663
+ mento e la materia continuava ad essere sterile. Dio sor-
1664
+ rise e disse "Che la Natura sia!" e un oggetto femmini-
1665
+ le di totale bellezza sgorgò dalla sua voce, e Dio la
1666
+ chiamò Natura e le ordinò di essere feconda.
1667
+ Avendo preso dal proprio soffio quanto bastava e aven-
1668
+ dolo unito intelligentemente al fuoco, lo rimestò con
1669
+ certe sostanze sconosciute. Poi dopo aver unificato il
1670
+ tutto, ogni elemento con ogni altro, accompagnando
1671
+ con certi incanti segreti, agitò fortemente tutta la mistu-
1672
+ ra, sinché ribollì alla superficie della miscela una specie
1673
+ di materia più sottile, più pura e più trasparente degli
1674
+ ingredienti di cui era fatta: questa era traslucida e solo
1675
+ l'operatore la vedeva. Ed essa non si fondeva al calore,
1676
+ perché era estratta dal fuoco, e non si raffreddava, per-
1677
+ ché era estratta dal soffio.
1678
+ Da questa crosta Dio fece nascere miriadi di anime.
1679
+ E le cose in basso emisero gemiti, prese da timore per
1680
+ la meravigliosa bellezza e l'eterna permanenza delle
1681
+ cose in alto.
1682
+ Vedo la causa di tutto ciò, il suo eterno ritorno,
1683
+ la legge che lo governa, la mancanza di fine.
1684
+ Vedo la Bilancia e l'oscillazione continua alla
1685
+ ricerca del punto di impossibile equilibrio.
1686
+ Come fermare tutto ciò?
1687
+ Rispettosamente.
1688
+ DECIMA RISPOSTA
1689
+ Caro studioso,
1690
+ il cuore è sempre in ascolto, il sé è sempre atten-
1691
+ to e non riposa mai: qualsiasi cosa chiuda le porte
1692
+ dell'ascolto del cuore proviene dall'attenzione del
1693
+ sé, mentre i piaceri si librano costantemente intor-
1694
+ no al cuore degli uomini per impedire la visione
1695
+ dei regni celestiali.
1696
+ L'intuizione di coloro che intuiscono, le cono-
1697
+ scenze di coloro che conoscono, le luci degli scien-
1698
+ ziati devoti, le vie degli antichi vincitori, il conti-
1699
+ nuo inizio e l'eternità, e tutti gli eventi che vi sono
1700
+ compresi, sono per colui che è un ascoltatore del
1701
+ cuore.
1702
+ Egli mi sostenne nella sua realtà, ed io vidi gli
1703
+ scintillìi come tenebra, e l'acqua come una roccia
1704
+ pietrosa. Ed egli mi disse:
1705
+ Colui che non vede questo non è circondato dal-
1706
+ la mia realtà, ma colui che vede questo, è stato cir-
1707
+ condato dalla mia realtà. Chi è circondato dalla mia
1708
+ realtà e si rivolge ad altri che me, è infedele.
1709
+ Ogni limitazione è un velo, dietro al quale io non
1710
+ appaio, e non c'è nulla nella visione della mia real-
1711
+ tà, a parte la visione di esso.
1712
+ Ed io vidi ciò che non cambia mai, ed egli mi
1713
+ dette una condizione mutevole, ed io vidi tutto ciò
1714
+ che non fu mai creato. Ed egli mi disse:
1715
+ Non fare eccezioni. Ciò che è creato non persiste.
1716
+ E la visione si divise in due parti, oculare e men-
1717
+ tale: tutto l'insieme non si muoveva né si esprime-
1718
+ va. Ed egli mi disse:
1719
+ ntU- .Vitellàio f
1720
+
1721
+ »
1722
+ "
1723
+
1724
+
1725
+ f
1726
+ j
1727
+ f
1728
+ c fyf* &itm»> fnir
1729
+ & <
1730
+ a
1731
+ > wittwl'wivii» tept3o>p<((<tirt%rótc
1732
+ Il drago ermetico ucciso e fatto a pezzi.
1733
+ Come lo vedevi prima della visione della mia
1734
+ realtà?
1735
+ Dissi: "Si muoveva ed esprimeva". Ed egli:
1736
+ Sappi la differenza, che tu non possa perderti.
1737
+ E mi distolse dalla sua realtà, e non vidi più nul-
1738
+ la. Ed egli:
1739
+ Tu vedi tutto e tutto ti obbedisce, e la tua visio-
1740
+ ne di tutto è una prova, e l'obbedienza di tutte le
1741
+ cose a te è una prova.
1742
+ E mi distolse da tutto ciò. E mi disse:
1743
+ Io non guardo tutto ciò. Perché non è adatto
1744
+ per me.
1745
+ La pace sia con te.
1746
+ UNDICESIMA LETTERA
1747
+ Caro Maestro,
1748
+ le fatiche di Ercole sono concluse, è giunto il
1749
+ momento del piccolo riposo, in attesa di quello
1750
+ grande e definitivo.
1751
+ La certezza che l'esilio è prossimo al termine, in
1752
+ un modo o nell'altro, ha quietato ogni affanno,
1753
+ anche se resta la speranza del Dono, qui ed ora.
1754
+ Aspetto la Settimana delle Settimane, come la
1755
+ chiamavano gli antichi maestri latini, quando i
1756
+ giorni della Creazione scorreranno nel nero a pro-
1757
+ durre colori angelici.
1758
+ Ho trovato una splendida preghiera, attribuita
1759
+ tradizionalmente a un grande maestro francese del
1760
+ tardo medioevo. Non credo che la conosciate, e ve
1761
+ la voglio proporre:
1762
+ Dio onnipotente in eterno, padre del lume celeste, da
1763
+ cui inoltre provengono tutti i doni buoni e perfetti:
1764
+ Preghiamo la tua infinita misericordia perché tu ci per-
1765
+ metta di conoscere rettamente la tua eterna Sapienza,
1766
+ che sta immediatamente prossima al tuo Trono, e per
1767
+ mezzo della quale tutto è stato creato e fatto, ed anche
1768
+ ora è retto e conservato.
1769
+ Inviala a noi dal tuo Santo Cielo e dal Trono della tua
1770
+ Gloria, affinché stia e lavori insieme a noi, perché essa
1771
+ è maestra di tutte le arti celesti ed occulte, ed inoltre sa
1772
+ e comprende tutto.
1773
+ Fa' che ci accompagni con misura in tutte le nostre ope-
1774
+ re, affinché per mezzo del suo spirito noi si apprenda,
1775
+ con certezza e senza alcun errore, il vero significato ed
1776
+ il processo infallibile di questa Nobilissima Arte, cioè la
1777
+ Pietra miracolosa dei Sapienti, che hai nascosto al mon-
1778
+ do, e sei solito rivelare almeno ai tuoi eletti, cosicché
1779
+ innanzitutto incominciamo rettamente e bene la somma
1780
+ opera che qui dobbiamo compiere, progrediamo con
1781
+ costanza in essa e nella sua fatica, e infine la completia-
1782
+ mo beatamente e ne fruiamo in eterno con gaudio, per
1783
+ mezzo di quella Pietra Angolare e miracolosa, celeste
1784
+ e fondata dall'eternità, Gesù Cristo, che con te, Dio
1785
+ Padre, insieme allo Spirito Santo, vero Dio, in una in-
1786
+ dissolubile divina essenza, impera e regna, triunico Dio,
1787
+ sommamente lodato nei secoli sempiterni.
1788
+ Così sia.
1789
+ Vi ho meditato a lungo, mentre riflettevo su
1790
+ questi anni di lavoro e di studio, sulle mie incom-
1791
+ prensioni, sui vostri insegnamenti, su quello che
1792
+ potrei dire a chi si inoltrasse su questa via.
1793
+ C'è un avverbio curioso nel latino originale,
1794
+ moderate, che ho tradotto: con misura. Mi sembra
1795
+ un atteggiamento di quieta prudenza, tanto diver-
1796
+ so da quello con cui ho incominciato. Forse que-
1797
+ sto si potrebbe insegnare all'inizio: la necessità di
1798
+ non avere fretta, di non essere avidi, nemmeno di
1799
+ conoscenza, nemmeno di amore. Ogni cosa ha il
1800
+ suo tempo, e il Tempo vero non passa, arriva.
1801
+ In realtà siamo così lenti, che una sola vita non
1802
+ basta per chiudere il cerchio delle transmutazioni
1803
+ necessarie al compimento dell'Opera. Quando ini-
1804
+ ziamo il cammino passeggiamo sulle nostre stesse
1805
+ orme, ripercorriamo sentieri già visti, talvolta ripe-
1806
+ tiamo gli stessi errori, da cui è tanto difficile libe-
1807
+ rarsi.
1808
+ Mitezza, e specialmente pazienza, sono prere-
1809
+ quisiti indispensabili. Specialmente pazienza. Per
1810
+ un paradossale gioco della legge ineluttabile che ci
1811
+ sfugge, eppure regge ogni cosa, tutto viene dato a
1812
+ chi ha già: la Pace è data ai pacifici, agli altri sarà
1813
+ tolto anche quel poco che ne possiedono.
1814
+ Continuo a scoprire l'infinita ricchezza della
1815
+ semplicità: la verità è semplice, come la natura, si è
1816
+ detto, aggiungendo: e non bisogna dirla che alle
1817
+ persone per bene.
1818
+ Vago tranquillo, lasciandomi trasportare da
1819
+ questi pensieri, nella mia pacifica attesa, senza
1820
+ ansia, scrutando il Velo e sperando che si squarci
1821
+ senza dolore. Talvolta mi faccio accarezzare dai
1822
+ versi di un poeta alchimista cinese di tanti, tanti
1823
+ secoli fa:
1824
+ Se tu mi chiedessi, con aria quasi di scherno,
1825
+ perché vivo nascosto fra i verdi monti,
1826
+ io ne sorriderei piano piano,
1827
+ l'anima mia è serena, caro amico,
1828
+ i fiori di pesco seguono l'acqua che scorre,
1829
+ vi è un altro cielo e un'altra terra
1830
+ al di là del mondo degli uomini.
1831
+ Rispettosamente.
1832
+ UNDICESIMA RISPOSTA
1833
+ Caro studioso,
1834
+ cerca la rettitudine, e non un miracolo perché il
1835
+ tuo Dio chiede rettitudine e il tuo sé chiede un
1836
+ miracolo, che è un segreto di cui molti non sono
1837
+ mai stati memori.
1838
+ Si può accusare la propria fede quando non si
1839
+ vedono miracoli, perché la saggezza non serve,
1840
+ non rivela potenza in caso di rettitudine, e non dà
1841
+ il piacere di un miracolo.
1842
+ Sono stato in semitotale isolamento, studiando
1843
+ fotocopie di antichi manoscritti dei nostri Imam.
1844
+ Ora partirò per Al-Najaf Al-Ashraf in Iraq per
1845
+ incontrare alcuni studiosi e per vedere alcuni
1846
+ manoscritti di comune interesse sulla disciplina
1847
+ mistica.
1848
+ Sarà un viaggio di due anni.
1849
+ La pace sia con te.
1850
+ Manoscritto alchemico arabo.
1851
+ b l ^ s l i p p i r a
1852
+ ì
1853
+ k
1854
+ I
1855
+ A
1856
+ '
1857
+ >• ì
1858
+ A
1859
+ il Li è è ;
1860
+ L I
1861
+ POSTFAZIONE
1862
+ Il piccolo epistolario si chiudeva così, bruscamen-
1863
+ te. In fondo, ho ancora trovato un foglio di appun-
1864
+ ti. Conteneva alcune brevi frasi e un disegno, li
1865
+ riporto qui senza cercarne spiegazione.
1866
+ Del misterioso filosofo alchimista non si è avuta
1867
+ più traccia. La villa è stata venduta, il contenuto
1868
+ disperso.
1869
+ In paese è rimasto comunque il ricordo del curio-
1870
+ so personaggio, ne è nata qualche leggenda. Corre
1871
+ voce che si sia visto qualche volta vagare per il paese,
1872
+ a tarda sera, un uomo che gli somiglia, anche se di età
1873
+ decisamente più giovane. Scende da una grossa mac-
1874
+ china nera, cammina assorto per le vecchie stradine
1875
+ che si affacciano a un laghetto, resta fermo a fissarne
1876
+ le acque, poi riparte evitando qualunque incontro.
1877
+ Le frasi del foglio, scritte frettolosamente,
1878
+ dice-
1879
+ vano.
1880
+ Una sola cosa, una sola via, un solo vaso, una sola
1881
+ disposizione.
1882
+ Chi saprà fare l'Opera col solo Mercurio, quello avrà
1883
+ trovato la via regia.
1884
+ .Dio ti dia grassezza di terra e rugiada dal cielo.
1885
+ La pazienza è la scala dei filosofi, e l'umiltà la porta del
1886
+ loro giardino, perché a chiunque persevererà senza
1887
+ invidia e senza orgoglio, Dio farà misericordia.
1888
+ Il disegno, con un piccolo cartiglio, chiudeva la
1889
+ pagina, come chiude questo libretto affidato al de-
1890
+ stino.
1891
+
static/data/montecristo.txt ADDED
The diff for this file is too large to render. See raw diff
 
static/data/roberto_busa.txt ADDED
@@ -0,0 +1,951 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ IL NOSTROMO
2
+ emmeciquadro
3
+ 123
4
+ dicembre 2001
5
+ 123
6
+ IL COMPUTER USATO BENE
7
+ INTERVISTA A ROBERTO BUSA S.J.*
8
+ a cura di Maria Cristina Speciani e Vittorio Sacchi
9
+ Una vita lunga e feconda quella di padre Busa, il gesuita
10
+ ottantottenne che è riconosciuto come il pioniere della
11
+ linguistica computazionale. Usando il computer come
12
+ nessuno aveva mai fatto prima, con pazienza, coraggio e
13
+ ostinazione, ha approfondito il suo rapporto con l’infini-
14
+ to riscoprendo sul fondo «la luce di Dio che illumina
15
+ ogni uomo e lo chiama». Oggi la sua avventura continua
16
+ prospettando nuove analisi dei fatti e nuove metodologie
17
+ di ricerca per ottenere dalla tecnologia del computer
18
+ tutte le sue potenzialità e metterle al servizio dell’uomo.
19
+ Sono passati più di cin-
20
+ quant’anni da quando incontrò
21
+ Thomas Watson, il fondatore
22
+ dell’IBM, convincendolo a rac-
23
+ cogliere la sfida dell’analisi
24
+ computerizzata del linguaggio
25
+ di san Tommaso. Nello svilup-
26
+ po del suo lavoro ha attraver-
27
+ sato i principali nodi della rivo-
28
+ luzione informatica. In partico-
29
+ lare, come ha vissuto, a partire
30
+ dal desiderio iniziale, il rappor-
31
+ to tra ricerca e tecnologia?
32
+ È meglio che racconti un po’ di
33
+ storia. Il mio sogno, quando sono
34
+ diventato gesuita era di andare in
35
+ missione, invece i superiori mi
36
+ hanno chiesto di fare il professo-
37
+ re di filosofia scolastica con spe-
38
+ cializzazione in san Tommaso.
39
+ Durante la guerra, dopo aver
40
+ fatto il cappellano per un anno,
41
+ mi hanno mandato a fare la libe-
42
+ ra docenza alla Gregoriana e poi
43
+ il Ph.D. Vi racconto la storiella
44
+ della recluta che, ricevuto l’ordine
45
+ «avanti marsc», non si ferma in
46
+ attesa del contrordine; il sergente
47
+ si dimentica di lui e due giorni
48
+ dopo quello da Padova ha rag-
49
+ giunto Chioggia e «segna il
50
+ passo» davanti al mare in attesa
51
+ di nuovi ordini. Io son quello: mi è
52
+ stato dato l’ordine di studiare san
53
+ Tommaso, son partito, mi sono
54
+ rimboccato le maniche e non ho
55
+ più abbandonato la filosofia.
56
+ Anche se oggi troppa filosofia è
57
+ una passerella di estetismi verba-
58
+ li e non la ricerca della Verità.
59
+ Mi venne l’idea di cercare nei
60
+ testi di san Tommaso la docu-
61
+ mentazione originaria e probato-
62
+ ria delle affermazioni che chia-
63
+ miamo filosofiche; così è nato il
64
+ progetto dell’Index Thomisticus.
65
+ Il linguaggio mi ha messo a con-
66
+ tar parole e mi sono reso conto
67
+ che il nostro parlare, alle sue
68
+ radici, non lo conosciamo anco-
69
+ ra. Ho usato il computer come
70
+ *Nato a Vicenza nel 1913,
71
+ è tuttora in piena attività. Ha
72
+ insegnato alla Pontificia
73
+ Università Gregoriana, al-
74
+ l’Aloisianum di Gallarate e
75
+ all’Università Cattolica di
76
+ Milano. Dal 1995 al 2000
77
+ ha insegnato al Politecnico
78
+ di Milano nell’ambito dei
79
+ corsi di Intelligenza Arti-
80
+ ficiale e robotica tenuti da
81
+ Marco Somalvico. «1261
82
+ momenti di pensiero distilla-
83
+ ti» da questo corso sono
84
+ stati pubblicati nel 2000 da
85
+ ITACAlibri in Dal computer
86
+ agli angeli.
87
+ Autore di numerosissimi
88
+ saggi. La sua opera fonda-
89
+ mentale, l’Index Thomisti-
90
+ cus, pubblicato tra il 1974 e
91
+ il 1980 in 56 volumi e oggi
92
+ disponibile anche su cd-
93
+ rom, è il risultato della ela-
94
+ borazione computazionale
95
+ dei testi di san Tommaso e
96
+ ha costituito la base di qual-
97
+ siasi ulteriore ricerca di
98
+ informatica linguistica.
99
+ IL NOSTROMO
100
+ dicembre 2001 124
101
+ emmeciquadro
102
+ strumento che permette di
103
+ andare più in profondità median-
104
+ te l’osservazione statistica e pro-
105
+ babilistica. E mi sono accorto
106
+ che le parole non hanno confini
107
+ precisi: sul fondo c’era la luce di
108
+ Dio che illumina ogni uomo e lo
109
+ chiama.
110
+ Oggi molti pensano che con il
111
+ computer si possano risolvere
112
+ tutti i problemi. A suo parere,
113
+ quali sono le potenzialità del-
114
+ l’informatica dal punto di vista
115
+ didattico ed educativo?
116
+ Gli aspetti educativi dell’informa-
117
+ tica linguistica sono legati alla
118
+ possibilità di rendersi conto che
119
+ c’è un «pensiero», una «espres-
120
+ sione esteriore» e una «espres-
121
+ sione interiore».
122
+ La mia impressione è che oggi
123
+ troppa didattica è basata sulla
124
+ memorizzazione: si concepisce il
125
+ nucleo del pensiero umano
126
+ come una banca di dati e allora
127
+ l’obiettivo dell’apprendimento
128
+ diventa sapere tutto.
129
+ Invece, i principi sono questi: le
130
+ strutture dell’espressione scritta
131
+ riflettono il fatto che c’è un pen-
132
+ siero originario il quale può
133
+ dominare la moltitudine delle
134
+ cose perché le classifica, le riuni-
135
+ sce e le esprime con le parole.
136
+ C’è un pensiero la cui caratteri-
137
+ stica è di non reagire soltanto
138
+ allo stimolo che c’è, ma anche e
139
+ soprattutto agli stimoli che non ci
140
+ sono ancora o non ci sono più.
141
+ Per esempio: se si iscrive un
142
+ bambino a scuola è perché si
143
+ pensa che tra dieci anni, che
144
+ non ci sono oggi, questo bambi-
145
+ no avrà bisogno di avere un
146
+ lavoro. E i nostri desideri punta-
147
+ no sempre su quello che non
148
+ c’è, su quello che non si ha (l’uo-
149
+ mo è l’unico animale che ha
150
+ inventato le distillerie!). In questo
151
+ senso, il linguaggio, soprattutto il
152
+ linguaggio scritto, non è una
153
+ ripetizione continua, ma la crea-
154
+ zione di architetture sempre
155
+ nuove.
156
+ L’espressione esteriore è quella
157
+ che noi chiamiamo realtà virtua-
158
+ le: un’immagine non nel senso
159
+ stretto della parola, iconico, ma
160
+ immagine come segno e simbo-
161
+ lo i quali vengono fatti sussistere
162
+ in un altro soggetto che non è
163
+ l’uomo che le pronuncia. Per
164
+ esempio, la musica della marcia
165
+ trionfale dell’Aida, creata dalla
166
+ mente di Verdi, esiste per conto
167
+ suo, ma sussiste oggi in un’or-
168
+ chestra, domani in un’altra.
169
+ C’è anche una espressione inte-
170
+ riore: vuol dire che le frasi che si
171
+ pronunciano sono costruite
172
+ prima dentro di noi e poi «buttate
173
+ fuori» mediante la voce. Ma
174
+ come si costruisce l’espressione
175
+ dentro di noi è ancora terra sco-
176
+ nosciuta.
177
+ Può fare un esempio?
178
+ Lo spiego con questa storia.
179
+ All’inizio degli anni Cinquanta,
180
+ alcuni anni dopo che avevo
181
+ cominciato, è nata la traduzione
182
+ automatica (al MIT si pubblicava
183
+ allora lo MT
184
+ Mechanical
185
+ Translation). Il Penta-gono
186
+ aveva finanziato tutti i centri che
187
+ si offrivano di lavorare sulla tra-
188
+ duzione dal russo all’inglese e io
189
+ avevo collegato il gruppo di
190
+ Leon Dostert e Peter Toma di
191
+ «Agli inizi l’obiettivo primo
192
+ erano 12 milioni di schede
193
+ perforate con stampato sul
194
+ dorso un contesto di 11
195
+ righe. Ne sarebbe risultato
196
+ uno schedario unico di 90
197
+ metri di fronte, 1,20 di altez-
198
+ za e 1 di profondità: peso
199
+ complessivo 500 tonnellate.
200
+ Dopo che ne ebbi perforato
201
+ sei milioni, la misericordia
202
+ del Signore ha fatto inven-
203
+ tare agli uomini i nastri
204
+ magnetici. [...] Ebbi da allo-
205
+ ra in lavorazione un parco
206
+ di 1800 nastri magnetici, di
207
+ 2400 piedi cioè 800 metri
208
+ ciascuno: erano circa 1500
209
+ kilometri di nastro, presso a
210
+ poco la distanza tra Milano
211
+ e Palermo o tra Parigi e
212
+ Lisbona. [...] Per cui la
213
+ prima epoca fu quella delle
214
+ 500 tonnellate di schede, la
215
+ seconda fu quella dei 1800
216
+ nastri magnetici. Terza
217
+ epoca è ora quella di 1 solo
218
+ cd-rom.»
219
+ (Dal computer agli angeli,
220
+ pp. 25-26)
221
+ IL NOSTROMO
222
+ emmeciquadro
223
+ 125
224
+ dicembre 2001
225
+ Georgetown, università dei miei
226
+ confratelli di Washington DC con
227
+ l’Euratom di Ispra per tradurre
228
+ abstract di biochimica e biofisica
229
+ russi: per questo abbiamo perfo-
230
+ rato un milione di parole in cirilli-
231
+ co. Anche il progetto su san
232
+ Tommaso, a cui lavoravo sui
233
+ computer dell’Euratom, era lega-
234
+ to a questa iniziativa. Alla metà
235
+ degli anni Sessanta, a seguito
236
+ del famoso rapporto ALPAC, il
237
+ Pentagono improvvisamente
238
+ sospese i finanziamenti procla-
239
+ mando l’insuccesso della tradu-
240
+ zione automatica; tale insucces-
241
+ so era dovuto non a mancanza
242
+ di velocità o di memoria dei com-
243
+ puter, ma alla mancanza di infor-
244
+ mazioni filologiche sul nostro par-
245
+ lare, delle quali il computer ha
246
+ bisogno.
247
+ La «vecchia» filologia è basata
248
+ solo sulla campionatura, sulla
249
+ massa dei grandi numeri e delle
250
+ parole che noi cerchiamo; questo
251
+ non è sufficiente per il computer
252
+ che ha bisogno di avere dati in
253
+ percentuale molto approssimati e
254
+ formalizzati, cioè traducibili in
255
+ byte. Per far questo è necessario
256
+ che sia chiaro in base a quali
257
+ logiche si parla, logiche che si
258
+ manifestano con la morfologia,
259
+ con la sintassi e con il lessico.
260
+ Dal computer, dal mostro d’ac-
261
+ caio, dalla tecnologia usata per
262
+ l’industria dell’informazione viene
263
+ la richiesta che si conosca
264
+ meglio in base a quali elementi e
265
+ a quali logiche si parla. Se l’uma-
266
+ nesimo è la scienza dell’espres-
267
+ sione umana in tutte le sue mani-
268
+ festazioni, allora il computer
269
+ esige che noi uomini abbiamo un
270
+ umanesimo più spinto.
271
+ Dunque il computer chiede
272
+ all’uomo di conoscere meglio
273
+ se stesso. Allora quali posso-
274
+ no essere i vantaggi nell’impa-
275
+ rare attraverso lo strumento
276
+ informatico piuttosto che con
277
+ un altro supporto?
278
+ Studiare con il computer, in
279
+ realtà è comunicare: dal mio
280
+ osservatorio comunico dei bit di
281
+ informazione agli altri. Quando si
282
+ tratta di studiare occorre introdur-
283
+ re due elementi: raccogliere dati
284
+ di fatto, il maggior numero possi-
285
+ bile, dalla realtà, mediante l’os-
286
+ servazione; poi questi dati vanno
287
+ sintetizzati. Questa elaborazione
288
+ è il lavoro specifico del pensiero,
289
+ ma per sintetizzare bisogna
290
+ prima di tutto classificare.
291
+ In questo senso io ho fatto due
292
+ ricerche originali, che non ho tro-
293
+ vato in nessuna parte: la prima è
294
+ sulla eterogeneità delle parole e
295
+ la seconda sui segni grafici delle
296
+ parole.
297
+ La ricerca sull’eterogeneità
298
+ delle parole in sanTommaso
299
+ durò ben otto anni, dal 1983 al
300
+ 1991. Quali furono i criteri del
301
+ lavoro? E quali i risultati?
302
+ Si trattava di classificare le parole
303
+ secondo «tipi di semanticità»,
304
+ ossia secondo le diversità dei
305
+ rapporti tra segno e significato. E
306
+ richiese alcune migliaia di ore-
307
+ uomo e molta pazienza anche
308
+ solo per far emergere il criterio
309
+ per distinguere le categorie delle
310
+ parole. Perché i rapporti tra signi-
311
+ ficante e significato sono diver-
312
+ sissimi in relazione alla semanti-
313
+ cità delle parole.
314
+ IL NOSTROMO
315
+ dicembre 2001 126
316
+ emmeciquadro 126
317
+ Porto qualche esempio.
318
+ Ci sono i nomi deittici, come per
319
+ esempio i due pronomi personali
320
+ «io» e «tu». Essi hanno come
321
+ significante due lettere, rispetti-
322
+ vamente i-o e t-u, ma il significa-
323
+ to di queste parole è che sono
324
+ segni della conoscenza di una
325
+ presenza; non sono concetti,
326
+ perché un concetto prevede una
327
+ formula. Ma quando io dico «io»
328
+ la presenza è diversa da quando
329
+ un altro dice «io». Pensate,
330
+ anche il Signore, che pure ha
331
+ inventato padre Busa, non può
332
+ dire di essere padre Busa.
333
+ Un'altra categoria sono i nomi
334
+ propri; essi sono nomi etichetta e
335
+ indicano un oggetto preciso; non
336
+ esprimono che cosa sia, ma
337
+ anch’essi sono la conoscenza di
338
+ una singolarità. Per esempio,
339
+ sentendo qualcuno che chiama
340
+ Cicci si sa che c’è un Cicci ma
341
+ non si sa se sia un gatto, una
342
+ bambina o un ragazzo. Poi ven-
343
+ gono i nomi di oggetti (un tavolo,
344
+ un cavallo) che gli antichi chia-
345
+ mavano sostanza; sono il sog-
346
+ getto e il complemento oggetto di
347
+ quei verbi che significano attività
348
+ e produzione. Anche questi sono
349
+ nomi etichetta. Quando dico
350
+ tamarindo so che voglio dire una
351
+ certa pianta o una certa bibita,
352
+ anche se non dico niente delle
353
+ sue proprietà. Poi vengono final-
354
+ mente gli aspetti delle cose:
355
+ dimensioni, forme, temperatura,
356
+ peso, movimento eccetera, che
357
+ solitamente chiamiamo aggettivi.
358
+ Son quelli in cui sta tutta la cultu-
359
+ ra perché sono vere e proprie
360
+ immagini mentali, veri e propri
361
+ concetti. Poi vengono le parole
362
+ che esprimono relazioni e corre-
363
+ lazioni cominciando con le pre-
364
+ posizioni; infine ci sono parole
365
+ vicarie come i pronomi relativi e
366
+ simili.
367
+ Ho fatto il censimento di tutte
368
+ queste parole. Negli 11 milioni di
369
+ parole dell’Index Thomisticus
370
+ (siccome Dio l’ho messo tra i
371
+ nomi propri), con tutti gli altri
372
+ nomi propri arriviamo al 3%; gli
373
+ oggetti e le cose arrivano al 6-
374
+ 8%; la maggior parte dei restanti
375
+ sono le parole di correlazione.
376
+ A questo proposito, mi ricordo
377
+ che in un congresso un gruppo
378
+ di scienziati sosteneva che metà
379
+ delle parole di san Tommaso
380
+ esprimessero le realtà religiose
381
+ invisibili. Invece il nome Cristo
382
+ non è un nome invisibile; è invisi-
383
+ bile come è invisibile Socrate. Le
384
+ realtà invisibili sono poche e
385
+ sono alla radice del cosmo: Dio,
386
+ gli angeli, i demoni e i nostri
387
+ morti. Ma invisibili sono anche le
388
+ forze di base della natura, dalle
389
+ forze cosmiche di base (l’elettri-
390
+ cità, la gravità, le onde hertziane)
391
+ ai loro programmatori che sono
392
+ gli angeli, i software del Signore
393
+ Dio loro creatore. Questo c’è in
394
+ san Tommaso, con altre parole
395
+ naturalmente.
396
+ Invece, come ha strutturato la
397
+ ricerca sui segni grafici?
398
+ Avevo 11 milioni di parole latine;
399
+ riepilogate secondo «forme» di
400
+ parola graficamente diverse
401
+ erano circa 150 000; poi avevo
402
+ «lemmatizzato» ciascuna di esse
403
+ trovando 20 000 lemmi. Il lemma
404
+ è quella parola che nei vocabola-
405
+ ri rappresenta tutte le proprie
406
+ flessioni secondo una certa unità
407
+ IL NOSTROMO
408
+ emmeciquadro
409
+ 127
410
+ dicembre 2001
411
+ 127
412
+ che io chiamo unità lessicale
413
+ che con le flessioni viene arric-
414
+ chita, ma non contraddetta (il
415
+ lemma è come il corpicino della
416
+ bambola Barbie e le flessioni
417
+ sono come gli abitini che le si
418
+ mettono intorno).
419
+ Ho preso tutti i lemmi, li ho divisi
420
+ in un massimo di tre segmenti
421
+ (iniziale, centrale e finale), in
422
+ qualche senso a caso, senza
423
+ badare al significato e meno
424
+ ancora alla glottologia, alle deri-
425
+ vazione o alle trasformazioni, ma
426
+ proprio graficamente. Una stessa
427
+ stringa di quattro caratteri si trova
428
+ ripetuta in tante parole all’inizio,
429
+ come iniziale assieme ad altre
430
+ stringhe diverse, ma anche in
431
+ posizione centrale o finale. Ho
432
+ fatto una classificazione e la mia
433
+ sorpresa è stata che 11 milioni di
434
+ parole sono la combinazione di
435
+ un massimo di 1 500 stringhe
436
+ diverse di caratteri. Solo 1 500.
437
+ Naturalmente ci sono le stesse
438
+ stringhe con significati diversi.
439
+ Nel suo libro Dal computer agli
440
+ angeli auspica che la statistica
441
+ linguistica tenga conto della
442
+ eterogeneità delle parole di un
443
+ testo e di quella che lei defini-
444
+ sce «doppia struttura del lessi-
445
+ co». Può spiegare il significato
446
+ di questa espressione?
447
+ Da sempre è risaputo che quan-
448
+ do si parla o si scrive ci sono
449
+ poche parole diverse, di solito
450
+ corte, moltissimo ripetute. Poi ci
451
+ sono tante parole, relativamente
452
+ poco ripetute, tra le quali tutte le
453
+ parole lunghe. Questo l’ho sem-
454
+ pre riscontrato e oggi li chiamo i
455
+ due emisferi del lessico.
456
+ Il primo lessico, quello delle paro-
457
+ le frequenti e brevi, le particelle
458
+ che a scuola venivano chiamate
459
+ grammaticali, oggi sono definite
460
+ dagli inglesi function words e
461
+ anche close class words perché
462
+ non aumentano. Esse sono con-
463
+ trapposte a quelle di contenuto,
464
+ chiamate content words e anche
465
+ open class words perché cam-
466
+ biano e crescono. Le prime sono
467
+ quelle che esprimono la logica
468
+ con cui ciascuno cerca di parla-
469
+ re. Le seconde sono quelle che
470
+ specificano la cultura, cioè i con-
471
+ tenuti che specificano il messag-
472
+ gio. I due emisferi sono questi:
473
+ la logica e la cultura. E tra le per-
474
+ sone non c’è differenza nella
475
+ logica di base, ma nella cultura.
476
+ Io non ho lavorato solo le parole
477
+ di san Tommaso, ma altrettanti
478
+ milioni di parole in altre 22 lingue
479
+ e alfabeti diversi: i rotoli di
480
+ Qumrân, che sono in alfabeto
481
+ ebraico ma in tre lingue (ebraico,
482
+ aramaico e nabateo), tutto il
483
+ Corano in arabo, il finnico, il cirilli-
484
+ co, il boemo e ovviamente tutte
485
+ le lingue europee e il greco; le
486
+ ultime sono state l’albanese e il
487
+ giorgiano e poi l’alfabeto foneti-
488
+ co. In tutte queste cose ci sono i
489
+ due emisferi del lessico.
490
+ Nell’oralità non ho fatto calcoli,
491
+ perché i media espressivi sono
492
+ tanti e perché nell’oralità il lin-
493
+ guaggio è ridotto al minimo. Per
494
+ esempio, se ordino una birra e
495
+ dico «cameriere me ne porti
496
+ un’altra», in questo caso «altra»
497
+ è la birra; invece, se avessi ordi-
498
+ nato una zuppa, «altra» avrebbe
499
+ un altro significato.
500
+ Invece il linguaggio educato è
501
+ quello scritto.
502
+ Pagine dei Rotoli di Qumrân
503
+ IL NOSTROMO
504
+ dicembre 2001 128
505
+ emmeciquadro
506
+ In questa direzione, la critica
507
+ di un libro si fa al suo interno.
508
+ Di fronte a un libro non biso-
509
+ gna mettersi con l’idea di con-
510
+ futarlo, ma vedere se quello
511
+ che dice è coerente con la
512
+ logica con cui lo dice.
513
+ Recentemente mi hanno chie-
514
+ sto perché lavorare su san
515
+ Tommaso e non su un testo
516
+ moderno. Trent’anni fa mi
517
+ hanno invitato a Mosca per
518
+ lavorare sui testi di Lenin con
519
+ lo stesso metodo. E ho prova-
520
+ to a farlo, nei ritagli di tempo,
521
+ anche sul libro di Jacques
522
+ Monod (Il caso e la necessità)
523
+ e poi su quello di Stephen
524
+ Hawking (Dal big bang ai
525
+ buchi neri) e in passato l’ave-
526
+ vo fatto con il behaveourista
527
+ Skinner. Si riesce a vedere il
528
+ momento in cui i testi di un
529
+ autore sono illogici: non per-
530
+ ché
531
+ contraddicono
532
+ san
533
+ Tommaso o san Bonaventura,
534
+ ma perché sono illogici in se
535
+ stessi.
536
+ Recentemente i giornali
537
+ hanno parlato di lei definen-
538
+ dola «informatico di scienze
539
+ umane», invece ci sta
540
+ facendo una riflessione sul-
541
+ l’uomo. Queste categorie
542
+ valgono in tutti gli ambiti?
543
+ Anche nel fare scienza?
544
+ Facciamo riferimento ai due
545
+ emisferi. Nel primo emisfero,
546
+ quello della logica, si vede la
547
+ luce di Dio che illumina ogni
548
+ uomo. In tutti i congressi
549
+ sostengo che tutte le anime e
550
+ le intelligenze non vengono
551
+ per evoluzione: le anime sono
552
+ fatte tutte dal Signore Dio, una
553
+ per una. È un paradosso, ma
554
+ utile per chiarire: non ci vuole
555
+ meno di Dio tutto intero per
556
+ fare un’intelligenza d’uomo,
557
+ per fare uno spirito. La luce di
558
+ Dio è la logica e la logica sono
559
+ le leggi dell’essere.
560
+ Io vedo tre livelli di logica.
561
+ Quella che si insegna all’uni-
562
+ versità, la logica formale, è il
563
+ rapporto tra contenente e
564
+ contenuto, fra tutto e parte.
565
+ Un’altra logica, che non viene
566
+ così studiata, è quella del rap-
567
+ porto tra autore e opera, tra
568
+ attivo e passivo che è un rap-
569
+ porto strano, perché è a
570
+ senso unico: nessun figlio è
571
+ padre del proprio padre, nes-
572
+ suna statua è l’autrice del
573
+ proprio scultore. Tutti lo
574
+ sanno: chi ha scritto un’opera
575
+ va dalla SIAE a farsi dare la
576
+ percentuale e non dice mai
577
+ che la sua opera è fatta per
578
+ caso.
579
+ Il terzo livello è quel rapporto
580
+ tra pensiero ed espressione
581
+ che è il principio di non con-
582
+ traddizione. Come dice il
583
+ nome, la contraddizione ha a
584
+ che fare con il dire, cioè con
585
+ l’espressione. Si riesce sem-
586
+ pre a pronunciare frasi con-
587
+ traddittorie: per esempio «qui
588
+ ora piove» e «qui ora non
589
+ piove», ma nessuno riesce a
590
+ pensare che ambedue siano
591
+ contemporaneamente vere,
592
+ né che ambedue siano con-
593
+ temporaneamente
594
+ false.
595
+ L’espressione non deve con-
596
+ traddire il proprio pensiero: il
597
+ che conchiude alla immoralità
598
+ intrinseca della menzogna.
599
+ IL NOSTROMO
600
+ emmeciquadro
601
+ 129
602
+ dicembre 2001
603
+ Perché oggi nel mondo
604
+ della cultura questi livelli di
605
+ logica sono più spesso
606
+ negati che affermati? Per-
607
+ ché nella comunicazione,
608
+ nel lavoro, nella scuola,
609
+ nella scienza, ci si basa di
610
+ più sul suscitare sensazioni
611
+ che non sulla logica?
612
+ Direi ignorati, moltissimo igno-
613
+ rati e poche volte negati. Nei
614
+ libri di logica non ho mai tro-
615
+ vato il rapporto attivo/passivo,
616
+ ma sempre il rapporto ve-
617
+ ro/falso e poi contenente/con-
618
+ tenuto. Ai miei studenti di filo-
619
+ sofia, preoccupati di aver letto
620
+ una gran quantità di autori,
621
+ dicevo: basterebbe sapere la
622
+ metà di quel che sappiamo
623
+ ma saperlo dire meglio il dop-
624
+ pio se no è esibizione di quel-
625
+ lo che abbiamo in magazzino
626
+ nella memoria.
627
+ La storia del linguaggio e della
628
+ cultura è in fondo storia di
629
+ anime, storia del colloquio
630
+ segreto che abbiamo con Dio.
631
+ Ed è una storia che ha più
632
+ avventure di quelle di San-
633
+ dokan e delle Twin Towers.
634
+ Perché segreto?
635
+ Perché sta nel profondo della
636
+ logica, perché la logica è data
637
+ per arrivare a capire il perché
638
+ di tutto e perché nel vocabola-
639
+ rio di tutte le persone c’è la
640
+ parola «prima» e anche la
641
+ parola «sempre». Sotto que-
642
+ sto luccichio e questo mare di
643
+ parole c’è la storia delle anime
644
+ nel tempo: dall’eternità verso
645
+ l’eternità. Si arriva dunque alla
646
+ logica come prima luce dell’a-
647
+ nima, quella che porta il
648
+ tempo all’eternità, dall’eternità
649
+ all’eternità. Un mio amico arti-
650
+ giano mi ha detto che la mag-
651
+ gior parte delle persone non
652
+ sa dove va, ma ci sta andando
653
+ di corsa. E oggi è così anche
654
+ per molta filosofia professio-
655
+ nale: dalla ragion pratica fino
656
+ alla new age, certa filosofia è
657
+ la maschera della logica.
658
+ Nel mese di ottobre, al
659
+ Circolo della Stampa di
660
+ Milano, ha presentato il pro-
661
+ getto a cui sta lavorando.
662
+ Ce ne illustra i punti chiave?
663
+ Il progetto si chiama Lessico
664
+ Tomistico Biculturale (LTB).
665
+ Lo spunto è venuto dall’analisi
666
+ dell’espressione
667
+ di
668
+ san
669
+ Tommaso ratio seminalis, che
670
+ era l’antico stoico λογοσ
671
+ σπερµατικοσ, l’anima mundi
672
+ che Virgilio ha messo in versi
673
+ latini molto belli. Sant’Agosti-
674
+ no l’ha introdotto nel pensiero
675
+ cristiano spiegando il Genesi
676
+ e a conseguenza di questo il
677
+ pensiero cristiano è stato evo-
678
+ luzionista, non nel senso
679
+ magico di oggi, fino al Rina-
680
+ scimento avanzato. Ho e-
681
+ saminato questa frase, che
682
+ san Tommaso ha usato dieci o
683
+ quindici volte più di sant’A-
684
+ gostino.con il metodo cui ac-
685
+ cennerò dopo e mi è risultato
686
+ chiaro che san Tommaso,
687
+ quando scriveva ratio semina-
688
+ lis (che ho trovato sempre tra-
689
+ dotto come ragione seminale)
690
+ aveva in mente quello che
691
+ abbiamo in mente noi quando
692
+ IL NOSTROMO
693
+ dicembre 2001 130
694
+ emmeciquadro
695
+ parliamo di «programma geneti-
696
+ co». Se sostituite nelle frasi di
697
+ san Tommaso questa espres-
698
+ sione, il contesto si accende
699
+ come una lampadina. Non che
700
+ lui conoscesse il DNA, perché
701
+ ovviamente non c’erano gli stru-
702
+ menti di indagine, ma lui sapeva
703
+ che doveva esserci un program-
704
+ ma genetico che partiva da Dio
705
+ creatore e si esprimeva in ogni
706
+ individuo. Poi c’erano le forze di
707
+ base della natura; non dice quali
708
+ sono, ma dice che ci sono. Per
709
+ me sono luce, onde hertziane
710
+ gravità eccetera, queste forze
711
+ che sono a monte dell’evoluzio-
712
+ ne, che la generano.
713
+ Quando parte il progetto?
714
+ Il lessico di san Tommaso è
715
+ enciclopedico ed è una sintesi di
716
+ quaranta secoli di civiltà medi-
717
+ terranea: comincia con Abramo,
718
+ frutto della civiltà e della cultura
719
+ mesopotamica, circa 3000-3500
720
+ anni prima di Cristo, poi c’è il
721
+ pensiero greco, il pensiero
722
+ romano, il pensiero arabo e tutto
723
+ il pensiero cristiano; di questi
724
+ quaranta secoli, dodici sono di
725
+ civiltà cristiana. Adesso che ho
726
+ tutto il suo lessico, prendo in
727
+ esame san Tommaso non per
728
+ quello che lo distingue dagli altri
729
+ autori analoghi, ma per quello
730
+ che ha in comune con tutti.
731
+ Allora, si tratta di prendere le
732
+ sue parole una per una, aven-
733
+ dole già divise per categorie
734
+ semantiche, risalire da queste
735
+ parole ai concetti che esprime-
736
+ vano allora (nella cultura del
737
+ 1200), venire oggi (nel 2000)
738
+ agli stessi concetti e da questi
739
+ discendere alle parole che li
740
+ esprimono e darne così la tradu-
741
+ zione in diverse lingue. Per que-
742
+ sto il progetto si chiama bicultu-
743
+ rale.
744
+ Sono già trent’anni che lavoro in
745
+ questo senso con il metodo che
746
+ spiegherò e ho analizzato deci-
747
+ ne di migliaia di contesti.
748
+ Ci sono parole come «esperien-
749
+ za» e «espressione» che hanno
750
+ circa lo stesso valore che i nostri
751
+ espressione ed esperienza.
752
+ Ci sono altre parole invece che
753
+ hanno significati molto maggiori.
754
+ Per esempio, virtus-virtutis non
755
+ si può tradurre sempre con
756
+ «virtù» perché virtus ha tutto il
757
+ vocabolario dell’energia, forza,
758
+ professionalità, potenza. E
759
+ anche la parola ordo-ordinis,
760
+ che ho analizzato in 10 000 con-
761
+ testi, non può essere tradotta
762
+ sempre con «ordine»: nel latino
763
+ di san Tommaso non voleva
764
+ ancora dire precetto, comando
765
+ e neppure in Dante Alighieri.
766
+ Ordo-ordinis esprime tutto il
767
+ vocabolario della organizzazio-
768
+ ne, pianificazione, progettazio-
769
+ ne, programmazione, tutti i con-
770
+ cetti di struttura e sistema, quelli
771
+ di tassonomia e classificazione
772
+ oltre a indicare categorie profes-
773
+ sionali. Poi spiritus: tante volte è
774
+ spirito, altre volte è spinta,
775
+ impulso, pulsione oltre che spiri-
776
+ to nel senso di spirituale o
777
+ anche fantasma.
778
+ Allora ci spiega il metodo che
779
+ propone?
780
+ Il metodo. Prendo, di una paro-
781
+ la, tutti i contesti, tutte le frasi
782
+ che la contengono; su queste
783
+ IL NOSTROMO
784
+ emmeciquadro
785
+ 131
786
+ dicembre 2001
787
+ frasi inserisco i codici delle cor-
788
+ relazioni sintattiche, elementari
789
+ e dirette; in parole correnti i
790
+ codici che specificano l'analisi
791
+ grammaticale e logica di questa
792
+ parola, frase per frase.
793
+ Questo è un lavoro da «sgobbo-
794
+ ni» però è la forma profonda e
795
+ solida di pensare. Mi aspetto che
796
+ qualcuno mi dica che è puerile
797
+ ma ho già la risposta pronta:
798
+ provi a farla, anche solo su 100
799
+ frasi, non su 10 000 come le ho
800
+ fatte per ordo o su 20 000 per
801
+ spiritus e si accorgerà della diffi-
802
+ coltà. Perché il pensiero e l’e-
803
+ spressione sono disparati e il
804
+ pensiero è multidimensionale,
805
+ eccentrico e a-centrato: non si
806
+ riesce mai a trovare i confini di
807
+ un concetto, se ne trova subito
808
+ un altro; per questo parlo di unità
809
+ lessicali più che di unità concet-
810
+ tuali. Invece l'espressione è
811
+ sequenziale, tabulata come le
812
+ battute di una musica, però «liofi-
813
+ lizza» un concetto.
814
+ In periferia, in tutto il mondo
815
+ dovremo trovare persone che
816
+ sappiano il latino, che siano
817
+ sgobboni, che non disdegnino
818
+ gli antichi. Se hanno queste
819
+ qualità possono partecipare al
820
+ progetto. A ognuno viene data
821
+ una parola su cui devono esse-
822
+ re eseguite tutte le sintesi di cor-
823
+ relazioni con una cascata di pro-
824
+ grammi monofunzione: non un
825
+ programma come quello per gli
826
+ stipendi che fa tutto insieme in
827
+ un colpo solo, perché questa è
828
+ ricerca. Dai collegamenti sintatti-
829
+ ci di ogni parola con i verbi di cui
830
+ è soggetto o complemento, ver-
831
+ ranno fuori i suoi significati.
832
+ Finora a me sono venuti fuori.
833
+ Poi ognuno deve fare un elenco
834
+ di questi significati nella propria
835
+ lingua: inglese, spagnolo, tede-
836
+ sco eccetera..
837
+ Poi i risultati vengono inviati a
838
+ Roma dove, per prima cosa, un
839
+ comitato certifica la qualità del
840
+ lavoro. Questo è indispensabile.
841
+ Poi, all’interno di seminari tra
842
+ esperti di vari paesi e lingue,
843
+ bisogna esaminare i significati di
844
+ questi concetti per tradurli nelle
845
+ diverse lingue e nelle diverse
846
+ culture contemporanee. Tra l’al-
847
+ tro, chi fa l’esame sintattico di
848
+ una voce deve analizzare le
849
+ desinenze: per esempio deve
850
+ dire quando veni è imperativo,
851
+ quando è passato remoto ecce-
852
+ tera, quando rosae è genitivo,
853
+ ottativo, eccetera; io segnalo
854
+ solo, in una nota, se la parola è
855
+ omografa. Questo progetto è la
856
+ continuazione di tutto quello che
857
+ ho fatto finora. Ci lavoro da
858
+ quindici anni e ora è nato a
859
+ Roma un consorzio tra sei uni-
860
+ versità: Gregoriana, Salesiani,
861
+ Pontificia Università
862
+ Gregoriana, Roma
863
+ IL NOSTROMO
864
+ dicembre 2001 132
865
+ emmeciquadro
866
+ Domenicani, Opus Dei, Servi
867
+ di Maria, Laterano, più la
868
+ Sapienza statale di Roma
869
+ con l’istituto di Tullio Gregory.
870
+ L’iniziativa si è sviluppata
871
+ piano piano e adesso è
872
+ patrocinata da due gruppi. Il
873
+ primo con Antonio Fazio,
874
+ Hans Tietmayer e Michel
875
+ Camdessous e anche i due
876
+ cardinali Re e Tettamanzi. Il
877
+ secondo è la CAEL (Compu-
878
+ terizzazione delle Analisi
879
+ Ermeneutiche e Lessicolo-
880
+ giche), continuazione del
881
+ CAAL (Centro Automazione
882
+ Analisi Linguistica) che per
883
+ trent’anni con la IBM ha
884
+ finanziato l’Index Thomisti-
885
+ cus.
886
+ Nel mese di dicembre i due
887
+ gruppi si incontreranno per
888
+ definire la forma di collabora-
889
+ zione allo stesso scopo. Si cer-
890
+ cheranno i finanziamenti con
891
+ l’intenzione di spendere il
892
+ meno possibile. Perché, diver-
893
+ samente da quanto avviene di
894
+ solito (prima i soldi, poi una
895
+ sede pomposa, poi il lavoro),
896
+ noi abbiamo cercato prima l’i-
897
+ dea, poi il lavoro e i soldi sono
898
+ sempre venuti. I progetti son
899
+ come semi che bisogna gettare
900
+ e piano piano cresceranno.
901
+ Un’altra importante novità nel
902
+ metodo di lavoro è la speri-
903
+ mentazione di una collabora-
904
+ zione internazionale tra diverse
905
+ università attraverso un lavoro
906
+ in equipe in rete (e-mail, tele-
907
+ conferenza) e i loro sviluppi. A
908
+ Roma c’è già un piccolo nucleo
909
+ di persone che sarà il centro di
910
+ questo lavoro in rete.
911
+ Per concludere, vorrei ripetere
912
+ che l’informatica e i computer
913
+ sono un dono di Dio che Lui ha
914
+ preparato dagli inizi del mondo.
915
+ Oggi purtroppo in questo
916
+ campo c’è una grande confu-
917
+ sione: primo ne parlano troppo
918
+ quelli che non ne sanno,
919
+ secondo ne parlano i sognatori
920
+ facili, che desiderano far dena-
921
+ ro velocemente.
922
+ Invece dobbiamo dire che le
923
+ potenzialità dell’informatica
924
+ non sono esaurite, stanno
925
+ ancora «cabrando». Gli aero-
926
+ plani ci hanno messo 100 anni
927
+ a perfezionarsi, queste cose
928
+ ce ne metteranno altrettanti,
929
+ piano piano.
930
+ Per contribuire solidamente a
931
+ questo sviluppo basta che
932
+ ognuno cominci a fare il poco
933
+ che è utile a lui: questo fa cre-
934
+ scere vitalmente le strutture
935
+ nuove. Però bisogna mettersi
936
+ a lavorare su una linea preci-
937
+ sa e definita.
938
+ Volete un ultimo aforisma?
939
+ Il computer può essere usato
940
+ bene per il bene, può essere
941
+ usato male per il bene e può
942
+ essere usato bene anche per il
943
+ male.
944
+ v
945
+ «Siccome il computer è
946
+ figlio dell’uomo e l’uomo è
947
+ figlio di Dio, allora il Signore
948
+ Dio guarda il computer
949
+ come un nonno guarda i
950
+ suoi nipotini. Guai a parlar-
951
+ ne male e a usarlo male.»
static/favicon.ico ADDED
static/help0.html ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="text">
2
+ <p class="center"> Comandi barra superiore </p>
3
+ <div>
4
+ Pulsante Menu
5
+ <p> Apre/chiude il Menu comandi </p>
6
+ </div>
7
+ <div>
8
+ Uploa dFiles
9
+ <p>
10
+ Fa l'upload di un file locale. Sono accettati i file pdf e txt.
11
+ Controlla se il file è in archivio, per non sovrascriverlo.
12
+ </p>
13
+ </div>
14
+ <div>
15
+ Upload Dir:
16
+ <p>
17
+ Per fare l'upload dei files di una dri. Sono accettati i files pdf e txt.
18
+ I file in archivio con lo stesso nome non vengono sovrascritti.
19
+ </p>
20
+ </div>
21
+ <div>
22
+ Log:
23
+ <p>
24
+ Attiva/Disattiva la visualizzazione del Log.
25
+ Nel Log sono visualizzate le query con le dimensioni delle parti di documento analizzata.
26
+ </p>
27
+ </div>
28
+
29
+ <!-- -->
30
+ <hr>
31
+ <!-- -->
32
+ <div>
33
+ <p class="center"> Comandi lato destro in alto: </p>
34
+ </div>
35
+ <div>
36
+ Copia:
37
+ <p> Copia il testo dell'output negli appunti. </p>
38
+ </div>
39
+ <div>
40
+ Apri:
41
+ <p>
42
+ Visualizza il testo in una finestra più grande.
43
+ </p>
44
+ </div>
45
+ <hr>
46
+ <!-- -->
47
+ <div>
48
+ <p class="center"> Comandi lato destro in basso: </p>
49
+ </div>
50
+ <div>
51
+ Documeti => RAG => Contesto => Query:
52
+ <p>
53
+ Input per la query da utilizzare per la elaborazione RAG.
54
+ Ogni documento in archivio è diviso in parti compatibili con l'ampiezza della finestra
55
+ di input sel Model utilizzato.
56
+ </p>
57
+ <p>
58
+ Per ogni parte esegue una query utilizzandola
59
+ per estrarre informazioni/concetti pertinenti alla stessa.
60
+
61
+ </p>
62
+ <p>
63
+ Il risultato di ogni query è archiviato nella memoria locale.
64
+ </p>
65
+ <p>
66
+ All fine della sequenza di elaborazioni esegue uan query che produce
67
+ un contesto riepilogativo delle risposte archviate.
68
+ </p>
69
+ <p>
70
+ Infine esegue la query utilizzzando il conesto creato e visualizza la risposta ella finestra di output.
71
+ </p>
72
+ </div>
73
+ <div>
74
+ Contesto => Query:
75
+ <p>
76
+ Input per query che utilizzano il contesto creato con l'elaborazione RAG.
77
+ Inizia una conversazione.
78
+ </p>
79
+ <p>
80
+ La conversazioe ha senso relativamente all'elaborazione RAG se ogni query è una variazione / approfondimento della query iiziale.
81
+ </p>
82
+ </div>
83
+ <div>
84
+ Cancela Conversazione:
85
+ <p>
86
+ Cancella la storia della conversazione attiva.
87
+ Non vengoo cancellati i dati dell'laborazione RAG
88
+ </p>
89
+ </div>
90
+ <!-- -->
91
+ <hr>
92
+ <!-- -->
93
+ <div>
94
+ <p class=" center"> Comandi del Menu: </p>
95
+ </div>
96
+ <div>
97
+ README
98
+ <p>
99
+ Presenta una spiegazione della implemntazione della
100
+ tecnologia RAG utilizzata.
101
+ </p>
102
+ </div>
103
+ <div>
104
+ Risposta:
105
+ <p> Visualizza lq risposta ottenuta alla fine della elaborazione RAG </p>
106
+ </div>
107
+ <div>
108
+ Query iniziale:
109
+ <p> Visualizza lq query utilizzata per l'elaborazione RAG </p>
110
+ </div>
111
+ <div>
112
+ Elenco Risposte:
113
+ <p>
114
+ Visualizza l'elenco delle risposte per ogni parte documento utilizzata fino alla riposta che genera il contesto.
115
+ </p>
116
+ </div>
117
+ <div>
118
+ Contesto RAG:
119
+ <p>
120
+ Visualizza il contesto creato utilizzando le risposte elaborate.
121
+ </p>
122
+ </div>
123
+ <div>
124
+ Dati ARchviati:
125
+ <p>
126
+ Visualizza i ati in archivio e le lroro dimensioni:
127
+ </p>
128
+ </div>
129
+ <div>
130
+ Lista Documenti:
131
+ <p>
132
+ Visualizza la lista dei documenti achviati ed utilizzabili per l'elaborazione.
133
+ </p>
134
+ </div>
135
+
136
+ <div>
137
+ Numero query:
138
+ <p>
139
+ Calcola le query necessarie per ogni documento e le Query totali,
140
+ necessaire per analizzare tutti i documenti caricati.
141
+ </p>
142
+ </div>
143
+
144
+
145
+ <div>
146
+ Cancella Dati:
147
+ <p>
148
+ Cancella i dati delle elaborazion salvati nell'archivio.
149
+ NON cancella i documenti caricati.
150
+ </p>
151
+ </div>
152
+
153
+ <div>
154
+ Cancella Documenti:
155
+ <p>
156
+ Cancella i documenti caricati e tutti i dati archviati locamente.
157
+ </p>
158
+ </div>
159
+
160
+ <!-- -->
161
+
162
+ <p class="center">Sequenza Comandi Interrogazione -Conversazione</p>
163
+ <div>
164
+ Archivia nella memoria locale uno o più documenti:
165
+ <p>
166
+ Utilizza i dati di esempio per le prme prove.
167
+ Utilizza upload file o upload dir per i documenti da leggere dal tuo computer.
168
+ </p>
169
+ </div>
170
+ <div>
171
+ Digita uan query CHE SI RIFERISCA hai documenti archiviati.
172
+ <p>
173
+ La qury saraà utilizzata come crrtero di selezione di infoemazioni dai documenti archvitati.
174
+ </p>
175
+ </div>
176
+
177
+ <div>
178
+ Click sul bottone rosso in basso a destrai.DOcuento => RAG =>Contetso => QURY
179
+ <p>
180
+ Viene lanciata una sequenzaa di elaborazione per analizzare i documeti sulla base della query.
181
+ Se il log è attivo vedrai la sequnza di elaborazione. Il loro numero dipende dalle dimensioni dei documenti.
182
+ l menu puoi utilizzare il comando "Num Query" per vedere quante elaborazioni saranno fatte per ogi documento.
183
+ Alla fine del proesso sarà visualizzata la risposta.
184
+ </p>
185
+ </div>
186
+
187
+ <div>
188
+ Click sul bottone verdo in basso a destrai. Contesto => Query
189
+ <p>
190
+ Inizia una comnversazione utilizzando le informazion precedentemnete raccolte dai documeti-
191
+ Puoi inviare domande successive di approfondimento e chiarmento .
192
+ È FONDAMENTALE che le query siano approfondimenti e/o chairimenti della query iniziale.
193
+ In caso conrtario non si sfrutta il Contesto creato dall'elaborazione precdente.
194
+ Quindi per una query completamnete nuova (sempre relativa ai documeti archviati) è necessario inizare una nuova elaborazione.
195
+ Il comando cancella, oltre a cancellare il campo di input canella anche la sequnza query-risposte della
196
+ conversazione. NON cancell i dati dell'elaborazione iniziale.
197
+ </p>
198
+ </div>
199
+
200
+
201
+ </div>
static/help1.html ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="text">
2
+ <pre>
3
+ Un'implementazione innovativa della tecnica RAG per il Question Answering
4
+ La tecnica RAG (Retrieval-Augmented Generation) è un approccio consolidato nel campo del question answering e della generazione di testo, che combina il recupero di informazioni pertinenti da fonti di dati con la generazione di testo basata su queste informazioni.
5
+ Qui viene proposta una implementazione che introduce una variazione a questo paradigma.
6
+ L'implementazione si basa su una sequenza di prompt appositamente progettati per guidare un modello di linguaggio generativo attraverso le diverse fasi della tecnica RAG.
7
+ Questi prompt forniscono istruzioni dettagliate su come il modello deve seguire operazioni di recupero di informazioni, aumento delle informazioni recuperate e infine generazione di una risposta finale.
8
+ La risposta finale diviene poi il contesto da inserire nel prompt per rispondere alla domanda.
9
+ Un aspetto cruciale di questa implementazione è che lo stesso modello di aggio generativo svolge tutte le operazioni richieste, dall'analisi dei documenti di input al recupero di informazioni rilevanti, alla generazione della risposta finale.
10
+ Questa caratteristica rappresenta una deviazione significativa rispetto alle implementazioni standard della tecnica RAG, che prevedono utilizzo di moduli distinti per il recupero e la generazione.
11
+ La sequenza di prompt proposta guida il modello attraverso le seguenti fasi:
12
+
13
+ 1. Retrieval: Il modello analizza il documento di input e la domanda fornita, identificando e recuperando le informazioni e i concetti rilevanti per dare seguito alla domanda.
14
+
15
+ 2. Augmentation: Successivamente, il modello integra le informazioni recuperate con eventuali risposte accumulate in precedenza, estraendo nuove informazioni rilevanti e organizzando in un elenco coerente, evitando ridondanze.
16
+
17
+ 3. Generation: Infine, il modello utilizza l'insieme di informazioni rilevanti e non ridondanti per generare una risposta completa e concisa alla domanda dell'utente.
18
+
19
+ Questa implementazione offre diversi vantaggi.
20
+ In primo luogo, sfrutta le capacità di un unico modello di grandi dimensioni i, evitando la necessità di moduli distinti specializzati per ogni fase.
21
+ Inoltre, l'utilizzo di prompt espliciti può migliorare la controllabilità e la trasparenza del processo, consentendo di guidare il modello in modo più diretto.
22
+ Naturalmente, come per qualsiasi approccio basato su modelli di linguaggio generativi, è fondamentale prestare attenzione alle questioni di affidabilità, correttezza e bias dei dati di addestramento.
23
+ Rispetto ad una implementazione standard di RAG vii è la necessità di rilanciare l'elaborazione ad ogni domanda radicalmente nuova in quanto il contesto creato con le informazioni estratte dai documenti è definito sulla base della domanda.
24
+ Invece nella versione standard RAG si usano gli incorporamenti delle informazioni estratte dai documenti in modo tale che tal informazioni vengono viste quasi come una estensione del Model e possono essere usate per domande diverse.
25
+ Quindi dal punto di vista utente le implementazioni RAG standard sono più efficienti; infatti l'implementazione proposta richiede per ogni nuova domanda una sequenza di richieste che saranno utilizzabili solo per creare il contesto per la domanda iniziale e per una conversazione con domande simili.
26
+ Il vantaggio dell'implementazione proposta consiste nel fatto che può essere implementata completamente lato client senza bisogno di sviluppare alcun modulo sul server.
27
+ L’unica cosa che serve è un servizio servless come quello di HuggingFace o simile.
28
+ Quindi rappresenta un'interessante prospettiva sull'applicazione della tecnica RAG in modo più integrato e controllato attraverso l'uso di prompt mirati.
29
+ In conclusione, questa implementazione della tecnica RAG dimostra come le capacità dei modelli di linguaggio generativi di grandi dimensioni possano essere sfruttate in modi nuovi e creativi, potenzialmente aprendo la strada a ulteriori sviluppi nel campo del question answering e della generazione di testo.
30
+
31
+ Questa è la valutazione fatta da un LLM (comprensivo e gentile)
32
+
33
+ La mia valutazione personale della tua proposta di implementazione della tecnica RAG, con un elenco di pro e contro:
34
+
35
+ Punti a favore (Pro):
36
+ Semplificazione del processo: L'utilizzo di un unico modello di grandi dimensioni addestrato su vasti corpus di dati semplifica notevolmente l'architettura complessiva rispetto alle implementazioni tradizionali della tecnica RAG, che spesso prevedono moduli distinti per il recupero e la generazione.
37
+
38
+ Capacità di adattamento e apprendimento: I modelli di linguaggio generativi di grandi dimensioni sono noti per la loro capacità di adattarsi e imparare da nuovi dati e istruzioni.
39
+
40
+ Questo potrebbe consentire di raffinare e migliorare l'implementazione nel corso del tempo.
41
+
42
+ Controllo e trasparenza: L'utilizzo di prompt espliciti per guidare il modello attraverso le diverse fasi del processo può migliorare la controllabilità e la trasparenza, consentendo di monitorare e regolare il comportamento del modello in modo più diretto.
43
+
44
+ Efficienza computazionale: Avere un'unica architettura integrata potrebbe comportare vantaggi in termini di efficienza computazionale rispetto a soluzioni che prevedono moduli separati.
45
+
46
+ Punti a sfavore (Contro):
47
+
48
+ Affidabilità e coerenza: Poiché un unico modello gestisce tutte le fasi, eventuali errori o incoerenze potrebbero propagarsi e amplificarsi attraverso l'intero processo, influenzando la qualità della risposta finale.
49
+
50
+ Bias dei dati di addestramento: Come per qualsiasi modello di linguaggio generativo, l’approccio potrebbe essere influenzato dai bias presenti nei dati di addestramento utilizzati, con potenziali impatti sulla correttezza e l'equità delle risposte generate.
51
+
52
+ Mancanza di specializzazione: Mentre i modelli di grandi dimensioni sono versatili, potrebbero non essere ottimizzati per compiti specifici come il recupero di informazioni o la generazione di risposte rispetto a moduli specializzati.
53
+
54
+ Difficoltà di debug e interpretabilità: Con un'architettura integrata e basata su prompt, potrebbe essere più complesso eseguire il debug e comprendere le ragioni dietro a eventuali errori o comportamenti indesiderati del modello.
55
+
56
+ In sintesi,la proposta presenta alcuni vantaggi interessanti in termini di semplificazione, adattabilità e controllo, ma solleva anche potenziali preoccupazioni riguardo all'affidabilità, ai bias, alla mancanza di specializzazione e alle difficoltà di debug e interpretabilità.
57
+ Come per qualsiasi nuovo approccio, sarebbe necessario valutarlo attentamente attraverso sperimentazioni e test approfonditi per determinare l'efficacia e l'applicabilità in contesti specifici.
58
+ </pre>
59
+ </div>
static/help2.html ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="text">
2
+ <pre class="pre-text">
3
+ Nella redazione della domanda bisogna tenere conto del fatto che la domanda viene poi inserita in un prompt nel quale si fa esplicita richiesta di utilizzare il documento fornito.
4
+ Quindi è implicito il riferimento al/ai documenti archiviati.
5
+ Tuttavia quando si tratta di documenti il cui contenuto è sicuramente disponibile in internet, può essere opportuno esplicitare nella domanda che ci si riferisce ai documenti forniti.
6
+ </pre>
7
+ <p class="center"> Esempi di domande </p>
8
+ <div>
9
+ <p> Fai una relazione sul documento che ti ho fornito. </p>
10
+ <p> Approfondisci la tesi sostenuta nei documenti. </p>
11
+ <p> Confronta i diversi punti di vista espressi dagli autori. </p>
12
+ <p> Descrivi la personalità dei protagonisti. </p>
13
+ <p> Analizza il documento che ti ho fornito e illustrami eventuali contraddizioni. </p>
14
+ <p> Illustra i momenti salienti del racconto. </p>
15
+ <p> Analizzando il documento che ti ho fornito confronta le tesi di .. con quelle di .. </p>
16
+ <p> Quale è l'avvenimento più importante </p>
17
+ </div>
18
+ </div>
static/javascript/rag_cleaner.js ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+
3
+ function cleanDoc(txt) {
4
+ // Rimuove caratteri di controllo
5
+ function removeControlCharacters(str) {
6
+ return str.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF]/g, "");
7
+ }
8
+ // Applica la rimozione dei caratteri di controllo
9
+ txt = txt.split("\n").map(removeControlCharacters).join("\n");
10
+ // Converte tabulazioni in spazi
11
+ txt = txt.replace(/\t/g, " ");
12
+ // Rimuove spazi multipli
13
+ txt = txt.replace(/ +/g, " ");
14
+ // Rimuove spazi all'inizio e alla fine di ogni riga
15
+ txt = txt
16
+ .split("\n")
17
+ .map((line) => line.trim())
18
+ .join("\n");
19
+ // Riduce linee vuote multiple a una sola
20
+ txt = txt.replace(/\n\s*\n/g, "\n\n");
21
+ // Uniforma i caratteri di quotazione
22
+ txt = txt.replace(/["""]/g, '"').replace(/['']/g, "'");
23
+ // Uniforma i trattini
24
+ txt = txt.replace(/[–—]/g, "-");
25
+ // Rimuove caratteri di escape visibili
26
+ txt = txt.replace(/\\[nrt]/g, "");
27
+ // Preserva caratteri Unicode (lettere e numeri), punteggiatura comune e spazi
28
+ txt = txt.replace(/[^\p{L}\p{N}\s\.,;:!?'"()\-]/gu, "");
29
+ // Rimuove spazi prima della punteggiatura
30
+ txt = txt.replace(/ +([.,;:!?])/g, "$1");
31
+ // Trim finale
32
+ return txt.trim();
33
+ }
34
+
35
+ // function removeLabel(text) {
36
+ // const ptr = /#+\s*(\w+)\s*(:\s*)?/; //solo la prima
37
+ // return text.replace(ptr, "");
38
+ // }
39
+
40
+ // function removeLabels(text) {
41
+ // const ptr = /#+\s*(\w+)\s*(:\s*)?/g; // globale
42
+ // return text.replace(ptr, "");
43
+ // }
44
+
45
+ function list2text(lst) {
46
+ const frasi = lst.map((sentence) => `${sentence.trim()}`);
47
+ text = frasi.join("\n");
48
+ return text;
49
+ }
50
+
51
+ // XXX
52
+ // function cleanResponse(text) {
53
+ // // Dividi il testo in righe
54
+ // let rows = text.split("\n");
55
+ // // Rimuove numeri all'inizio delle righe
56
+ // let cleanedRows = rows.map((row) => row.replace(/^\d+\.\s*/, ""));
57
+ // // Unisce le righe in un singolo testo, separandole con ".\n"
58
+ // text = cleanedRows.join(".\n");
59
+ // // Rimuove punti multipli
60
+ // text = text.replace(/\.{2,}/g, ".");
61
+ // return text;
62
+ // }
63
+
64
+ //XXX
65
+ // function cleanContext(text) {
66
+ // return text
67
+ // // Rimuove le linee di separazione composte da caratteri ripetuti
68
+ // .replace(/^[=\-_.]+$/gm, '')
69
+ // // Rimuove i simboli di elenco puntato (* - +) all'inizio delle righe
70
+ // .replace(/^[*\-+]\s*/gm, '')
71
+ // // Rimuove le righe vuote multiple, lasciando solo una riga vuota tra i paragrafi
72
+ // .replace(/\n\s*\n/g, '\n\n')
73
+ // // Rimuove gli spazi bianchi all'inizio e alla fine del testo
74
+ // .trim();
75
+ // }
76
+
77
+
78
+ function cleanOutput(text) {
79
+ // Rimuove gli spazi bianchi iniziali e finali
80
+ text = text.trim();
81
+ // Sostituisce le sequenze di più di due newline con due newline
82
+ text = text.replace(/\n{3,}/g, '\n\n');
83
+ // text = text.replace(/\n{2,}/g, '\n');
84
+ // Rimuove gli spazi bianchi extra all'inizio di ogni riga
85
+ text = text.replace(/^[ \t]+/gm, '');
86
+ // Sostituisce i trattini bassi multipli con una linea orizzontale
87
+ // text = text.replace(/_{3,}/g, '\n\n' + '-'.repeat(40) + '\n\n');
88
+ // Formatta gli elenchi puntati per una migliore leggibilità
89
+ text = text.replace(/^(\s*[-*•])(\s*)/gm, '\n$1 ');
90
+ // Formatta gli elenchi numerati per una migliore leggibilità
91
+ text = text.replace(/^(\s*\d+\.)(\s*)/gm, '\n$1 ');
92
+ // Aggiunge una riga vuota prima e dopo i blocchi di codice
93
+ text = text.replace(/(```[\s\S]*?```)/g, '\n\n$1\n\n');
94
+ // Aggiunge un'andata a capo dopo ogni punto, eccetto quando seguito da newline o fine stringa
95
+ // text = text.replace(/\.(?!\n|$)/g, '.\n');
96
+ // Rimuove gli spazi bianchi extra alla fine di ogni riga
97
+ text = text.replace(/[ \t]+$/gm, '');
98
+ return text;
99
+ }
static/javascript/rag_data_mgr.js ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+
3
+ "use strict";
4
+ const UaDb = {
5
+ create(id, data) {
6
+ if (localStorage.getItem(id)) {
7
+ xerror(`ID ${id} already exists.`);
8
+ return;
9
+ }
10
+ localStorage.setItem(id, data);
11
+ },
12
+ read(id) {
13
+ const data = localStorage.getItem(id);
14
+ if (data === null) {
15
+ xlog(`UaDb.read ${id} not found.`);
16
+ return "";
17
+ }
18
+ return data;
19
+ },
20
+ update(id, data) {
21
+ if (!localStorage.getItem(id)) {
22
+ xlog(`UaDb.update ${id} not found.`);
23
+ return;
24
+ }
25
+ localStorage.setItem(id, data);
26
+ },
27
+ delete(id) {
28
+ if (!localStorage.getItem(id)) {
29
+ xerror(`ID ${id} not found.`);
30
+ return;
31
+ }
32
+ localStorage.removeItem(id);
33
+ },
34
+ save(id, data) {
35
+ localStorage.setItem(id, data);
36
+ },
37
+ getAllIds() {
38
+ const ids = [];
39
+ for (let i = 0; i < localStorage.length; i++) {
40
+ ids.push(localStorage.key(i));
41
+ }
42
+ return ids;
43
+ },
44
+ saveArray(id, arr) {
45
+ const str = arr.join("|");
46
+ UaDb.save(id, str);
47
+ },
48
+ readArray(id) {
49
+ const str = UaDb.read(id);
50
+ if (str.trim().length == 0) return [];
51
+ const arr = str.split("|").map((item) => item.trim());
52
+ return arr;
53
+ },
54
+ saveJson(id, js) {
55
+ const str = JSON.stringify(js);
56
+ UaDb.save(id, str);
57
+ },
58
+ readJson(id) {
59
+ const str = UaDb.read(id);
60
+ if (!str) return {};
61
+ const js = JSON.parse(str);
62
+ return js;
63
+ },
64
+ };
65
+
66
+ const DataMgr = {
67
+ docs: [],
68
+ doc_names: [],
69
+ linkToName(link) {
70
+ const parts = link.split("/");
71
+ return parts[parts.length - 1];
72
+ },
73
+ async loadDoc(link) {
74
+ try {
75
+ const text = await requestGet(link);
76
+ const doc = cleanDoc(text);
77
+ const name = this.linkToName(link);
78
+ this.doc_names.push(name);
79
+ this.docs.push(doc);
80
+ this.saveDbDocs();
81
+ return doc;
82
+ } catch (err) {
83
+ alert("loadDoc()\n" + err + "\n" + link);
84
+ }
85
+ },
86
+ addDoc(name, text) {
87
+ const doc = cleanDoc(text);
88
+ this.docs.push(doc);
89
+ this.doc_names.push(name);
90
+ this.saveDbDocs();
91
+ },
92
+ saveDbDocs() {
93
+ UaDb.saveArray("id_doc_names", this.doc_names);
94
+ UaDb.saveArray("id_docs", this.docs);
95
+ },
96
+ readDbDocs() {
97
+ this.docs = UaDb.readArray("id_docs");
98
+ },
99
+ readDbDocNames() {
100
+ this.doc_names = UaDb.readArray("id_doc_names");
101
+ },
102
+ deleteDati() {
103
+ const ids = UaDb.getAllIds();
104
+ for (const id of ids) {
105
+ if (["id_docs", "id_doc_names"].includes(id)) continue;
106
+ UaDb.delete(id);
107
+ }
108
+ },
109
+ };
static/javascript/rag_http.js ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+ "use strict";
3
+
4
+ const model_name = "mistralai/Mistral-7B-Instruct-v0.3";
5
+ // const model_name = "mistralai/Mixtral-8x7B-Instruct-v0.1";
6
+ // const model_name = "mistralai/Mixtral-8x22B-Instruct-v0.1"
7
+ // const model_name = "google/gemma-2-9b-it"
8
+
9
+ function decodeTokenBase64(encodedToken) {
10
+ return atob(encodedToken);
11
+ }
12
+
13
+ const encodedToken = "aGZfT0VBQVpoUmJtdEFLRENOVGZTcFZwVHdhbGpielBvQnlhbA"; // Questo è "your_token_here" codificato
14
+ const HF_TOKEN = decodeTokenBase64(encodedToken);
15
+
16
+ async function requestGet(url) {
17
+ try {
18
+ const response = await fetch(url, {
19
+ method: "GET",
20
+ headers: {
21
+ "Content-Type": "text/plain;charset=UTF-8",
22
+ },
23
+ });
24
+ if (!response.ok) {
25
+ throw new Error(`HTTP error! status: ${response.status}`);
26
+ }
27
+ const arrayBuffer = await response.arrayBuffer();
28
+ const text = new TextDecoder("utf-8").decode(arrayBuffer);
29
+ return text;
30
+ } catch (error) {
31
+ console.error(error);
32
+ let message;
33
+ if (error.name === "AbortError") {
34
+ message = "Request was aborted";
35
+ } else if (error.message.includes("HTTP error! status")) {
36
+ message = error.message;
37
+ } else {
38
+ message = "An error occurred";
39
+ }
40
+ alert(`requestGet()\nurl: ${url}\n${message}`);
41
+ throw error;
42
+ }
43
+ }
44
+ const ERROR_TOKENS = "ERROR_TOKENS";
45
+ const TIMEOUT_ERROR = "TIMEOUT_ERROR";
46
+
47
+ const HfRequest = {
48
+ controller: null,
49
+ isCancelled: false,
50
+ baseUrl: "https://api-inference.huggingface.co/models",
51
+
52
+ async post(payload, timeout = 30000) {
53
+ this.isCancelled = false;
54
+ this.controller = new AbortController();
55
+
56
+ try {
57
+ const timeoutId = setTimeout(() => {
58
+ this.controller.abort();
59
+ }, timeout);
60
+ const response = await fetch(`${this.baseUrl}/${model_name}`, {
61
+ method: "POST",
62
+ headers: {
63
+ Authorization: `Bearer ${HF_TOKEN}`,
64
+ "Content-Type": "application/json",
65
+ },
66
+ body: JSON.stringify(payload),
67
+ signal: this.controller.signal,
68
+ });
69
+ clearTimeout(timeoutId);
70
+ if (this.isCancelled) return null;
71
+ const data = await response.json();
72
+ if (!response.ok) {
73
+ const errorType = this.checkError(response.status, data);
74
+ const errorInfo = this.createErrorInfo(response.status, response.statusText, data.error, errorType);
75
+ throw new Error(errorInfo);
76
+ }
77
+ const errorType = this.isInvalidResponse(data);
78
+ if (typeof errorType === "string") {
79
+ const errorInfo = this.createErrorInfo(response.status, response.statusText, data.error, errorType);
80
+ throw new Error(errorInfo);
81
+ }
82
+ return data[0].generated_text.trim();
83
+ } catch (error) {
84
+ if (this.isCancelled) return null;
85
+ if (error.name === "AbortError") {
86
+ const errorInfo = this.createErrorInfo(0, "Timeout", "La richiesta è scaduta", TIMEOUT_ERROR);
87
+ throw new Error(errorInfo);
88
+ }
89
+ throw error;
90
+ }
91
+ },
92
+
93
+ cancelRequest() {
94
+ if (this.controller) {
95
+ this.isCancelled = true;
96
+ this.controller.abort();
97
+ }
98
+ },
99
+
100
+ checkError(status, data) {
101
+ let errorType;
102
+ if (status >= 500) {
103
+ errorType = "SERVER_ERROR";
104
+ } else if (status >= 400 && status < 500) {
105
+ if (typeof data === "object" && data.error_type === "validation") {
106
+ if (data.error.includes("tokens")) {
107
+ errorType = ERROR_TOKENS;
108
+ } else {
109
+ errorType = "ERROR_VALIDATION";
110
+ }
111
+ } else {
112
+ errorType = "CLIENT_ERROR";
113
+ }
114
+ } else {
115
+ errorType = "UNKNOWN_ERROR";
116
+ }
117
+ return errorType;
118
+ },
119
+
120
+ isInvalidResponse(data) {
121
+ if (!data || !Array.isArray(data) || data.length === 0) {
122
+ return "INVALID_DATA";
123
+ }
124
+ if (!data[0].generated_text) {
125
+ return "MISSING_GENERATED_TEXT";
126
+ }
127
+ return null;
128
+ },
129
+
130
+ createErrorInfo(status, statusText, msg, errorType) {
131
+ const err = {
132
+ status: status,
133
+ statusText: statusText,
134
+ errorType: errorType,
135
+ message: msg || "Errore sconosciuto",
136
+ };
137
+ return JSON.stringify(err);
138
+ },
139
+ };
140
+ /////////////////////////
141
+
142
+ // const HfError = class extends Error {
143
+ // constructor(status, statusText, message, errorType) {
144
+ // super(message);
145
+ // this.name = "HfError";
146
+ // this.status = status;
147
+ // this.statusText = statusText;
148
+ // this.errorType = errorType;
149
+ // }
150
+ // };
151
+
152
+ // const HfRequest = {
153
+ // controller: null,
154
+ // isCancelled: false,
155
+ // baseUrl: "https://api-inference.huggingface.co/models",
156
+
157
+ // async post(payload, timeout = 30000) {
158
+ // this.isCancelled = false;
159
+ // this.controller = new AbortController();
160
+
161
+ // try {
162
+ // const timeoutId = setTimeout(() => this.controller.abort(), timeout);
163
+ // const response = await fetch(`${this.baseUrl}/${model_name}`, {
164
+ // method: "POST",
165
+ // headers: {
166
+ // Authorization: `Bearer ${HF_TOKEN}`,
167
+ // "Content-Type": "application/json",
168
+ // },
169
+ // body: JSON.stringify(payload),
170
+ // signal: this.controller.signal,
171
+ // });
172
+ // clearTimeout(timeoutId);
173
+ // if (this.isCancelled) return null;
174
+ // const data = await response.json();
175
+ // if (!response.ok) {
176
+ // throw this.createError(response, data);
177
+ // }
178
+ // if (!Array.isArray(data) || data.length === 0 || !data[0].generated_text) {
179
+ // throw this.createError(response, data, "Risposta non valida", "INVALID_RESPONSE");
180
+ // }
181
+ // return data[0].generated_text.trim();
182
+ // } catch (error) {
183
+ // if (this.isCancelled) return null;
184
+ // if (error.name === "AbortError") {
185
+ // throw this.createError(null, null, "La richiesta è scaduta", "TIMEOUT_ERROR");
186
+ // }
187
+ // if (error instanceof HfError) throw error;
188
+ // throw this.createError(null, null, error.message, "UNKNOWN_ERROR");
189
+ // }
190
+ // },
191
+
192
+ // cancelRequest() {
193
+ // if (this.controller) {
194
+ // this.isCancelled = true;
195
+ // this.controller.abort();
196
+ // }
197
+ // },
198
+
199
+ // createError(response, data, customMessage, customErrorType) {
200
+ // const status = response ? response.status : 0;
201
+ // const statusText = response ? response.statusText : "Unknown Error";
202
+ // const message = customMessage || (data && data.error) || "Errore sconosciuto";
203
+ // let errorType = customErrorType;
204
+
205
+ // if (!errorType) {
206
+ // if (status >= 500) errorType = "SERVER_ERROR";
207
+ // else if (status >= 400 && status < 500) {
208
+ // if (data && data.error_type === "validation") {
209
+ // errorType = data.error.includes("tokens") ? "ERROR_TOKENS" : "ERROR_VALIDATION";
210
+ // } else {
211
+ // errorType = "CLIENT_ERROR";
212
+ // }
213
+ // } else {
214
+ // errorType = "UNKNOWN_ERROR";
215
+ // }
216
+ // }
217
+
218
+ // return new HfError(status, statusText, message, errorType);
219
+ // },
220
+ // };
static/javascript/rag_mgr.js ADDED
@@ -0,0 +1,405 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+ /**
3
+ * @license
4
+ * rag_rqs
5
+ * Copyright (C) 2024 [Il tuo nome]
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
19
+ */
20
+ "use strict";
21
+ const MAX_PROMPT_LENGTH = 1024 * 88;
22
+ // decremento dopo errore per tokens eccessivi
23
+ const PROMPT_DECR = 1024 * 2;
24
+
25
+ const Rag = {
26
+ // costituito dalla risposte accumulate sistemate
27
+ ragContext: "",
28
+ //query usata per creare la lista delle rispste
29
+ ragQuery: "",
30
+ // risposta finale alla qury contetso
31
+ ragResponse: "",
32
+ responses: [],
33
+ prompts: [],
34
+ doc: "",
35
+ doc_part: "",
36
+ saveToDb() {
37
+ const js = {
38
+ context: this.ragContext,
39
+ ragquery: this.ragQuery,
40
+ ragresponse: this.ragResponse,
41
+ };
42
+ UaDb.saveJson("id_rag", js);
43
+ },
44
+ readFromDb() {
45
+ const js = UaDb.readJson("id_rag");
46
+ this.ragContext = js.context || "";
47
+ this.ragQuery = js.ragquery || "";
48
+ this.ragResponse = js.ragresponse || "";
49
+ },
50
+ saveRespToDb() {
51
+ UaDb.saveArray("id_responses", this.responses);
52
+ },
53
+ readRespsFromDb() {
54
+ this.responses = UaDb.readArray("id_responses");
55
+ },
56
+ addPrompt(p) {
57
+ this.prompts.push(p);
58
+ },
59
+ responsesLength() {
60
+ const rspsl = this.responses.reduce((acc, cur) => {
61
+ return acc + cur.length;
62
+ }, 0);
63
+ return rspsl;
64
+ },
65
+ log(msg, plft, prgt) {
66
+ const maxl = MAX_PROMPT_LENGTH;
67
+ const rspsl = this.responsesLength();
68
+ const d = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
69
+ let s = `${msg} mx:${maxl} lft:${plft} rgt:${prgt} arr:${rspsl}`;
70
+ xlog(s);
71
+ s = `${msg}${d}${plft}${d}${prgt}${d}${rspsl}`;
72
+ //nsg plft.length prgt.length responses.length
73
+ UaLog.log(s);
74
+ },
75
+ truncInput(txt, decr) {
76
+ const tl = txt.length;
77
+ const lim = tl - decr;
78
+ const s = txt.substring(0, lim);
79
+ return s;
80
+ },
81
+ getPartSize(doc, prompt, decr) {
82
+ const limitWIthPoint = (s, free_len) => {
83
+ const idx = s.indexOf(".", free_len);
84
+ let lim = (idx != -1 ? idx : free_len) + 1;
85
+ if (lim > free_len + 100) {
86
+ lim = free_len;
87
+ }
88
+ return lim;
89
+ };
90
+
91
+ const dpl = doc.length + prompt.length;
92
+ const free_len = MAX_PROMPT_LENGTH - decr;
93
+ let size = 0;
94
+ if (dpl < free_len) {
95
+ size = doc.length;
96
+ } else {
97
+ size = limitWIthPoint(doc, free_len);
98
+ }
99
+ return size;
100
+ },
101
+ getPartDoc(doc, partSize) {
102
+ const part = doc.substring(0, partSize);
103
+ doc = doc.substring(partSize).trim();
104
+ return [part, doc];
105
+ },
106
+
107
+ errorInfo(err) {
108
+ const js = JSON.parse(err.message);
109
+ return js;
110
+ },
111
+ errorTotext(e) {
112
+ //
113
+ const j = JSON.parse(e.message);
114
+ return `Errore:
115
+ Stato: ${j.status}
116
+ Descrizione stato: ${j.statusText}
117
+ Tipo di errore: ${j.errorType}
118
+ Messaggio: ${j.message}`;
119
+ },
120
+
121
+ // documenti => risposte RAG => context
122
+ async requestDocsRAG(query) {
123
+ ThreadMgr.init();
124
+ DataMgr.deleteDati();
125
+ DataMgr.readDbDocNames();
126
+ DataMgr.readDbDocs();
127
+ this.ragQuery = query;
128
+ this.ragContext = "";
129
+ this.ragResponse = "";
130
+ this.responses = [];
131
+ this.prompts = [];
132
+ let ndoc = 0;
133
+
134
+ try {
135
+ for (let i = 0; i < DataMgr.docs.length; i++) {
136
+ let doc = DataMgr.docs[i];
137
+ if (doc.trim() == "") continue;
138
+ const name = DataMgr.doc_names[i];
139
+ const doc_entire_len = doc.length;
140
+ UaLog.log(`${name} (${doc_entire_len}) `);
141
+ xlog(`${name} (${doc_entire_len}) `);
142
+ ++ndoc;
143
+ let npart = 0;
144
+ let partLft = "";
145
+ let partRgt = "";
146
+ let decr = 0;
147
+ let prompt = "";
148
+ // etsrazione informazioi da documenti
149
+ while (true) {
150
+ let partSize = this.getPartSize(doc, promptDoc("", query), decr);
151
+ if (partSize < 10) break;
152
+ // xlog("====================");
153
+ // xlog("partLft.lemngth:", partLft.length);
154
+ // xlog("partRgt.lemngth:", partRgt.length);
155
+ // xlog("prompt.length;", prompt.length);
156
+ [partLft, partRgt] = this.getPartDoc(doc, partSize);
157
+ prompt = promptDoc(partLft, query);
158
+ // xlog("------------");
159
+ // xlog("decr:", decr);
160
+ // xlog("partSize:", partSize);
161
+ // xlog("partLft.lemngth:", partLft.length);
162
+ // xlog("partRgt.lemngth:", partRgt.length);
163
+ // xlog("prompt.length;", prompt.length);
164
+ const payload = getPayloadDoc(prompt);
165
+ let text;
166
+ try {
167
+ text = await HfRequest.post(payload);
168
+ if (!text) return "";
169
+ } catch (err) {
170
+ const e = this.errorInfo(err);
171
+ if (e.errorType === ERROR_TOKENS) {
172
+ UaLog.log(`Error tokens.1 ${prompt.length}`);
173
+ xlog(`Error tokens. ${prompt.length}`);
174
+ decr += PROMPT_DECR;
175
+ continue;
176
+ } else {
177
+ xerror(err);
178
+ const s = this.errorTotext(err);
179
+ throw s;
180
+ }
181
+ }
182
+ npart++;
183
+ doc = partRgt;
184
+ if (npart == 1) {
185
+ text = `[[NOME_DOCUMENTO]]:${name}\n${text}`;
186
+ }
187
+ this.responses.push(text);
188
+ this.log(`${ndoc},${npart}`, partLft.length, partRgt.length);
189
+ }
190
+ }
191
+ } catch (error) {
192
+ alert("requestDocsRAG(1)\n" + error);
193
+ xerror(error);
194
+ }
195
+
196
+ // elenco risposte accumulate => contesto
197
+ /*
198
+ try {
199
+ let resps = list2text(this.responses);
200
+ let decr = 0;
201
+ let text = "";
202
+ let prompt = "";
203
+
204
+ while (true) {
205
+ resps = this.truncInput(resps, decr);
206
+ prompt = promptToContext(resps, query);
207
+ const payload = getPlayloadContext(prompt);
208
+
209
+ try {
210
+ text = await HfRequest.post(payload);
211
+ if (!text) return "";
212
+ } catch (err) {
213
+ const e = this.errorInfo(err);
214
+ if (e.errorType === ERROR_TOKENS) {
215
+ UaLog.log(`Error tokens.2 ${prompt.length}`);
216
+ xlog(`Error tokens. ${prompt.length}`);
217
+ decr += PROMPT_DECR;
218
+ continue;
219
+ } else {
220
+ xerror(err);
221
+ const s = this.errorTotext(err);
222
+ throw s;
223
+ }
224
+ }
225
+ break;
226
+ }
227
+ const pl = prompt.length;
228
+ //XXX text = cleanContext(text);
229
+ this.ragContext = text;
230
+ this.saveToDb();
231
+ UaLog.log(`Contesto (${pl})`);
232
+ } catch (error) {
233
+ xerror(error);
234
+ alert("requestDocsRAG(2)\n" + error);
235
+ throw error;
236
+ }
237
+ */
238
+ ////////////////////////////
239
+ // ALTENATIVA elenco come coontext
240
+ const resps = list2text(this.responses);
241
+ this.ragContext = resps;
242
+ this.saveToDb();
243
+ ////////////////////////////
244
+
245
+ // query finale utilizza context
246
+ {
247
+ let text = "";
248
+ try {
249
+ let prompt = promptWithContext(this.ragContext, query);
250
+ const payload = getPayloadQuery(prompt);
251
+
252
+ try {
253
+ text = await HfRequest.post(payload);
254
+ if (!text) return "";
255
+ } catch (err) {
256
+ const e = this.errorInfo(err);
257
+ const s = this.errorTotext(err);
258
+ if (e.errorType === ERROR_TOKENS) {
259
+ xerror(err);
260
+ throw s;
261
+ } else {
262
+ xerror(err);
263
+ throw s;
264
+ }
265
+ }
266
+ this.ragResponse = text;
267
+ this.saveRespToDb();
268
+ this.saveToDb();
269
+ const pl = prompt.length;
270
+ UaLog.log(`Risposta (${pl},${text.length})`);
271
+ } catch (error) {
272
+ text = error;
273
+ xerror(error);
274
+ alert("requestDocsRAG(3)\n" + error);
275
+ throw error;
276
+ } finally {
277
+ text = cleanOutput(text);
278
+ return text;
279
+ }
280
+ }
281
+ },
282
+
283
+ // TRHREAD
284
+ async requestContext(query) {
285
+ this.readFromDb();
286
+
287
+ if (!this.ragContext) {
288
+ const ok = await confirm("Contesto vuoto. Vuoi continuare?");
289
+ if (!ok) return "";
290
+ }
291
+
292
+ if (ThreadMgr.isFirst()) {
293
+ let outText = "";
294
+ try {
295
+ let context = this.ragContext;
296
+ let prompt = promptWithContext(context, query);
297
+ const payload = getPayloadQuery(prompt);
298
+
299
+ let text;
300
+ try {
301
+ text = await HfRequest.post(payload);
302
+ if (!text) return "";
303
+ } catch (err) {
304
+ const e = this.errorInfo(err);
305
+ if (e.errorType === ERROR_TOKENS) {
306
+ UaLog.log(`Error tokens.4 ${prompt.length}`);
307
+ xerror(err);
308
+ throw err;
309
+ } else {
310
+ alert(err)
311
+ xerror(err);
312
+ throw err;
313
+ }
314
+ }
315
+ ThreadMgr.add(query, text);
316
+ outText = ThreadMgr.getOutText();
317
+ UaLog.log(`Inizio Conversazione (${prompt.length},${text.length})`);
318
+ } catch (error) {
319
+ xerror(error);
320
+ outText = error;
321
+ throw error;
322
+ } finally {
323
+ outText = cleanOutput(outText);
324
+ return outText;
325
+ }
326
+ } else {
327
+ let outText = "";
328
+ try {
329
+ let context = this.ragContext;
330
+ let thread = ThreadMgr.getThread();
331
+ let prompt = "";
332
+ let text = "";
333
+ let decr = 0;
334
+
335
+ while (true) {
336
+ thread = this.truncInput(thread, decr);
337
+ prompt = promptThread(context, thread, query);
338
+ const payload = getPayloadQuery(prompt);
339
+
340
+ try {
341
+ text = await HfRequest.post(payload);
342
+ if (!text) return "";
343
+ } catch (err) {
344
+ const e = this.errorInfo(err);
345
+ if (e.errorType === ERROR_TOKENS) {
346
+ UaLog.log(`Error tokens.5 ${prompt.length}`);
347
+ xlog(`Error tokens. ${prompt.length}`);
348
+ decr += PROMPT_DECR;
349
+ continue;
350
+ } else {
351
+ xerror(err);
352
+ throw e.errorType;
353
+ }
354
+ }
355
+ break;
356
+ }
357
+ ThreadMgr.add(query, text);
358
+ outText = ThreadMgr.getOutText();
359
+ UaLog.log(`Conversazione (${prompt.length},${text.length})`);
360
+ } catch (error) {
361
+ alert("requestContext(2) \n" + error);
362
+ xerror(error);
363
+ outText = error;
364
+ throw error;
365
+ } finally {
366
+ outText = cleanOutput(outText);
367
+ return outText;
368
+ }
369
+ }
370
+ },
371
+ };
372
+
373
+ const ThreadMgr = {
374
+ rows: [],
375
+ init() {
376
+ this.rows = [];
377
+ },
378
+ add(query, resp) {
379
+ const row = [query, resp];
380
+ this.rows.push(row);
381
+ },
382
+ getOutText() {
383
+ const rows = [];
384
+ for (const ua of this.rows) {
385
+ const u = ua[0].trim();
386
+ const a = ua[1].trim();
387
+ rows.push(`<user>:\n${u}\n<Assistant>:\n${a}\n\n`);
388
+ }
389
+ let text = rows.join("").trim();
390
+ return text;
391
+ },
392
+ getThread() {
393
+ const rows = [];
394
+ for (const ua of this.rows) {
395
+ const u = ua[0].trim();
396
+ const a = ua[1].trim();
397
+ rows.push(`<user>:\n${u}\n<Assitant>:\n${a}\n\n`);
398
+ }
399
+ const text = rows.join("").trim();
400
+ return text;
401
+ },
402
+ isFirst() {
403
+ return this.rows.length == 0;
404
+ },
405
+ };
static/javascript/rag_prompts.js ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ function promptDoc(documento, domanda) {
4
+ return `
5
+ [[RUOLO]]
6
+ Analista di documenti esperto nell'estrazione di informazioni pertinenti.
7
+
8
+ [[COMPITO]]
9
+ Analizza il documento e estrai le informazioni rilevanti per la domanda.
10
+
11
+ [[DOCUMENTO]]
12
+ ${documento}
13
+
14
+ [[DOMANDA]]
15
+ ${domanda}
16
+
17
+ [[ISTRUZIONI]]
18
+ 1. Identifica i concetti chiave e sintetizzali per fornire una risposta completa.
19
+ 2. Assicurati di organizzare le informazioni in modo chiaro e logico.
20
+ 3. Conserva le informazioni contrastanti, se presenti, senza tentare di risolverle.
21
+ 4. Puoi fare inferenze ragionevoli basate sulle informazioni fornite.
22
+ 5. Includi citazioni o riferimenti specifici al documento solo se necessari per chiarire la descrizione.
23
+
24
+ [[OUTPUT]]
25
+ Elenco delle informazioni identificate, incluse eventuali inferenze
26
+ `;
27
+ }
28
+
29
+ function promptToContext(risposte) {
30
+ return `
31
+ [[RUOLO]]
32
+ Esperto di analisi semantica delle informazioni.
33
+
34
+ [[OBIETTIVO]]
35
+ Unificare le informazioni semanticamente equivalenti da vari documenti.
36
+
37
+ [[ELENCO_RISPOSTE]]
38
+ ${risposte}
39
+
40
+ [[ISTRUZIONI]]
41
+ 1. Analizza le informazioni dell'elenco risposte.
42
+ 2. Per ogni documento raggruppa le informazioni sulla base del loro significato.
43
+ 3. Presenta le informazioni in modo chiaro e coerente.
44
+
45
+ [[OUTPUT]]
46
+ Elenco delle informazioni mantenendo la divisione per documento.
47
+ `;
48
+ }
49
+
50
+ function promptWithContext(contesto, domanda) {
51
+ return `
52
+ [[COMPITO]]
53
+ Elabora una risposta esaustiva e pertinente alla domanda basata sul contesto fornito.
54
+
55
+ [[CONTESTO]]
56
+ ${contesto}
57
+
58
+ [[DOMANDA]]
59
+ ${domanda}
60
+
61
+ [[ISTRUZIONI]]
62
+ 1. Analizza attentamente il contesto e la domanda posta.
63
+ 2. Struttura una risposta logica, coerente e completa.
64
+ 3. Utilizza le informazioni del contesto, citando i documenti di origine solo se necessario per chiarire la descrizione.
65
+ 4. Evidenzia le connessioni tra i vari concetti e le fonti.
66
+ 5. Includi inferenze ragionevoli.
67
+
68
+ [[OUTPUT]]
69
+ L'output è destinato ad essere letto da un lettore italiano.
70
+ `;
71
+ }
72
+
73
+ function promptThread(contesto, conversazione, domanda) {
74
+ return `
75
+ [[COMPITO]]
76
+ Rispondi alla nuova domanda integrando il contesto iniziale e gli sviluppi della conversazione in corso.
77
+
78
+ [[CONTESTO]]
79
+ ${contesto}
80
+
81
+ [[CONVERSAZIONE]]
82
+ ${conversazione}
83
+
84
+ [[DOMANDA]]
85
+ ${domanda}
86
+
87
+ [[ISTRUZIONI]]
88
+ 1. Analizza la nuova domanda nel contesto della conversazione in corso.
89
+ 2. Integra le informazioni dal contesto iniziale con gli sviluppi della discussione.
90
+ 3. Mantieni la coerenza con la conversazione precedente, evitando ripetizioni non necessarie.
91
+ 4. Puoi fare inferenze ragionevoli.
92
+ 5. Adatta la risposta alla domanda attuale, anche se si discosta dal tema principale della conversazione.
93
+ 6. Usa citazioni o riferimenti solo se necessario per chiarire la descrizione.
94
+
95
+ [[OUTPUT]]
96
+ L'output è destinato ad essere letto da un lettore italiano.
97
+ `;
98
+ }
99
+
100
+ ///////////////////////////////////}
101
+ /*
102
+
103
+ 1. max_new_tokens: 512
104
+ Questo è un valore ragionevole per risposte di lunghezza media.
105
+ Potrebbe essere aumentato a 1024 o più se si desiderano risposte più lunghe e dettagliate.
106
+
107
+ 2. temperature: 0.7
108
+ Questo valore offre un buon equilibrio tra creatività e coerenza.
109
+ Va bene per la maggior parte degli usi.
110
+
111
+ 3. top_k: 50
112
+ Un valore standard che limita la selezione alle 50 parole più probabili.
113
+ È appropriato per la maggior parte delle applicazioni.
114
+
115
+ 4. top_p: 0.85
116
+ Questo valore di nucleus sampling è buono per mantenere un buon equilibrio
117
+ tra diversità e coerenza.
118
+
119
+ 5. do_sample: true
120
+ Corretto per generare testo più vario.
121
+
122
+ 6. no_repeat_ngram_size: 3
123
+ Aiuta a evitare ripetizioni a breve termine.
124
+ Potrebbe essere aumentato a 4 o 5 per evitare ripetizioni più lunghe.
125
+
126
+ 7. num_beams: 5
127
+ Un buon valore per la beam search.
128
+ Aumentarlo potrebbe migliorare la qualità ma aumenterebbe anche il
129
+ tempo di elaborazione.
130
+
131
+ 8. repetition_penalty: 1.2
132
+ Un valore moderato per penalizzare le ripetizioni.
133
+ Potrebbe essere aumentato leggermente (es. 1.3 o 1.4) se si notano
134
+ ancora troppe ripetizioni.
135
+
136
+ 9. return_full_text: false
137
+ Corretto se si vuole solo il nuovo testo generato.
138
+
139
+ 10. max_time: 60.0
140
+ Un minuto è un tempo ragionevole. Potrebbe essere aumentato
141
+ se si stanno generando risposte molto lunghe o complesse.
142
+
143
+ 11. seed: 42
144
+ Un valore fisso per la riproducibilità.
145
+ Va bene se si desidera coerenza tra le esecuzioni.
146
+
147
+ Suggerimenti per l'ottimizzazione:
148
+ 1. Considera di aumentare max_new_tokens a 1024 o più se hai bisogno di risposte più lunghe.
149
+ 2. Potresti aumentare leggermente no_repeat_ngram_size a 4 per ridurre ulteriormente le ripetizioni.
150
+ 3. Se desideri risposte più precise e meno creative, potresti ridurre temperature a 0.6 e top_p a 0.8.
151
+ 4. Per risposte più diverse, potresti aumentare temperature a 0.8 e top_p a 0.9.
152
+ 5. Se noti ancora troppe ripetizioni, considera di aumentare repetition_penalty a 1.3 o 1.4.
153
+ */
154
+ const getPayloadDoc = (prompt) => {
155
+ let payload = {
156
+ inputs: prompt,
157
+ parameters: {
158
+ task: "text2text-generation",
159
+ max_new_tokens: 512,
160
+ num_return_sequences: 1,
161
+ temperature: 0.6,
162
+ top_k: 50,
163
+ top_p: 0.85,
164
+ do_sample: true,
165
+ no_repeat_ngram_size: 4,
166
+ num_beams: 6,
167
+ repetition_penalty: 1.2,
168
+ return_full_text: false,
169
+ details: false,
170
+ max_time: 90.0,
171
+ seed: 42,
172
+ },
173
+ options: {
174
+ use_cache: false,
175
+ wait_for_model: true,
176
+ },
177
+ };
178
+ return payload;
179
+ };
180
+
181
+ const getPlayloadContext = (prompt) => {
182
+ let payload = {
183
+ inputs: prompt,
184
+ parameters: {
185
+ task: "text2text-generation",
186
+ max_new_tokens: 1024,
187
+ num_return_sequences: 1,
188
+ temperature: 0.8,
189
+ top_k: 50,
190
+ top_p: 0.85,
191
+ do_sample: true,
192
+ no_repeat_ngram_size: 3,
193
+ num_beams: 5,
194
+ repetition_penalty: 1.1,
195
+ return_full_text: false,
196
+ details: false,
197
+ max_time: 120.0,
198
+ seed: 42,
199
+ },
200
+ options: {
201
+ use_cache: false,
202
+ wait_for_model: true,
203
+ },
204
+ };
205
+ return payload;
206
+ };
207
+
208
+ const getPayloadQuery = (prompt) => {
209
+ const seed = Math.floor(Math.random() * Math.pow(2, 32));
210
+ let payload = {
211
+ inputs: prompt,
212
+ parameters: {
213
+ task: "text-generation",
214
+ max_new_tokens: 512,
215
+ num_return_sequences: 1,
216
+ temperature: 0.7,
217
+ top_k: 50,
218
+ top_p: 0.85,
219
+ do_sample: true,
220
+ no_repeat_ngram_size: 3,
221
+ num_beams: 5,
222
+ repetition_penalty: 1.4,
223
+ return_full_text: false,
224
+ details: false,
225
+ max_time: 120.0,
226
+ seed: 42,
227
+ },
228
+ options: {
229
+ use_cache: false,
230
+ wait_for_model: true,
231
+ },
232
+ };
233
+ return payload;
234
+ };
235
+
static/javascript/rag_rqs.js ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+ /**
3
+ * @license
4
+ * rag_rqs
5
+ * Copyright (C) 2024 [Il tuo nome]
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
19
+ */
20
+
21
+ "use strict";
22
+ const VERS = "0.1.33 (16-07-2024)";
23
+
24
+ var xlog = console.log;
25
+ var xerror = console.error;
26
+ //////////////////////
27
+
28
+ /////////////////////////
29
+ // let T0 = {};
30
+
31
+ // var start_performance = function (k) {
32
+ // T0.k = performance.now();
33
+ // };
34
+
35
+ // var log_performance = function (k, msg = "") {
36
+ // const t1 = performance.now();
37
+ // const d = t1 - T0.k;
38
+ // console.log(msg, d);
39
+ // T0.k = t1;
40
+ // return d;
41
+ // };
42
+
43
+ // function showMessage(message, duraction = 5000) {
44
+ // const popup = document.createElement("div");
45
+ // popup.className = "msg";
46
+ // popup.innerText = message;
47
+ // document.body.appendChild(popup);
48
+ // setTimeout(function () {
49
+ // document.body.removeChild(popup);
50
+ // }, duraction);
51
+ // }
52
+
53
+ const cancelRequest = () => {
54
+ const ok = confirm("Confermi Cancellazione Richeista ?");
55
+ if (!ok) return;
56
+ HfRequest.cancelRequest();
57
+ hideSpinner();
58
+ };
59
+
60
+ const showSpinner = () => {
61
+ const spinner = document.getElementById("spinner");
62
+ spinner.classList.add("show-spinner");
63
+ spinner.addEventListener("click", cancelRequest);
64
+ };
65
+
66
+ const hideSpinner = () => {
67
+ const spinner = document.getElementById("spinner");
68
+ spinner.classList.remove("show-spinner");
69
+ spinner.removeEventListener("click", cancelRequest);
70
+ };
71
+
72
+ ////////////////////////
73
+ function openApp() {
74
+ wnds.init();
75
+ Menu.init();
76
+ TextInput.init();
77
+ TextOutput.init();
78
+ document.querySelector(".menu-btn").checked = false;
79
+ release();
80
+ }
81
+
82
+ function release() {
83
+ document.querySelector(".release").innerHTML = VERS;
84
+ }
85
+
86
+ /////////////////////////
87
+ // README
88
+ const op0 = async function (e) {
89
+ const text = await requestGet("./help1.html");
90
+ wnds.wdiv.show(text);
91
+ };
92
+
93
+ //query iniziale
94
+ function op1(e) {
95
+ Rag.readFromDb();
96
+ const txt = `\n${Rag.ragQuery}`;
97
+ wnds.wpre.show(txt);
98
+ // Menu.close();
99
+ }
100
+
101
+ //Rispost Rsg
102
+ function showRagResponse(e) {
103
+ Rag.readFromDb();
104
+ const txt = `\n${Rag.ragResponse}`;
105
+ wnds.wpre.show(txt);
106
+ }
107
+
108
+ //elenco risposte
109
+ function op2(e) {
110
+ let rs = [...Rag.responses];
111
+ if (rs.length == 0) {
112
+ rs = UaDb.readArray("id_responses");
113
+ }
114
+ if (rs.length == 0) return;
115
+ const text = rs
116
+ .map((x, i) => {
117
+ return `[${i + 1}]\n ${x.trim()}`;
118
+ })
119
+ .join("\n");
120
+ wnds.wpre.show(text);
121
+ // Menu.close();
122
+ }
123
+
124
+ //contesto
125
+ function op3(e) {
126
+ Rag.readFromDb();
127
+ const txt = `${Rag.ragContext}`;
128
+ wnds.wpre.show(txt);
129
+ // Menu.close();
130
+ }
131
+
132
+ //elemco dati
133
+ function op4(e) {
134
+ const ids = UaDb.getAllIds();
135
+ const arr = [];
136
+ for (const id of ids) {
137
+ const s = UaDb.read(id);
138
+ const l = s.length;
139
+ arr.push(`${id} (${l})`);
140
+ }
141
+ let msg = arr.join("\n ");
142
+ wnds.wpre.show(msg);
143
+ }
144
+
145
+ //elenco documenti
146
+ async function op5(e) {
147
+ DataMgr.readDbDocNames();
148
+ const arr = DataMgr.doc_names;
149
+ const s = arr.join("\n");
150
+ wnds.wpre.show(s);
151
+ }
152
+
153
+ //calcolo query
154
+ function calcQuery() {
155
+ const calc = () => {
156
+ const arr = [];
157
+ let nptot = 0;
158
+ let i = 0;
159
+ arr.push(`Documento Num.Parti`);
160
+ arr.push("==================");
161
+ for (const doc of DataMgr.docs) {
162
+ const name = DataMgr.doc_names[i];
163
+ i += 1;
164
+ const dl = doc.length;
165
+ const np = Math.ceil(dl / MAX_PROMPT_LENGTH);
166
+ nptot += np;
167
+ arr.push(`${name}&nbsp;&nbsp;&nbsp;[${np}]`);
168
+ }
169
+ arr.push("==================");
170
+ arr.push(`Totale num. Parti: ${nptot}`);
171
+ const s = arr.join("\n");
172
+ return s;
173
+ };
174
+ DataMgr.readDbDocs();
175
+ DataMgr.readDbDocNames();
176
+ const s = calc();
177
+ wnds.wpre.show(s);
178
+ }
179
+
180
+ //cancellA DATI
181
+ function op7(e) {
182
+ const ok = confirm("Confermi cancellazione dati?");
183
+ if (ok) {
184
+ DataMgr.deleteDati();
185
+ Rag.ragContext = "";
186
+ Rag.ragQuery = "";
187
+ Rag.responses = [];
188
+ wnds.wdiv.close();
189
+ wnds.wpre.close();
190
+ TextOutput.clear();
191
+ }
192
+ }
193
+ //cancella localstrage
194
+ function op8(e) {
195
+ const ok = confirm("Confermi cancellazione documenti & dati?");
196
+ if (ok) {
197
+ localStorage.clear();
198
+ Rag.ragContext = "";
199
+ Rag.ragQuery = "";
200
+ Rag.responses = [];
201
+ wnds.wdiv.close();
202
+ wnds.wpre.close();
203
+ TextOutput.clear();
204
+ DataMgr.docs = [];
205
+ DataMgr.doc_names = [];
206
+ }
207
+ }
208
+ ////////////////////////////////
209
+ // Solo Sviluppo
210
+ //prompts
211
+ function op9(e) {
212
+ if (Rag.prompts.length == 0) return;
213
+ const text = Rag.prompts
214
+ .map((x, i) => {
215
+ return `[${i + 1}]${x}\n`;
216
+ })
217
+ .join("\n");
218
+ wnds.wpre.show(text);
219
+ }
220
+ //testi
221
+ function op6(e) {
222
+ DataMgr.readDbDocs();
223
+ const arr = DataMgr.docs;
224
+ const s = arr.join("\n");
225
+ wnds.wpre.show(s);
226
+ }
227
+ ///////////////////////////
228
+ async function help1(e) {
229
+ const text = await requestGet("./data/help_test.html");
230
+ wnds.wdiv.show(text);
231
+ }
232
+
233
+ //lanciata dalla pagina diegli sempi
234
+ function esempio(name) {
235
+ const link = `data/${name}`;
236
+ DataMgr.loadDoc(link);
237
+ wnds.wdiv.close();
238
+ }
239
+
240
+ async function help2(e) {
241
+ const text = await requestGet("./help2.html");
242
+ wnds.wdiv.show(text);
243
+ }
static/javascript/rag_ui.js ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+ /**
3
+ * @license
4
+ * rag_rqs
5
+ * Copyright (C) 2024 [Il tuo nome]
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
19
+ */
20
+ const WndPre = (id) => {
21
+ return {
22
+ w: UaWindowAdm.create(id),
23
+ out: null,
24
+ show(s) {
25
+ const fh = (txt) => {
26
+ return `
27
+ <div class="window-text">
28
+ <div class="btn-wrapper">
29
+ <button class="btn-copy" title="Copia">
30
+ <svg class="copy-icon" viewBox="0 0 20 24">
31
+ <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
32
+ </svg>
33
+ </button>
34
+ <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>
35
+ </div>
36
+ <pre class="pre-text">${txt}</pre>
37
+ </div>
38
+ `;
39
+ };
40
+ wnds.closeAll();
41
+ const h = fh(s);
42
+ this.w.drag();
43
+ this.w.setZ(12);
44
+ this.w.vw_vh().setXY(16.5, 10, -1);
45
+ this.w.setHtml(h);
46
+ this.w.show();
47
+ const e = this.w.getElement();
48
+ const copyBtn = e.querySelector(".btn-copy");
49
+ copyBtn.addEventListener("click", () => this.copy());
50
+ },
51
+ close() {
52
+ this.w.close();
53
+ },
54
+ async copy() {
55
+ const e = this.w.getElement();
56
+ const pre = e.querySelector(".pre-text");
57
+ const t = pre.textContent;
58
+ try {
59
+ await navigator.clipboard.writeText(t);
60
+ } catch (err) {
61
+ xerror("Errore ", err);
62
+ }
63
+ },
64
+ };
65
+ };
66
+
67
+ const WndDiv = (id) => {
68
+ return {
69
+ w: UaWindowAdm.create(id),
70
+ out: null,
71
+ show(s) {
72
+ const fh = (txt) => {
73
+ return `
74
+ <div class="window-text">
75
+ <div class="btn-wrapper">
76
+ <button class="btn-copy" title="Copia">
77
+ <svg class="copy-icon" viewBox="0 0 20 24">
78
+ <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
79
+ </svg>
80
+ </button>
81
+ <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>
82
+ </div>
83
+ <div class="div-text">${txt}</div>
84
+ </div>
85
+ `;
86
+ };
87
+ wnds.closeAll();
88
+ const h = fh(s);
89
+ this.w.drag();
90
+ this.w.setZ(12);
91
+ this.w.vw_vh().setXY(16.5, 10, -1);
92
+ this.w.setHtml(h);
93
+ this.w.show();
94
+ const e = this.w.getElement();
95
+ const copyBtn = e.querySelector(".btn-copy");
96
+ copyBtn.addEventListener("click", () => this.copy());
97
+ },
98
+ close() {
99
+ this.w.close();
100
+ },
101
+ async copy() {
102
+ const e = this.w.getElement();
103
+ const pre = e.querySelector(".div-text");
104
+ const t = pre.textContent;
105
+ try {
106
+ await navigator.clipboard.writeText(t);
107
+ } catch (err) {
108
+ xerror("Errore ", err);
109
+ }
110
+ },
111
+ };
112
+ };
113
+
114
+ const wnds = {
115
+ wdiv: null,
116
+ wpre: null,
117
+ wout: null,
118
+ init() {
119
+ this.wdiv = WndDiv("id_w0");
120
+ this.wpre = WndPre("id_w1");
121
+ this.wout = WndPre("id_out");
122
+ },
123
+ closeAll() {
124
+ UaWindowAdm.close("id_w0");
125
+ UaWindowAdm.close("id_w1");
126
+ UaWindowAdm.close("id_out");
127
+ },
128
+ };
129
+
130
+ const Menu = {
131
+ init() {
132
+ // gestione menu
133
+ const btn = document.querySelector("#id-menu-btn");
134
+ btn.addEventListener("change", () => {
135
+ document.querySelector("body").classList.toggle("menu-open", btn.checked);
136
+ });
137
+ // getsioe log
138
+ const log = document.getElementById("id_log");
139
+
140
+ const show = () => {
141
+ if (log.classList.contains("active")) return;
142
+ log.classList.add("active");
143
+ };
144
+
145
+ const hide = () => {
146
+ if (!log.classList.contains("active")) return;
147
+ log.classList.remove("active");
148
+ };
149
+ UaLog.callHide = hide;
150
+ UaLog.callShow = show;
151
+
152
+ UaLog.setXY(64, 13).setZ(111).new();
153
+ UaLog.log_show("Buon Lavoro");
154
+ },
155
+ close() {
156
+ const btn = document.querySelector("#menu-toggle");
157
+ document.querySelector("body").classList.remove("menu-open", btn.checked);
158
+ document.querySelector(".menu-btn").checked = false;
159
+ },
160
+ async help() {
161
+ const text = await requestGet("./help0.html");
162
+ wnds.wdiv.show(text);
163
+ },
164
+ upload() {
165
+ RagUpload.open();
166
+ },
167
+ uploadDir() {
168
+ RagUpload.openDir();
169
+ },
170
+ async load() {
171
+ alert("load");
172
+ },
173
+ log() {
174
+ UaLog.toggle();
175
+ },
176
+ };
177
+
178
+
179
+ const TextInput = {
180
+ wnd: null,
181
+ init() {
182
+ this.inp = document.querySelector(".text-input");
183
+ document.addEventListener("keydown", (e) => {
184
+ if (document.activeElement !== this.inp) {
185
+ const allowedKeys = [
186
+ "F1",
187
+ "F2",
188
+ "F3",
189
+ "F4",
190
+ "F5",
191
+ "F6",
192
+ "F7",
193
+ "F8",
194
+ "F9",
195
+ "F10",
196
+ "F11",
197
+ "F12",
198
+ "Control",
199
+ "Alt",
200
+ "Shift",
201
+ "Meta",
202
+ "CapsLock",
203
+ "Escape",
204
+ "PrintScreen",
205
+ "ScrollLock",
206
+ "Pause",
207
+ "Insert",
208
+ "Delete",
209
+ "Home",
210
+ "End",
211
+ "PageUp",
212
+ "PageDown",
213
+ "ArrowLeft",
214
+ "ArrowRight",
215
+ "ArrowUp",
216
+ "ArrowDown",
217
+ ];
218
+ if (!allowedKeys.includes(e.key) && !e.ctrlKey && !e.metaKey) {
219
+ e.preventDefault();
220
+ }
221
+ }
222
+ });
223
+
224
+ const clsBtn = document.querySelector(".clear-button");
225
+ clsBtn.addEventListener("click", () => {
226
+ this.inp.value = "";
227
+ this.inp.focus();
228
+ });
229
+ // this.inp.addEventListener("keydown", (e) => this.handleEnter(e));
230
+ document.querySelector(".send-input").addEventListener("click", () => this.send());
231
+ document.querySelector(".send2-input").addEventListener("click", () => this.send2());
232
+ document.querySelector(".clear-input").addEventListener("click", () => this.clear());
233
+ },
234
+ handleEnter(e) {
235
+ // if (e.key === "Enter" && !e.shiftKey) {
236
+ // e.preventDefault();
237
+ // this.send();
238
+ // }
239
+ },
240
+
241
+ // legge i documenti dal DBlocale
242
+ // sala le risposte RAG
243
+ // crea il contesto
244
+ async send() {
245
+ const q=this.inp.value;
246
+ if (!q) {
247
+ alert("Ricorda di scrivere la Query ");
248
+ return;
249
+ }
250
+ Rag.readFromDb();
251
+ if (!!Rag.ragContext) {
252
+ const ok = confirm("Vuoi iniziare una nuova elabrazione ?");
253
+ if (!ok) return "";
254
+ }
255
+ showSpinner();
256
+ setOutText("");
257
+ const msg = this.inp.value.trim();
258
+ try {
259
+ const txt = await Rag.requestDocsRAG(msg);
260
+ setOutText(txt);
261
+ this.inp.value = "";
262
+ UaLog.close();
263
+ } catch (err) {
264
+ const msg = `send\n${err}`;
265
+ xerror(msg);
266
+ alert(msg);
267
+ setOutText(msg);
268
+ }
269
+ hideSpinner();
270
+ },
271
+
272
+ // utiliza il contesto esistente
273
+ async send2() {
274
+ const q=this.inp.value;
275
+ if (!q) {
276
+ alert("Ricorda di scrivere la Query ");
277
+ return;
278
+ }
279
+ showSpinner();
280
+ if (ThreadMgr.isFirst()) setOutText("");
281
+ const query = this.inp.value.trim();
282
+ try {
283
+ const text = await Rag.requestContext(query);
284
+ if (text == "") {
285
+ hideSpinner();
286
+ return;
287
+ }
288
+ setOutText(text);
289
+ this.inp.value = "";
290
+ } catch (err) {
291
+ const msg = `send2\n${err}`;
292
+ xerror(msg);
293
+ alert(msg);
294
+ setOutText(msg);
295
+ }
296
+ hideSpinner();
297
+ },
298
+ clear() {
299
+ const ok = confirm("Confermi cancellazione conversazione? ");
300
+ if (!ok) return;
301
+ this.inp.value = "";
302
+ setOutText("");
303
+ ThreadMgr.init();
304
+ },
305
+ };
306
+
307
+ //XXX const setOutText = (txt) => {
308
+ // let out = document.getElementById("id-text-out");
309
+ // const ht = `<div class="div-text">${txt}</div>`;
310
+ // out.innerHTML=ht;
311
+ // const pre = out.querySelector(".div-text");
312
+ // pre.scrollTop = pre.scrollHeight;
313
+ // };
314
+
315
+
316
+ const setOutText = (txt) => {
317
+ let out = document.getElementById("id-text-out");
318
+ const h = `<pre class="pre-text"></pre>`;
319
+ out.innerHTML = h;
320
+ const pre = out.querySelector(".pre-text");
321
+ pre.textContent = txt;
322
+ pre.scrollTop = pre.scrollHeight;
323
+ };
324
+
325
+ TextOutput = {
326
+ init() {
327
+ this.copyBtn = document.querySelector(".copy-output");
328
+ this.copyBtn.addEventListener("click", () => this.copy());
329
+ const clearBtn = document.querySelector(".clear-output");
330
+ clearBtn.addEventListener("click", () => this.clear());
331
+ const wndBtn = document.querySelector(".wnd-output");
332
+ wndBtn.addEventListener("click", () => this.openWnd());
333
+ },
334
+ openWnd() {
335
+ const p = document.getElementById("id-text-out");
336
+ const s = p.textContent;
337
+ wnds.wout.show(s);
338
+ },
339
+ async copy() {
340
+ const e = document.getElementById("id-text-out");
341
+ const pre = e.querySelector("pre");
342
+ if (!pre) return;
343
+ const t = pre.textContent;
344
+ pre.classList.add("copied");
345
+ this.copyBtn.classList.add("copied");
346
+ try {
347
+ await navigator.clipboard.writeText(t);
348
+ } catch (err) {
349
+ xerror("Errore ", err);
350
+ }
351
+ setTimeout(() => {
352
+ this.copyBtn.classList.remove("copied");
353
+ pre.classList.remove("copied");
354
+ }, 5000);
355
+ },
356
+ clear() {
357
+ const out = document.getElementById("id-text-out");
358
+ out.textContent = "";
359
+ },
360
+ };
static/javascript/rag_upload.js ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+
3
+ "use strict";
4
+
5
+ const RagUpload = {
6
+ open() {
7
+ const htmlContent = `
8
+ <div class="window-text">
9
+ <div class="btn-wrapper">
10
+ <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>
11
+ </div>
12
+ <div class="upload">
13
+ <h4>Upload file Text / PDF</h4>
14
+ <form id="uploadForm">
15
+ <input class="file" type="file" id="id_fileupload" >
16
+ <button type="button" onclick="RagUpload.upload();">Upload and Convert</button>
17
+ </form>
18
+ <div id="result" class="result"></div>
19
+ </div>
20
+ </div>
21
+ `;
22
+ const uploadWindow = UaWindowAdm.create("id_upload");
23
+ uploadWindow.drag();
24
+ uploadWindow.setZ(12);
25
+ uploadWindow.vw_vh().setXY(16.5, 10, -1);
26
+ uploadWindow.setHtml(htmlContent);
27
+ uploadWindow.show();
28
+ },
29
+ async upload() {
30
+ const fileInput = document.getElementById("id_fileupload");
31
+ const file = fileInput.files[0];
32
+ if (!file) {
33
+ alert("Nessun file selezionato.");
34
+ return;
35
+ }
36
+ const fileName = file.name;
37
+ const exist = DataMgr.doc_names.includes(fileName);
38
+ if (exist) {
39
+ alert("Il file è già in archivio");
40
+ return;
41
+ }
42
+
43
+ const result = document.getElementById("result");
44
+ const fileExtension = file.name.split(".").pop().toLowerCase();
45
+ showSpinner();
46
+ try {
47
+ let text;
48
+ if (fileExtension === "pdf") {
49
+ const pdfHandler = new PdfHandler();
50
+ await pdfHandler.loadPdfJs();
51
+ text = await pdfHandler.extractTextFromPDF(file);
52
+ pdfHandler.cleanup();
53
+ } else if (fileExtension === "txt") {
54
+ text = await readTextFile(file);
55
+ } else {
56
+ alert("Formato file non supportato.");
57
+ return;
58
+ }
59
+ DataMgr.addDoc(fileName, text);
60
+ const msg = `<br><br> ${fileName}<br><br>caricato e salvato nella memoria locale`;
61
+ result.innerHTML = msg;
62
+ } catch (error) {
63
+ console.error("Error:", error);
64
+ alert("Errore durante l'estrazione del testo dal file.");
65
+ } finally {
66
+ hideSpinner();
67
+ }
68
+ },
69
+ openDir() {
70
+ const htmlContent = `
71
+ <div class="window-text">
72
+ <div class="btn-wrapper">
73
+ <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>
74
+ </div>
75
+ <div class="upload">
76
+ <h4>Upload files Text / PDF</h4>
77
+ <form id="uploadForm">
78
+ <input id="id_fileupload" class="file" type="file" webkitdirectory mozdirectory msdirectory odirectory directory multiple />
79
+ <button type="button" onclick="RagUpload.uploadDir();">Upload and Convert</button>
80
+ </form>
81
+ <div class="result" id="result"></div>
82
+ </div>
83
+ </div>
84
+ `;
85
+ const uploadWindow = UaWindowAdm.create("id_upload");
86
+ uploadWindow.drag();
87
+ uploadWindow.setZ(12);
88
+ uploadWindow.vw_vh().setXY(16.5, 10, -1);
89
+ uploadWindow.setHtml(htmlContent);
90
+ uploadWindow.show();
91
+ },
92
+
93
+ async uploadDir() {
94
+ const fileInput = document.getElementById("id_fileupload");
95
+ const files = fileInput.files;
96
+
97
+ if (!files || files.length == 0) {
98
+ alert("Nessun file selezionato.");
99
+ return;
100
+ }
101
+ const msgs = [];
102
+
103
+ showSpinner();
104
+
105
+ try {
106
+ for (const file of files) {
107
+ const fileName = file.name;
108
+ UaLog.log_show(fileName);
109
+ const exist = DataMgr.doc_names.includes(fileName);
110
+ if (exist) {
111
+ UaLog.log_shw(fileName + " : è già in archivio");
112
+ continue;
113
+ }
114
+ const fileExtension = file.name.split(".").pop().toLowerCase();
115
+ let text;
116
+ if (fileExtension === "pdf") {
117
+ const pdfHandler = new PdfHandler();
118
+ await pdfHandler.loadPdfJs();
119
+ text = await pdfHandler.extractTextFromPDF(file);
120
+ pdfHandler.cleanup();
121
+ } else if (fileExtension === "txt") {
122
+ text = await readTextFile(file);
123
+ } else {
124
+ alert("Formato file non supportato.");
125
+ return;
126
+ }
127
+ DataMgr.addDoc(fileName, text);
128
+ const msg = `${fileName}`;
129
+ msgs.push(msg);
130
+ }
131
+ } catch (error) {
132
+ console.error("Error:", error);
133
+ alert("Errore durante l'estrazione del testo dal file.");
134
+ } finally {
135
+ hideSpinner();
136
+ }
137
+
138
+ const result = document.getElementById("result");
139
+ const msg = msgs.join("<br>");
140
+ result.innerHTML = msg;
141
+ },
142
+ };
143
+
144
+ class PdfHandler {
145
+ constructor() {
146
+ this.pdfjsLib = null;
147
+ this.scriptElement = null;
148
+ this.workerScriptElement = null;
149
+ }
150
+
151
+ async loadPdfJs() {
152
+ if (window["pdfjsLib"]) {
153
+ this.pdfjsLib = window["pdfjs-dist/build/pdf"];
154
+ this.pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js";
155
+ return;
156
+ }
157
+ // Carica pdf.js dinamicamente
158
+ this.scriptElement = document.createElement("script");
159
+ this.scriptElement.src = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.min.js";
160
+ document.body.appendChild(this.scriptElement);
161
+
162
+ // Aspetta che il worker sia caricato
163
+ await new Promise((resolve) => {
164
+ this.scriptElement.onload = () => {
165
+ this.workerScriptElement = document.createElement("script");
166
+ this.workerScriptElement.src = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js";
167
+ document.body.appendChild(this.workerScriptElement);
168
+ this.workerScriptElement.onload = resolve;
169
+ };
170
+ });
171
+
172
+ this.pdfjsLib = window["pdfjs-dist/build/pdf"];
173
+ this.pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js";
174
+ }
175
+
176
+ async extractTextFromPDF(file) {
177
+ const arrayBuffer = await file.arrayBuffer();
178
+ const pdf = await this.pdfjsLib.getDocument({ data: arrayBuffer }).promise;
179
+ let text = "";
180
+ for (let i = 1; i <= pdf.numPages; i++) {
181
+ const page = await pdf.getPage(i);
182
+ const textContent = await page.getTextContent();
183
+ const pageText = textContent.items.map((item) => item.str).join(" ");
184
+ text += pageText + "\n";
185
+ }
186
+ return text;
187
+ }
188
+
189
+ cleanup() {
190
+ if (this.scriptElement) {
191
+ document.body.removeChild(this.scriptElement);
192
+ this.scriptElement = null;
193
+ }
194
+ if (this.workerScriptElement) {
195
+ document.body.removeChild(this.workerScriptElement);
196
+ this.workerScriptElement = null;
197
+ }
198
+ this.pdfjsLib = null;
199
+ if (window.gc) {
200
+ window.gc();
201
+ }
202
+ }
203
+ }
204
+
205
+ async function readTextFile(file) {
206
+ if (!file || file.type !== "text/plain") {
207
+ throw new Error("Invalid file type. Please select a text file.");
208
+ }
209
+ return new Promise((resolve, reject) => {
210
+ const reader = new FileReader();
211
+ reader.onload = (event) => resolve(event.target.result);
212
+ reader.onerror = (error) => reject(new Error("Error reading file: " + error.message));
213
+ reader.readAsText(file);
214
+ });
215
+ }
static/javascript/uadrag.js ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // jshint esversion: 8
2
+ // release 24-04-2022
3
+
4
+
5
+ const nodrag_tds = ['input', 'select', 'a'];
6
+ const nodrag_cls = "nodrag";
7
+
8
+ var UaDrag = function (e) {
9
+ const drag = function (element) {
10
+ let pos1 = 0,
11
+ pos2 = 0,
12
+ pos3 = 0,
13
+ pos4 = 0;
14
+
15
+ const dragMouseDown = function (e) {
16
+ e = e || window.event;
17
+ let t = e.target;
18
+ t = t || null;
19
+ if (!t) return;
20
+ if (nodrag_tds.includes(t.tagName.toLowerCase())) return;
21
+ if (t.classList.contains(nodrag_cls)) return;
22
+ e.preventDefault();
23
+ //e.stopImmediatePropagation();
24
+ pos3 = e.clientX;
25
+ pos4 = e.clientY;
26
+ document.onmouseup = closeDragElement;
27
+ document.onmousemove = elementDrag;
28
+ };
29
+
30
+ const elementDrag = function (e) {
31
+ e = e || window.event;
32
+ //e.stopImmediatePropagation();
33
+ e.preventDefault();
34
+ pos1 = pos3 - e.clientX;
35
+ pos2 = pos4 - e.clientY;
36
+ pos3 = e.clientX;
37
+ pos4 = e.clientY;
38
+ element.style.top = (element.offsetTop - pos2) + "px";
39
+ element.style.left = (element.offsetLeft - pos1) + "px";
40
+ };
41
+
42
+ const closeDragElement = function () {
43
+ document.onmouseup = null;
44
+ document.onmousemove = null;
45
+ };
46
+
47
+ element.onmousedown = dragMouseDown;
48
+ };
49
+ return drag(e);
50
+ };
51
+
static/javascript/uajtfh.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+ const UaJtfh = () => {
3
+ return {
4
+ rows: [],
5
+ init() {
6
+ this.rows = [];
7
+ return this;
8
+ },
9
+ insert(s) {
10
+ this.rows.unshift(s);
11
+ return this;
12
+ },
13
+ append(s) {
14
+ this.rows.push(s);
15
+ return this;
16
+ },
17
+ text(ln = "") {
18
+ return this.rows.join(ln);
19
+ },
20
+ html(ln = "") {
21
+ const h = this.rows.join(ln).replace(/\s+|\[rn\]/g, " ");
22
+ return h;
23
+ },
24
+ };
25
+ };
static/javascript/ualog.js ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+ // function show() {
3
+ // const log = document.getElementById("id_log");
4
+ // if (log.classList.contains("active")) return;
5
+ // log.classList.add("active");
6
+ // }
7
+
8
+ // function hide() {
9
+ // const log = document.getElementById("id_log");
10
+ // if (!log.classList.contains("active")) return;
11
+ // log.classList.remove("active");
12
+ // }
13
+ // jshint esversion: 8
14
+ // release 09-'6-24
15
+ // utilizzare l'ultima versione di UaWindowAdm
16
+ // setXY con vw ,vh
17
+ var UaLog = {
18
+ callHide: function () {},
19
+ callShow: function () {},
20
+ active: false,
21
+ wind: null,
22
+ x: null,
23
+ y: null,
24
+ z: null,
25
+ max_length: 2000,
26
+ msg_id: "ualogmsg_",
27
+ new: function () {
28
+ if (this.wind == null) {
29
+ this.wind = UaWindowAdm.create("ualog_");
30
+ this.wind.drag();
31
+ }
32
+ const h = `
33
+ <button type="button" onclick="javascript:UaLog.cls();">Clear</button>
34
+ <button type="button" onclick="javascript:UaLog.close();">Close</button>
35
+ <div id="ualogmsg_"></div>`;
36
+ this.wind.setHtml(h);
37
+ this.wind.setStyle({
38
+ width: "auto",
39
+ minWidth: "300px",
40
+ maxWidth: "400px",
41
+ height: "auto",
42
+ textAlign: "center",
43
+ padding: "2px 2px 2px 2px",
44
+ margin: "5px 0 0 0",
45
+ // background: "#111111",
46
+ background: "#333333",
47
+ color: "#ffffff",
48
+ fontSize: "15px",
49
+ fontWeight: "normal",
50
+ borderRadius: "9px",
51
+ border: "1px solid #999999",
52
+ });
53
+
54
+ const msg = document.getElementById(this.msg_id);
55
+ const msg_css = {
56
+ width: "auto",
57
+ textAlign: "left",
58
+ fontSize: "16px",
59
+ fontFamily:"monospace",
60
+ paddingTop: "2px ",
61
+ marginTop: "2px",
62
+ color: "inherit",
63
+ // background: "#444444",
64
+ background: "#000000",
65
+ maxHeight: "600px",
66
+ overflow: "auto",
67
+ scrollbarColor: "#ab3205 #ffffff",
68
+ scrollbarWidth: "auto",
69
+ };
70
+ for (const k in msg_css) msg.style[k] = msg_css[k];
71
+
72
+ const btn_css = {
73
+ background: "#444444",
74
+ color: "#ffffff",
75
+ padding: "5px 5px 5px 5px",
76
+ margin: "0 5px 0 5px",
77
+ fontSize: "16px",
78
+ fontWeight: "bold",
79
+ border: "1px solid #ffffff",
80
+ borderRadius: "10px",
81
+ };
82
+ const btns = document.querySelectorAll("#ualog_ button");
83
+ for (const b of btns) {
84
+ for (const k in btn_css) b.style[k] = btn_css[k];
85
+ b.addEventListener("mouseover", (e) => {
86
+ e.target.style.cursor = "pointer";
87
+ e.target.style.color = "#000000";
88
+ e.target.style.background = "#aaaaaa";
89
+ });
90
+ b.addEventListener("mouseout", (e) => {
91
+ for (const k in btn_css) e.target.style[k] = btn_css[k];
92
+ });
93
+ }
94
+ if (!!this.x) this.wind.vw_vh().setXY(this.x, this.y, -1);
95
+ else this.wind.setCenter(-1);
96
+ if (!!this.z) this.wind.setZ(this.z);
97
+ return this;
98
+ },
99
+ setXY(x, y) {
100
+ this.x = x;
101
+ this.y = y;
102
+ return this;
103
+ },
104
+ setZ(z) {
105
+ this.z = z;
106
+ return this;
107
+ },
108
+ prn_(...args) {
109
+ let s = args.join("<br/>");
110
+ let e = document.getElementById(this.msg_id);
111
+ let h = e.innerHTML + s + "<br/>";
112
+ if (h.length > this.max_length) h = h.slice(-this.max_length);
113
+ e.innerHTML = h;
114
+ },
115
+ print(...args) {
116
+ if (this.wind == null) return;
117
+ if (!this.active) return;
118
+ this.prn_(...args);
119
+ },
120
+ log(...args) {
121
+ if (this.wind == null) return;
122
+ this.prn_(...args);
123
+ },
124
+ log_show(...args) {
125
+ if (this.wind == null) return;
126
+ if (!this.active) this.toggle();
127
+ this.prn_(...args);
128
+ },
129
+ cls() {
130
+ if (this.wind == null) return;
131
+ document.getElementById(this.msg_id).innerHTML = "";
132
+ return this;
133
+ },
134
+ close() {
135
+ if (this.wind == null) return;
136
+ this.wind.hide();
137
+ this.active = false;
138
+ this.callHide();
139
+ },
140
+ // open() {
141
+ // if (this.wind == null) return;
142
+ // this.wind.show();
143
+ // this.active = true;
144
+ // },
145
+ toggle() {
146
+ if (this.wind == null) return;
147
+ if (!this.active) {
148
+ this.active = true;
149
+ this.wind.show();
150
+ this.callShow();
151
+ } else {
152
+ this.active = false;
153
+ this.wind.hide();
154
+ this.callHide();
155
+ }
156
+ },
157
+ };
static/javascript/uawindow.js ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+
3
+ // jshint esversion: 8
4
+ // release 03-05-24
5
+ "use strict";
6
+
7
+ var UaWindowAdm = {
8
+ ws: {},
9
+ create(id, parent_id = null) {
10
+ let w = document.getElementById(id);
11
+ if (!w) {
12
+ w = document.createElement("div");
13
+ if (!parent_id) document.body.appendChild(w);
14
+ else document.getElementById(parent_id).appendChild(w);
15
+ w.id = id;
16
+ w.setAttribute("data-name", "ua-window");
17
+ const uaw = this.newUaWindow(w);
18
+ this.ws[id] = uaw;
19
+ }
20
+ const uaw = this.ws[id];
21
+ w.style.display = "none";
22
+ return uaw;
23
+ },
24
+ get(id) {
25
+ if (!this.ws[id]) return null;
26
+ return this.ws[id];
27
+ },
28
+ show(id) {
29
+ if (!!this.ws[id]) this.ws[id].show();
30
+ },
31
+ close(id) {
32
+ if (!!this.ws[id]) this.ws[id].close();
33
+ },
34
+ toggle(id) {
35
+ if (!!this.ws[id]) this.ws[id].toggle();
36
+ },
37
+ hide(id) {
38
+ if (!!this.ws[id]) this.ws[id].hide();
39
+ },
40
+ closeThis(e) {
41
+ const ancestor = e.closest('[data-name="ua-window"]');
42
+ const id = ancestor.id;
43
+ this.ws[id].close();
44
+ },
45
+ showAll() {
46
+ for (let k in this.ws) this.ws[k].show();
47
+ },
48
+ hideAll() {
49
+ for (let k in this.ws) this.ws[k].hide();
50
+ },
51
+ closeAll() {
52
+ for (let k in this.ws) this.ws[k].close();
53
+ },
54
+ remove(id) {
55
+ if (!this.ws[id]) return;
56
+ document.getElementById(id).remove();
57
+ this.ws[id] = null;
58
+ delete this.ws[id];
59
+ },
60
+ removeAll() {
61
+ for (let k in this.ws) this.remove(k);
62
+ this.ws = {};
63
+ },
64
+ newUaWindow(jqw) {
65
+ let wnd = {
66
+ initialize(w) {
67
+ this.w = w;
68
+ this.wx = "0px";
69
+ this.wy = "0px";
70
+ this.isOpen = false;
71
+ this.isVisible = false;
72
+ this.firstShow = true;
73
+ this.pos = 0;
74
+ this.wz = 0;
75
+ this.vw = "px";
76
+ this.vh = "px";
77
+ },
78
+ vw_vh() {
79
+ // setta coe unità di misura vw e vh al posto di px;
80
+ this.vw = "vw";
81
+ this.vh = "vh";
82
+ return this;
83
+ },
84
+ addClassStyle(className) {
85
+ if (!this.w.classList.contains(className)) this.w.classList.add(className);
86
+ return this;
87
+ },
88
+ removeClassStyle(className) {
89
+ if (this.w.classList.contains(className)) this.w.classList.remove(className);
90
+ return this;
91
+ },
92
+ getWindow() {
93
+ alert("getWindow => ??");
94
+ return this.w;
95
+ },
96
+ getElement() {
97
+ return this.w;
98
+ },
99
+ getId() {
100
+ return this.w.id;
101
+ },
102
+ setStyle(styles) {
103
+ for (const prop in styles) this.w.style[prop] = styles[prop];
104
+ return this;
105
+ },
106
+ setHtml(html) {
107
+ this.w.innerHTML = html;
108
+ return this;
109
+ },
110
+ getHtml() {
111
+ return this.w.innerHTML;
112
+ },
113
+ /*
114
+ pos==1) => si posiziona ad ogni chiamata di show
115
+ pos==0) => si posiziona ad ogni chiamata di show
116
+ sucessiva ad uno status hide (default)
117
+ pos==-1)=> si posiziona solo alla prima chiamata di show
118
+
119
+ x => 0 left=x
120
+ x < 0 right=abs(x)
121
+ */
122
+ setXY(x, y, pos = 0) {
123
+ this.wx = x;
124
+ this.wy = y;
125
+ this.pos = pos;
126
+ return this;
127
+ },
128
+ setCenterY(y, pos) {
129
+ let xd = window.innerWidth;
130
+ const wd = this.w.clientWidth;
131
+ let x = (xd - wd) / 2;
132
+ this.setXY(x, y, pos);
133
+ return this;
134
+ },
135
+ setCenter(pos) {
136
+ let xd = window.innerWidth;
137
+ let yd = window.innerHeight;
138
+ const wd = this.w.clientWidth;
139
+ const wh = this.w.clientHeight;
140
+ let x = (xd - wd) / 2;
141
+ let y = (yd - wh) / 2;
142
+ this.setXY(x, y, pos);
143
+ return this;
144
+ },
145
+ linkToId(linked_id, dx, dy, pos) {
146
+ let lk = document.getElementById(linked_id);
147
+ this.linkToElement(lk, dx, dy, pos);
148
+ return this;
149
+ },
150
+ linkToElement(elm, dx, dy, pos) {
151
+ let x = elm.offsetLeft + elm.offsetWidth + dx;
152
+ let y = elm.offsetTop + dy;
153
+ if (y < 0) y = 0;
154
+ this.setXY(x, y, pos);
155
+ return this;
156
+ },
157
+ setZ(z) {
158
+ this.wz = z;
159
+ return this;
160
+ },
161
+ reset() {
162
+ this.firstShow = true;
163
+ return this;
164
+ },
165
+ toggle() {
166
+ if (!this.isVisible) this.show();
167
+ else this.hide();
168
+ return this;
169
+ },
170
+ show() {
171
+ if (this.firstShow || this.pos == 1 || (this.pos === 0 && this.isVisible === false)) {
172
+ this.w.style.position = "absolute";
173
+ this.w.style.marginLeft = 0;
174
+ this.w.style.marginTop = 0;
175
+ this.w.style.top = `${this.wy}${this.vh}`;
176
+ if (this.wx >= 0) this.w.style.left = `${this.wx}${this.vw}`;
177
+ else this.w.style.right = -`${this.wx}${this.vw}`;
178
+ if (this.wz > 0) this.w.style.zIndex = this.wz;
179
+ }
180
+ this.w.style.display = "";
181
+ this.firstShow = false;
182
+ this.isVisible = true;
183
+ this.isOpen = true;
184
+ return this;
185
+ },
186
+ hide() {
187
+ this.w.style.display = "none";
188
+ this.isVisible = false;
189
+ return this;
190
+ },
191
+ close() {
192
+ this.w.style.display = "none";
193
+ this.w.innerHTML = "";
194
+ // this.w.innerHTML = "block";
195
+ this.isOpen = false;
196
+ return this;
197
+ },
198
+ remove() {
199
+ const id = this.w.id;
200
+ UaWindowAdm.remove(id);
201
+ return null;
202
+ },
203
+ drag() {
204
+ UaDrag(this.w);
205
+ return this;
206
+ },
207
+ };
208
+ wnd.initialize(jqw);
209
+ return wnd;
210
+ },
211
+ };
static/js/ragrqs.min.js ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function cleanDoc(a){a=a.split("\n").map(function(b){return b.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF]/g,"")}).join("\n");a=a.replace(/\t/g," ");a=a.replace(/ +/g," ");a=a.split("\n").map(b=>b.trim()).join("\n");a=a.replace(/\n\s*\n/g,"\n\n");a=a.replace(/["""]/g,'"').replace(/['']/g,"'");a=a.replace(/[\u2013\u2014]/g,"-");a=a.replace(/\\[nrt]/g,"");a=a.replace(/[^\p{L}\p{N}\s\.,;:!?'"()\-]/gu,"");a=a.replace(/ +([.,;:!?])/g,"$1");return a.trim()}
2
+ function list2text(a){return text=a.map(b=>`${b.trim()}`).join("\n")}function cleanOutput(a){a=a.trim();a=a.replace(/\n{3,}/g,"\n\n");a=a.replace(/^[ \t]+/gm,"");a=a.replace(/^(\s*[-*\u2022])(\s*)/gm,"\n$1 ");a=a.replace(/^(\s*\d+\.)(\s*)/gm,"\n$1 ");a=a.replace(/(```[\s\S]*?```)/g,"\n\n$1\n\n");return a=a.replace(/[ \t]+$/gm,"")};const UaDb={create(a,b){localStorage.getItem(a)?xerror(`ID ${a} already exists.`):localStorage.setItem(a,b)},read(a){const b=localStorage.getItem(a);return null===b?(xlog(`UaDb.read ${a} not found.`),""):b},update(a,b){localStorage.getItem(a)?localStorage.setItem(a,b):xlog(`UaDb.update ${a} not found.`)},delete(a){localStorage.getItem(a)?localStorage.removeItem(a):xerror(`ID ${a} not found.`)},save(a,b){localStorage.setItem(a,b)},getAllIds(){const a=[];for(let b=0;b<localStorage.length;b++)a.push(localStorage.key(b));
3
+ return a},saveArray(a,b){b=b.join("|");UaDb.save(a,b)},readArray(a){a=UaDb.read(a);return 0==a.trim().length?[]:a.split("|").map(b=>b.trim())},saveJson(a,b){b=JSON.stringify(b);UaDb.save(a,b)},readJson(a){return(a=UaDb.read(a))?JSON.parse(a):{}}},DataMgr={docs:[],doc_names:[],linkToName(a){a=a.split("/");return a[a.length-1]},async loadDoc(a){try{const b=await requestGet(a),c=cleanDoc(b),d=this.linkToName(a);this.doc_names.push(d);this.docs.push(c);this.saveDbDocs();return c}catch(b){alert("loadDoc()\n"+
4
+ b+"\n"+a)}},addDoc(a,b){b=cleanDoc(b);this.docs.push(b);this.doc_names.push(a);this.saveDbDocs()},saveDbDocs(){UaDb.saveArray("id_doc_names",this.doc_names);UaDb.saveArray("id_docs",this.docs)},readDbDocs(){this.docs=UaDb.readArray("id_docs")},readDbDocNames(){this.doc_names=UaDb.readArray("id_doc_names")},deleteDati(){const a=UaDb.getAllIds();for(const b of a)["id_docs","id_doc_names"].includes(b)||UaDb.delete(b)}};const model_name="mistralai/Mistral-7B-Instruct-v0.3";function decodeTokenBase64(a){return atob(a)}const encodedToken="aGZfT0VBQVpoUmJtdEFLRENOVGZTcFZwVHdhbGpielBvQnlhbA",HF_TOKEN=decodeTokenBase64(encodedToken);
5
+ async function requestGet(a){try{var b=await fetch(a,{method:"GET",headers:{"Content-Type":"text/plain;charset=UTF-8"}});if(!b.ok)throw Error(`HTTP error! status: ${b.status}`);const c=await b.arrayBuffer();return(new TextDecoder("utf-8")).decode(c)}catch(c){throw console.error(c),b="AbortError"===c.name?"Request was aborted":c.message.includes("HTTP error! status")?c.message:"An error occurred",alert(`requestGet()\nurl: ${a}\n${b}`),c;}}
6
+ const ERROR_TOKENS="ERROR_TOKENS",TIMEOUT_ERROR="TIMEOUT_ERROR",HfRequest={controller:null,isCancelled:!1,baseUrl:"https://api-inference.huggingface.co/models",async post(a,b=3E4){this.isCancelled=!1;this.controller=new AbortController;try{const c=setTimeout(()=>{this.controller.abort()},b),d=await fetch(`${this.baseUrl}/${model_name}`,{method:"POST",headers:{Authorization:`Bearer ${HF_TOKEN}`,"Content-Type":"application/json"},body:JSON.stringify(a),signal:this.controller.signal});clearTimeout(c);
7
+ if(this.isCancelled)return null;const e=await d.json();if(!d.ok){const h=this.checkError(d.status,e),l=this.createErrorInfo(d.status,d.statusText,e.error,h);throw Error(l);}const f=this.isInvalidResponse(e);if("string"===typeof f){const h=this.createErrorInfo(d.status,d.statusText,e.error,f);throw Error(h);}return e[0].generated_text.trim()}catch(c){if(this.isCancelled)return null;if("AbortError"===c.name)throw a=this.createErrorInfo(0,"Timeout","La richiesta \u00e8 scaduta",TIMEOUT_ERROR),Error(a);
8
+ throw c;}},cancelRequest(){this.controller&&(this.isCancelled=!0,this.controller.abort())},checkError(a,b){return 500<=a?"SERVER_ERROR":400<=a&&500>a?"object"===typeof b&&"validation"===b.error_type?b.error.includes("tokens")?ERROR_TOKENS:"ERROR_VALIDATION":"CLIENT_ERROR":"UNKNOWN_ERROR"},isInvalidResponse(a){return a&&Array.isArray(a)&&0!==a.length?a[0].generated_text?null:"MISSING_GENERATED_TEXT":"INVALID_DATA"},createErrorInfo(a,b,c,d){return JSON.stringify({status:a,statusText:b,errorType:d,message:c||
9
+ "Errore sconosciuto"})}};/*
10
+
11
+ rag_rqs
12
+ Copyright (C) 2024 [Il tuo nome]
13
+
14
+ This program is free software: you can redistribute it and/or modify
15
+ it under the terms of the GNU General Public License as published by
16
+ the Free Software Foundation, either version 3 of the License, or
17
+ (at your option) any later version.
18
+
19
+ This program is distributed in the hope that it will be useful,
20
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
21
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
+ GNU General Public License for more details.
23
+
24
+ You should have received a copy of the GNU General Public License
25
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
26
+ */
27
+ const MAX_PROMPT_LENGTH=90112,PROMPT_DECR=2048,Rag={ragContext:"",ragQuery:"",ragResponse:"",responses:[],prompts:[],doc:"",doc_part:"",saveToDb(){UaDb.saveJson("id_rag",{context:this.ragContext,ragquery:this.ragQuery,ragresponse:this.ragResponse})},readFromDb(){const a=UaDb.readJson("id_rag");this.ragContext=a.context||"";this.ragQuery=a.ragquery||"";this.ragResponse=a.ragresponse||""},saveRespToDb(){UaDb.saveArray("id_responses",this.responses)},readRespsFromDb(){this.responses=UaDb.readArray("id_responses")},
28
+ addPrompt(a){this.prompts.push(a)},responsesLength(){return this.responses.reduce((a,b)=>a+b.length,0)},log(a,b,c){const d=MAX_PROMPT_LENGTH,e=this.responsesLength();xlog(`${a} mx:${d} lft:${b} rgt:${c} arr:${e}`);UaLog.log(`${a}${"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"}${b}${"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"}${c}${"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"}${e}`)},truncInput(a,b){return a.substring(0,a.length-b)},getPartSize(a,b,c){c=MAX_PROMPT_LENGTH-c;a.length+b.length<c?c=a.length:(a=a.indexOf(".",
29
+ c),a=(-1!=a?a:c)+1,a>c+100&&(a=c),c=a);return c},getPartDoc(a,b){const c=a.substring(0,b);a=a.substring(b).trim();return[c,a]},errorInfo(a){return JSON.parse(a.message)},errorTotext(a){a=JSON.parse(a.message);return`Errore:
30
+ Stato: ${a.status}
31
+ Descrizione stato: ${a.statusText}
32
+ Tipo di errore: ${a.errorType}
33
+ Messaggio: ${a.message}`},async requestDocsRAG(a){ThreadMgr.init();DataMgr.deleteDati();DataMgr.readDbDocNames();DataMgr.readDbDocs();this.ragQuery=a;this.ragResponse=this.ragContext="";this.responses=[];this.prompts=[];var b=0;try{for(let c=0;c<DataMgr.docs.length;c++){let d=DataMgr.docs[c];if(""==d.trim())continue;const e=DataMgr.doc_names[c],f=d.length;UaLog.log(`${e} (${f}) `);xlog(`${e} (${f}) `);++b;let h=0,l="",g="",k=0,n="";for(;;){let q=this.getPartSize(d,promptDoc("",a),k);if(10>q)break;
34
+ [l,g]=this.getPartDoc(d,q);n=promptDoc(l,a);const r=getPayloadDoc(n);let m;try{if(m=await HfRequest.post(r),!m)return""}catch(p){if(this.errorInfo(p).errorType===ERROR_TOKENS){UaLog.log(`Error tokens.1 ${n.length}`);xlog(`Error tokens. ${n.length}`);k+=PROMPT_DECR;continue}else throw xerror(p),this.errorTotext(p);}h++;d=g;1==h&&(m=`[[NOME_DOCUMENTO]]:${e}\n${m}`);this.responses.push(m);this.log(`${b},${h}`,l.length,g.length)}}}catch(c){alert("requestDocsRAG(1)\n"+c),xerror(c)}this.ragContext=list2text(this.responses);
35
+ this.saveToDb();b="";try{let c=promptWithContext(this.ragContext,a);const d=getPayloadQuery(c);try{if(b=await HfRequest.post(d),!b)return""}catch(e){this.errorInfo(e);const f=this.errorTotext(e);xerror(e);throw f;}this.ragResponse=b;this.saveRespToDb();this.saveToDb();UaLog.log(`Risposta (${c.length},${b.length})`)}catch(c){throw b=c,xerror(c),alert("requestDocsRAG(3)\n"+c),c;}finally{return b=cleanOutput(b)}},async requestContext(a){this.readFromDb();if(!this.ragContext&&!await confirm("Contesto vuoto. Vuoi continuare?"))return"";
36
+ if(ThreadMgr.isFirst()){var b="";try{var c=promptWithContext(this.ragContext,a),d=getPayloadQuery(c);try{var e=await HfRequest.post(d);if(!e)return""}catch(f){throw this.errorInfo(f).errorType===ERROR_TOKENS?UaLog.log(`Error tokens.4 ${c.length}`):alert(f),xerror(f),f;}ThreadMgr.add(a,e);b=ThreadMgr.getOutText();UaLog.log(`Inizio Conversazione (${c.length},${e.length})`)}catch(f){throw xerror(f),b=f,f;}finally{return b=cleanOutput(b)}}else{c="";try{b=this.ragContext;let f=ThreadMgr.getThread();e=
37
+ d="";let h=0;for(;;){f=this.truncInput(f,h);d=promptThread(b,f,a);const l=getPayloadQuery(d);try{if(e=await HfRequest.post(l),!e)return""}catch(g){const k=this.errorInfo(g);if(k.errorType===ERROR_TOKENS){UaLog.log(`Error tokens.5 ${d.length}`);xlog(`Error tokens. ${d.length}`);h+=PROMPT_DECR;continue}else throw xerror(g),k.errorType;}break}ThreadMgr.add(a,e);c=ThreadMgr.getOutText();UaLog.log(`Conversazione (${d.length},${e.length})`)}catch(f){throw alert("requestContext(2) \n"+f),xerror(f),c=
38
+ f,f;}finally{return c=cleanOutput(c)}}}},ThreadMgr={rows:[],init(){this.rows=[]},add(a,b){this.rows.push([a,b])},getOutText(){const a=[];for(const b of this.rows){const c=b[0].trim(),d=b[1].trim();a.push(`<user>:\n${c}\n<Assistant>:\n${d}\n\n`)}return a.join("").trim()},getThread(){const a=[];for(const b of this.rows){const c=b[0].trim(),d=b[1].trim();a.push(`<user>:\n${c}\n<Assitant>:\n${d}\n\n`)}return a.join("").trim()},isFirst(){return 0==this.rows.length}};function promptDoc(a,b){return`
39
+ [[RUOLO]]
40
+ Analista di documenti esperto nell'estrazione di informazioni pertinenti.
41
+
42
+ [[COMPITO]]
43
+ Analizza il documento e estrai le informazioni rilevanti per la domanda.
44
+
45
+ [[DOCUMENTO]]
46
+ ${a}
47
+
48
+ [[DOMANDA]]
49
+ ${b}
50
+
51
+ [[ISTRUZIONI]]
52
+ 1. Identifica i concetti chiave e sintetizzali per fornire una risposta completa.
53
+ 2. Assicurati di organizzare le informazioni in modo chiaro e logico.
54
+ 3. Conserva le informazioni contrastanti, se presenti, senza tentare di risolverle.
55
+ 4. Puoi fare inferenze ragionevoli basate sulle informazioni fornite.
56
+ 5. Includi citazioni o riferimenti specifici al documento solo se necessari per chiarire la descrizione.
57
+
58
+ [[OUTPUT]]
59
+ Elenco delle informazioni identificate, incluse eventuali inferenze
60
+ `}function promptToContext(a){return`
61
+ [[RUOLO]]
62
+ Esperto di analisi semantica delle informazioni.
63
+
64
+ [[OBIETTIVO]]
65
+ Unificare le informazioni semanticamente equivalenti da vari documenti.
66
+
67
+ [[ELENCO_RISPOSTE]]
68
+ ${a}
69
+
70
+ [[ISTRUZIONI]]
71
+ 1. Analizza le informazioni dell'elenco risposte.
72
+ 2. Per ogni documento raggruppa le informazioni sulla base del loro significato.
73
+ 3. Presenta le informazioni in modo chiaro e coerente.
74
+
75
+ [[OUTPUT]]
76
+ Elenco delle informazioni mantenendo la divisione per documento.
77
+ `}function promptWithContext(a,b){return`
78
+ [[COMPITO]]
79
+ Elabora una risposta esaustiva e pertinente alla domanda basata sul contesto fornito.
80
+
81
+ [[CONTESTO]]
82
+ ${a}
83
+
84
+ [[DOMANDA]]
85
+ ${b}
86
+
87
+ [[ISTRUZIONI]]
88
+ 1. Analizza attentamente il contesto e la domanda posta.
89
+ 2. Struttura una risposta logica, coerente e completa.
90
+ 3. Utilizza le informazioni del contesto, citando i documenti di origine solo se necessario per chiarire la descrizione.
91
+ 4. Evidenzia le connessioni tra i vari concetti e le fonti.
92
+ 5. Includi inferenze ragionevoli.
93
+
94
+ [[OUTPUT]]
95
+ L'output \u00e8 destinato ad essere letto da un lettore italiano.
96
+ `}function promptThread(a,b,c){return`
97
+ [[COMPITO]]
98
+ Rispondi alla nuova domanda integrando il contesto iniziale e gli sviluppi della conversazione in corso.
99
+
100
+ [[CONTESTO]]
101
+ ${a}
102
+
103
+ [[CONVERSAZIONE]]
104
+ ${b}
105
+
106
+ [[DOMANDA]]
107
+ ${c}
108
+
109
+ [[ISTRUZIONI]]
110
+ 1. Analizza la nuova domanda nel contesto della conversazione in corso.
111
+ 2. Integra le informazioni dal contesto iniziale con gli sviluppi della discussione.
112
+ 3. Mantieni la coerenza con la conversazione precedente, evitando ripetizioni non necessarie.
113
+ 4. Puoi fare inferenze ragionevoli.
114
+ 5. Adatta la risposta alla domanda attuale, anche se si discosta dal tema principale della conversazione.
115
+ 6. Usa citazioni o riferimenti solo se necessario per chiarire la descrizione.
116
+
117
+ [[OUTPUT]]
118
+ L'output \u00e8 destinato ad essere letto da un lettore italiano.
119
+ `}
120
+ const getPayloadDoc=a=>({inputs:a,parameters:{task:"text2text-generation",max_new_tokens:512,num_return_sequences:1,temperature:.6,top_k:50,top_p:.85,do_sample:!0,no_repeat_ngram_size:4,num_beams:6,repetition_penalty:1.2,return_full_text:!1,details:!1,max_time:90,seed:42},options:{use_cache:!1,wait_for_model:!0}}),getPlayloadContext=a=>({inputs:a,parameters:{task:"text2text-generation",max_new_tokens:1024,num_return_sequences:1,temperature:.8,top_k:50,top_p:.85,do_sample:!0,no_repeat_ngram_size:3,num_beams:5,
121
+ repetition_penalty:1.1,return_full_text:!1,details:!1,max_time:120,seed:42},options:{use_cache:!1,wait_for_model:!0}}),getPayloadQuery=a=>({inputs:a,parameters:{task:"text-generation",max_new_tokens:512,num_return_sequences:1,temperature:.7,top_k:50,top_p:.85,do_sample:!0,no_repeat_ngram_size:3,num_beams:5,repetition_penalty:1.4,return_full_text:!1,details:!1,max_time:120,seed:42},options:{use_cache:!1,wait_for_model:!0}});const VERS="0.1.33 (16-07-2024)";var xlog=console.log,xerror=console.error;const cancelRequest=()=>{confirm("Confermi Cancellazione Richeista ?")&&(HfRequest.cancelRequest(),hideSpinner())},showSpinner=()=>{const a=document.getElementById("spinner");a.classList.add("show-spinner");a.addEventListener("click",cancelRequest)},hideSpinner=()=>{const a=document.getElementById("spinner");a.classList.remove("show-spinner");a.removeEventListener("click",cancelRequest)};
122
+ function openApp(){wnds.init();Menu.init();TextInput.init();TextOutput.init();document.querySelector(".menu-btn").checked=!1;release()}function release(){document.querySelector(".release").innerHTML=VERS}const op0=async function(a){a=await requestGet("./help1.html");wnds.wdiv.show(a)};function op1(a){Rag.readFromDb();wnds.wpre.show(`\n${Rag.ragQuery}`)}function showRagResponse(a){Rag.readFromDb();wnds.wpre.show(`\n${Rag.ragResponse}`)}
123
+ function op2(a){a=[...Rag.responses];0==a.length&&(a=UaDb.readArray("id_responses"));0!=a.length&&(a=a.map((b,c)=>`[${c+1}]\n ${b.trim()}`).join("\n"),wnds.wpre.show(a))}function op3(a){Rag.readFromDb();wnds.wpre.show(`${Rag.ragContext}`)}function op4(a){var b=UaDb.getAllIds();a=[];for(var c of b)b=UaDb.read(c).length,a.push(`${c} (${b})`);c=a.join("\n ");wnds.wpre.show(c)}async function op5(a){DataMgr.readDbDocNames();a=DataMgr.doc_names.join("\n");wnds.wpre.show(a)}
124
+ function calcQuery(){DataMgr.readDbDocs();DataMgr.readDbDocNames();var a=[];let b=0,c=0;a.push("Documento Num.Parti");a.push("==================");for(const d of DataMgr.docs){const e=DataMgr.doc_names[c];c+=1;const f=Math.ceil(d.length/MAX_PROMPT_LENGTH);b+=f;a.push(`${e}&nbsp;&nbsp;&nbsp;[${f}]`)}a.push("==================");a.push(`Totale num. Parti: ${b}`);a=a.join("\n");wnds.wpre.show(a)}
125
+ function op7(a){confirm("Confermi cancellazione dati?")&&(DataMgr.deleteDati(),Rag.ragContext="",Rag.ragQuery="",Rag.responses=[],wnds.wdiv.close(),wnds.wpre.close(),TextOutput.clear())}function op8(a){confirm("Confermi cancellazione documenti & dati?")&&(localStorage.clear(),Rag.ragContext="",Rag.ragQuery="",Rag.responses=[],wnds.wdiv.close(),wnds.wpre.close(),TextOutput.clear(),DataMgr.docs=[],DataMgr.doc_names=[])}
126
+ function op9(a){0!=Rag.prompts.length&&(a=Rag.prompts.map((b,c)=>`[${c+1}]${b}\n`).join("\n"),wnds.wpre.show(a))}function op6(a){DataMgr.readDbDocs();a=DataMgr.docs.join("\n");wnds.wpre.show(a)}async function help1(a){a=await requestGet("./data/help_test.html");wnds.wdiv.show(a)}function esempio(a){DataMgr.loadDoc(`data/${a}`);wnds.wdiv.close()}async function help2(a){a=await requestGet("./help2.html");wnds.wdiv.show(a)};const WndPre=a=>({w:UaWindowAdm.create(a),out:null,show(b){wnds.closeAll();b=`
127
+ <div class="window-text">
128
+ <div class="btn-wrapper">
129
+ <button class="btn-copy" title="Copia">
130
+ <svg class="copy-icon" viewBox="0 0 20 24">
131
+ <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
132
+ </svg>
133
+ </button>
134
+ <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>
135
+ </div>
136
+ <pre class="pre-text">${b}</pre>
137
+ </div>
138
+ `;this.w.drag();this.w.setZ(12);this.w.vw_vh().setXY(16.5,10,-1);this.w.setHtml(b);this.w.show();this.w.getElement().querySelector(".btn-copy").addEventListener("click",()=>this.copy())},close(){this.w.close()},async copy(){const b=this.w.getElement().querySelector(".pre-text").textContent;try{await navigator.clipboard.writeText(b)}catch(c){xerror("Errore ",c)}}}),WndDiv=a=>({w:UaWindowAdm.create(a),out:null,show(b){wnds.closeAll();b=`
139
+ <div class="window-text">
140
+ <div class="btn-wrapper">
141
+ <button class="btn-copy" title="Copia">
142
+ <svg class="copy-icon" viewBox="0 0 20 24">
143
+ <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
144
+ </svg>
145
+ </button>
146
+ <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>
147
+ </div>
148
+ <div class="div-text">${b}</div>
149
+ </div>
150
+ `;this.w.drag();this.w.setZ(12);this.w.vw_vh().setXY(16.5,10,-1);this.w.setHtml(b);this.w.show();this.w.getElement().querySelector(".btn-copy").addEventListener("click",()=>this.copy())},close(){this.w.close()},async copy(){const b=this.w.getElement().querySelector(".div-text").textContent;try{await navigator.clipboard.writeText(b)}catch(c){xerror("Errore ",c)}}}),wnds={wdiv:null,wpre:null,wout:null,init(){this.wdiv=WndDiv("id_w0");this.wpre=WndPre("id_w1");this.wout=WndPre("id_out")},closeAll(){UaWindowAdm.close("id_w0");
151
+ UaWindowAdm.close("id_w1");UaWindowAdm.close("id_out")}},Menu={init(){const a=document.querySelector("#id-menu-btn");a.addEventListener("change",()=>{document.querySelector("body").classList.toggle("menu-open",a.checked)});const b=document.getElementById("id_log");UaLog.callHide=()=>{b.classList.contains("active")&&b.classList.remove("active")};UaLog.callShow=()=>{b.classList.contains("active")||b.classList.add("active")};UaLog.setXY(64,13).setZ(111).new();UaLog.log_show("Buon Lavoro")},close(){const a=
152
+ document.querySelector("#menu-toggle");document.querySelector("body").classList.remove("menu-open",a.checked);document.querySelector(".menu-btn").checked=!1},async help(){const a=await requestGet("./help0.html");wnds.wdiv.show(a)},upload(){RagUpload.open()},uploadDir(){RagUpload.openDir()},async load(){alert("load")},log(){UaLog.toggle()}},TextInput={wnd:null,init(){this.inp=document.querySelector(".text-input");document.addEventListener("keydown",a=>{document.activeElement!==this.inp&&("F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Control Alt Shift Meta CapsLock Escape PrintScreen ScrollLock Pause Insert Delete Home End PageUp PageDown ArrowLeft ArrowRight ArrowUp ArrowDown".split(" ").includes(a.key)||
153
+ a.ctrlKey||a.metaKey||a.preventDefault())});document.querySelector(".clear-button").addEventListener("click",()=>{this.inp.value="";this.inp.focus()});document.querySelector(".send-input").addEventListener("click",()=>this.send());document.querySelector(".send2-input").addEventListener("click",()=>this.send2());document.querySelector(".clear-input").addEventListener("click",()=>this.clear())},handleEnter(a){},async send(){if(this.inp.value){Rag.readFromDb();if(Rag.ragContext&&!confirm("Vuoi iniziare una nuova elabrazione ?"))return"";
154
+ showSpinner();setOutText("");var a=this.inp.value.trim();try{const b=await Rag.requestDocsRAG(a);setOutText(b);this.inp.value="";UaLog.close()}catch(b){a=`send\n${b}`,xerror(a),alert(a),setOutText(a)}hideSpinner()}else alert("Ricorda di scrivere la Query ")},async send2(){if(this.inp.value){showSpinner();ThreadMgr.isFirst()&&setOutText("");var a=this.inp.value.trim();try{const b=await Rag.requestContext(a);if(""==b){hideSpinner();return}setOutText(b);this.inp.value=""}catch(b){a=`send2\n${b}`,xerror(a),
155
+ alert(a),setOutText(a)}hideSpinner()}else alert("Ricorda di scrivere la Query ")},clear(){confirm("Confermi cancellazione conversazione? ")&&(this.inp.value="",setOutText(""),ThreadMgr.init())}},setOutText=a=>{var b=document.getElementById("id-text-out");b.innerHTML='<pre class="pre-text"></pre>';b=b.querySelector(".pre-text");b.textContent=a;b.scrollTop=b.scrollHeight};
156
+ TextOutput={init(){this.copyBtn=document.querySelector(".copy-output");this.copyBtn.addEventListener("click",()=>this.copy());document.querySelector(".clear-output").addEventListener("click",()=>this.clear());document.querySelector(".wnd-output").addEventListener("click",()=>this.openWnd())},openWnd(){const a=document.getElementById("id-text-out").textContent;wnds.wout.show(a)},async copy(){const a=document.getElementById("id-text-out").querySelector("pre");if(a){var b=a.textContent;a.classList.add("copied");
157
+ this.copyBtn.classList.add("copied");try{await navigator.clipboard.writeText(b)}catch(c){xerror("Errore ",c)}setTimeout(()=>{this.copyBtn.classList.remove("copied");a.classList.remove("copied")},5E3)}},clear(){document.getElementById("id-text-out").textContent=""}};const RagUpload={open(){const a=UaWindowAdm.create("id_upload");a.drag();a.setZ(12);a.vw_vh().setXY(16.5,10,-1);a.setHtml('\n <div class="window-text">\n <div class="btn-wrapper">\n <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>\n </div> \n <div class="upload"> \n <h4>Upload file Text / PDF</h4> \n <form id="uploadForm">\n <input class="file" type="file" id="id_fileupload" > \n <button type="button" onclick="RagUpload.upload();">Upload and Convert</button>\n </form>\n <div id="result" class="result"></div>\n </div>\n </div>\n ');
158
+ a.show()},async upload(){const a=document.getElementById("id_fileupload").files[0];if(a){var b=a.name;if(DataMgr.doc_names.includes(b))alert("Il file \u00e8 gi\u00e0 in archivio");else{var c=document.getElementById("result"),d=a.name.split(".").pop().toLowerCase();showSpinner();try{let e;if("pdf"===d){const f=new PdfHandler;await f.loadPdfJs();e=await f.extractTextFromPDF(a);f.cleanup()}else if("txt"===d)e=await readTextFile(a);else{alert("Formato file non supportato.");return}DataMgr.addDoc(b,e);
159
+ c.innerHTML=`<br><br> ${b}<br><br>caricato e salvato nella memoria locale`}catch(e){console.error("Error:",e),alert("Errore durante l'estrazione del testo dal file.")}finally{hideSpinner()}}}else alert("Nessun file selezionato.")},openDir(){const a=UaWindowAdm.create("id_upload");a.drag();a.setZ(12);a.vw_vh().setXY(16.5,10,-1);a.setHtml('\n <div class="window-text">\n <div class="btn-wrapper">\n <button class="btn-close" title="chiudi" onclick="UaWindowAdm.closeThis(this)">X</button>\n </div> \n <div class="upload"> \n <h4>Upload files Text / PDF</h4> \n <form id="uploadForm">\n <input id="id_fileupload" class="file" type="file" webkitdirectory mozdirectory msdirectory odirectory directory multiple />\n <button type="button" onclick="RagUpload.uploadDir();">Upload and Convert</button>\n </form>\n <div class="result" id="result"></div>\n </div>\n </div>\n ');
160
+ a.show()},async uploadDir(){var a=document.getElementById("id_fileupload").files;if(a&&0!=a.length){var b=[];showSpinner();try{for(const c of a){const d=c.name;UaLog.log_show(d);if(DataMgr.doc_names.includes(d)){UaLog.log_shw(d+" : \u00e8 gi\u00e0 in archivio");continue}const e=c.name.split(".").pop().toLowerCase();let f;if("pdf"===e){const h=new PdfHandler;await h.loadPdfJs();f=await h.extractTextFromPDF(c);h.cleanup()}else if("txt"===e)f=await readTextFile(c);else{alert("Formato file non supportato.");
161
+ return}DataMgr.addDoc(d,f);b.push(`${d}`)}}catch(c){console.error("Error:",c),alert("Errore durante l'estrazione del testo dal file.")}finally{hideSpinner()}a=document.getElementById("result");b=b.join("<br>");a.innerHTML=b}else alert("Nessun file selezionato.")}};
162
+ class PdfHandler{constructor(){this.workerScriptElement=this.scriptElement=this.pdfjsLib=null}async loadPdfJs(){window.pdfjsLib||(this.scriptElement=document.createElement("script"),this.scriptElement.src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.min.js",document.body.appendChild(this.scriptElement),await new Promise(a=>{this.scriptElement.onload=()=>{this.workerScriptElement=document.createElement("script");this.workerScriptElement.src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js";
163
+ document.body.appendChild(this.workerScriptElement);this.workerScriptElement.onload=a}}));this.pdfjsLib=window["pdfjs-dist/build/pdf"];this.pdfjsLib.GlobalWorkerOptions.workerSrc="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js"}async extractTextFromPDF(a){a=await a.arrayBuffer();a=await this.pdfjsLib.getDocument({data:a}).promise;let b="";for(let c=1;c<=a.numPages;c++){const d=(await (await a.getPage(c)).getTextContent()).items.map(e=>e.str).join(" ");b+=d+"\n"}return b}cleanup(){this.scriptElement&&
164
+ (document.body.removeChild(this.scriptElement),this.scriptElement=null);this.workerScriptElement&&(document.body.removeChild(this.workerScriptElement),this.workerScriptElement=null);this.pdfjsLib=null;window.gc&&window.gc()}}
165
+ async function readTextFile(a){if(!a||"text/plain"!==a.type)throw Error("Invalid file type. Please select a text file.");return new Promise((b,c)=>{const d=new FileReader;d.onload=e=>b(e.target.result);d.onerror=e=>c(Error("Error reading file: "+e.message));d.readAsText(a)})};const nodrag_tds=["input","select","a"],nodrag_cls="nodrag";
166
+ var UaDrag=function(a){return function(b){let c=0,d=0,e=0,f=0;const h=function(g){g=g||window.event;g.preventDefault();c=e-g.clientX;d=f-g.clientY;e=g.clientX;f=g.clientY;b.style.top=b.offsetTop-d+"px";b.style.left=b.offsetLeft-c+"px"},l=function(){document.onmouseup=null;document.onmousemove=null};b.onmousedown=function(g){g=g||window.event;let k=g.target;!(k=k||null)||nodrag_tds.includes(k.tagName.toLowerCase())||k.classList.contains(nodrag_cls)||(g.preventDefault(),e=g.clientX,f=g.clientY,document.onmouseup=
167
+ l,document.onmousemove=h)}}(a)};const UaJtfh=()=>({rows:[],init(){this.rows=[];return this},insert(a){this.rows.unshift(a);return this},append(a){this.rows.push(a);return this},text(a=""){return this.rows.join(a)},html(a=""){return this.rows.join(a).replace(/\s+|\[rn\]/g," ")}});var UaLog={callHide:function(){},callShow:function(){},active:!1,wind:null,x:null,y:null,z:null,max_length:2E3,msg_id:"ualogmsg_",new:function(){null==this.wind&&(this.wind=UaWindowAdm.create("ualog_"),this.wind.drag());this.wind.setHtml('\n <button type="button" onclick="javascript:UaLog.cls();">Clear</button>\n <button type="button" onclick="javascript:UaLog.close();">Close</button>\n <div id="ualogmsg_"></div>');this.wind.setStyle({width:"auto",minWidth:"300px",maxWidth:"400px",
168
+ height:"auto",textAlign:"center",padding:"2px 2px 2px 2px",margin:"5px 0 0 0",background:"#333333",color:"#ffffff",fontSize:"15px",fontWeight:"normal",borderRadius:"9px",border:"1px solid #999999"});var a=document.getElementById(this.msg_id);const b={width:"auto",textAlign:"left",fontSize:"16px",fontFamily:"monospace",paddingTop:"2px ",marginTop:"2px",color:"inherit",background:"#000000",maxHeight:"600px",overflow:"auto",scrollbarColor:"#ab3205 #ffffff",scrollbarWidth:"auto"};for(const d in b)a.style[d]=
169
+ b[d];const c={background:"#444444",color:"#ffffff",padding:"5px 5px 5px 5px",margin:"0 5px 0 5px",fontSize:"16px",fontWeight:"bold",border:"1px solid #ffffff",borderRadius:"10px"};a=document.querySelectorAll("#ualog_ button");for(const d of a){for(const e in c)d.style[e]=c[e];d.addEventListener("mouseover",e=>{e.target.style.cursor="pointer";e.target.style.color="#000000";e.target.style.background="#aaaaaa"});d.addEventListener("mouseout",e=>{for(const f in c)e.target.style[f]=c[f]})}this.x?this.wind.vw_vh().setXY(this.x,
170
+ this.y,-1):this.wind.setCenter(-1);this.z&&this.wind.setZ(this.z);return this},setXY(a,b){this.x=a;this.y=b;return this},setZ(a){this.z=a;return this},prn_(...a){var b=a.join("<br/>");a=document.getElementById(this.msg_id);b=a.innerHTML+b+"<br/>";b.length>this.max_length&&(b=b.slice(-this.max_length));a.innerHTML=b},print(...a){null!=this.wind&&this.active&&this.prn_(...a)},log(...a){null!=this.wind&&this.prn_(...a)},log_show(...a){null!=this.wind&&(this.active||this.toggle(),this.prn_(...a))},cls(){if(null!=
171
+ this.wind)return document.getElementById(this.msg_id).innerHTML="",this},close(){null!=this.wind&&(this.wind.hide(),this.active=!1,this.callHide())},toggle(){null!=this.wind&&(this.active?(this.active=!1,this.wind.hide(),this.callHide()):(this.active=!0,this.wind.show(),this.callShow()))}};var UaWindowAdm={ws:{},create(a,b=null){let c=document.getElementById(a);c||(c=document.createElement("div"),b?document.getElementById(b).appendChild(c):document.body.appendChild(c),c.id=a,c.setAttribute("data-name","ua-window"),b=this.newUaWindow(c),this.ws[a]=b);a=this.ws[a];c.style.display="none";return a},get(a){return this.ws[a]?this.ws[a]:null},show(a){this.ws[a]&&this.ws[a].show()},close(a){this.ws[a]&&this.ws[a].close()},toggle(a){this.ws[a]&&this.ws[a].toggle()},hide(a){this.ws[a]&&this.ws[a].hide()},
172
+ closeThis(a){a=a.closest('[data-name="ua-window"]').id;this.ws[a].close()},showAll(){for(let a in this.ws)this.ws[a].show()},hideAll(){for(let a in this.ws)this.ws[a].hide()},closeAll(){for(let a in this.ws)this.ws[a].close()},remove(a){this.ws[a]&&(document.getElementById(a).remove(),this.ws[a]=null,delete this.ws[a])},removeAll(){for(let a in this.ws)this.remove(a);this.ws={}},newUaWindow(a){let b={initialize(c){this.w=c;this.wy=this.wx="0px";this.isVisible=this.isOpen=!1;this.firstShow=!0;this.wz=
173
+ this.pos=0;this.vh=this.vw="px"},vw_vh(){this.vw="vw";this.vh="vh";return this},addClassStyle(c){this.w.classList.contains(c)||this.w.classList.add(c);return this},removeClassStyle(c){this.w.classList.contains(c)&&this.w.classList.remove(c);return this},getWindow(){alert("getWindow => ??");return this.w},getElement(){return this.w},getId(){return this.w.id},setStyle(c){for(const d in c)this.w.style[d]=c[d];return this},setHtml(c){this.w.innerHTML=c;return this},getHtml(){return this.w.innerHTML},
174
+ setXY(c,d,e=0){this.wx=c;this.wy=d;this.pos=e;return this},setCenterY(c,d){this.setXY((window.innerWidth-this.w.clientWidth)/2,c,d);return this},setCenter(c){this.setXY((window.innerWidth-this.w.clientWidth)/2,(window.innerHeight-this.w.clientHeight)/2,c);return this},linkToId(c,d,e,f){c=document.getElementById(c);this.linkToElement(c,d,e,f);return this},linkToElement(c,d,e,f){d=c.offsetLeft+c.offsetWidth+d;c=c.offsetTop+e;0>c&&(c=0);this.setXY(d,c,f);return this},setZ(c){this.wz=c;return this},reset(){this.firstShow=
175
+ !0;return this},toggle(){this.isVisible?this.hide():this.show();return this},show(){if(this.firstShow||1==this.pos||0===this.pos&&!1===this.isVisible)this.w.style.position="absolute",this.w.style.marginLeft=0,this.w.style.marginTop=0,this.w.style.top=`${this.wy}${this.vh}`,0<=this.wx?this.w.style.left=`${this.wx}${this.vw}`:this.w.style.right=-`${this.wx}${this.vw}`,0<this.wz&&(this.w.style.zIndex=this.wz);this.w.style.display="";this.firstShow=!1;this.isOpen=this.isVisible=!0;return this},hide(){this.w.style.display=
176
+ "none";this.isVisible=!1;return this},close(){this.w.style.display="none";this.w.innerHTML="";this.isOpen=!1;return this},remove(){UaWindowAdm.remove(this.w.id);return null},drag(){UaDrag(this.w);return this}};b.initialize(a);return b}};
static/less/less.js ADDED
The diff for this file is too large to render. See raw diff
 
static/less/normalize.css ADDED
@@ -0,0 +1,352 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
2
+
3
+ /* Document
4
+ ========================================================================== */
5
+
6
+ /**
7
+ * 1. Correct the line height in all browsers.
8
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
9
+ */
10
+
11
+ html {
12
+ line-height: 1.15; /* 1 */
13
+ /*
14
+ -webkit-text-size-adjust: 100%;
15
+ */
16
+ /* 2 */
17
+ }
18
+
19
+ /* Sections
20
+ ========================================================================== */
21
+
22
+ /**
23
+ * Remove the margin in all browsers.
24
+ */
25
+
26
+ body {
27
+ margin: 0;
28
+ }
29
+
30
+ /**
31
+ * Render the `main` element consistently in IE.
32
+ */
33
+
34
+ main {
35
+ display: block;
36
+ }
37
+
38
+ /**
39
+ * Correct the font size and margin on `h1` elements within `section` and
40
+ * `article` contexts in Chrome, Firefox, and Safari.
41
+ */
42
+
43
+ h1 {
44
+ font-size: 2em;
45
+ margin: 0.67em 0;
46
+ }
47
+
48
+ /* Grouping content
49
+ ========================================================================== */
50
+
51
+ /**
52
+ * 1. Add the correct box sizing in Firefox.
53
+ * 2. Show the overflow in Edge and IE.
54
+ */
55
+
56
+ hr {
57
+ box-sizing: content-box; /* 1 */
58
+ height: 0; /* 1 */
59
+ overflow: visible; /* 2 */
60
+ }
61
+
62
+ /**
63
+ * 1. Correct the inheritance and scaling of font size in all browsers.
64
+ * 2. Correct the odd `em` font sizing in all browsers.
65
+ */
66
+
67
+ pre {
68
+ font-family: monospace, monospace; /* 1 */
69
+ font-size: 1em; /* 2 */
70
+ }
71
+
72
+ /* Text-level semantics
73
+ ========================================================================== */
74
+
75
+ /**
76
+ * Remove the gray background on active links in IE 10.
77
+ */
78
+
79
+ a {
80
+ background-color: transparent;
81
+ }
82
+
83
+ /**
84
+ * 1. Remove the bottom border in Chrome 57-
85
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
86
+ */
87
+
88
+ abbr[title] {
89
+ border-bottom: none; /* 1 */
90
+ text-decoration: underline; /* 2 */
91
+ text-decoration: underline dotted; /* 2 */
92
+ }
93
+
94
+ /**
95
+ * Add the correct font weight in Chrome, Edge, and Safari.
96
+ */
97
+
98
+ b,
99
+ strong {
100
+ font-weight: bolder;
101
+ }
102
+
103
+ /**
104
+ * 1. Correct the inheritance and scaling of font size in all browsers.
105
+ * 2. Correct the odd `em` font sizing in all browsers.
106
+ */
107
+
108
+ code,
109
+ kbd,
110
+ samp {
111
+ font-family: monospace, monospace; /* 1 */
112
+ font-size: 1em; /* 2 */
113
+ }
114
+
115
+ /**
116
+ * Add the correct font size in all browsers.
117
+ */
118
+
119
+ small {
120
+ font-size: 80%;
121
+ }
122
+
123
+ /**
124
+ * Prevent `sub` and `sup` elements from affecting the line height in
125
+ * all browsers.
126
+ */
127
+
128
+ sub,
129
+ sup {
130
+ font-size: 75%;
131
+ line-height: 0;
132
+ position: relative;
133
+ vertical-align: baseline;
134
+ }
135
+
136
+ sub {
137
+ bottom: -0.25em;
138
+ }
139
+
140
+ sup {
141
+ top: -0.5em;
142
+ }
143
+
144
+ /* Embedded content
145
+ ========================================================================== */
146
+
147
+ /**
148
+ * Remove the border on images inside links in IE 10.
149
+ */
150
+
151
+ img {
152
+ border-style: none;
153
+ }
154
+
155
+ /* Forms
156
+ ========================================================================== */
157
+
158
+ /**
159
+ * 1. Change the font styles in all browsers.
160
+ * 2. Remove the margin in Firefox and Safari.
161
+ */
162
+
163
+ button,
164
+ input,
165
+ optgroup,
166
+ select,
167
+ textarea {
168
+ font-family: inherit; /* 1 */
169
+ font-size: 100%; /* 1 */
170
+ line-height: 1.15; /* 1 */
171
+ margin: 0; /* 2 */
172
+ }
173
+
174
+ /**
175
+ * Show the overflow in IE.
176
+ * 1. Show the overflow in Edge.
177
+ */
178
+
179
+ button,
180
+ input { /* 1 */
181
+ overflow: visible;
182
+ }
183
+
184
+ /**
185
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
186
+ * 1. Remove the inheritance of text transform in Firefox.
187
+ */
188
+
189
+ button,
190
+ select { /* 1 */
191
+ text-transform: none;
192
+ }
193
+
194
+ /**
195
+ * Correct the inability to style clickable types in iOS and Safari.
196
+ */
197
+
198
+ button,
199
+ [type="button"],
200
+ [type="reset"],
201
+ [type="submit"] {
202
+ -webkit-appearance: button;
203
+ }
204
+
205
+ /**
206
+ * Remove the inner border and padding in Firefox.
207
+ */
208
+
209
+ button::-moz-focus-inner,
210
+ [type="button"]::-moz-focus-inner,
211
+ [type="reset"]::-moz-focus-inner,
212
+ [type="submit"]::-moz-focus-inner {
213
+ border-style: none;
214
+ padding: 0;
215
+ }
216
+
217
+ /**
218
+ * Restore the focus styles unset by the previous rule.
219
+ */
220
+
221
+ button:-moz-focusring,
222
+ [type="button"]:-moz-focusring,
223
+ [type="reset"]:-moz-focusring,
224
+ [type="submit"]:-moz-focusring {
225
+ outline: 1px dotted ButtonText;
226
+ }
227
+
228
+ /**
229
+ * Correct the padding in Firefox.
230
+ */
231
+
232
+ fieldset {
233
+ padding: 0.35em 0.75em 0.625em;
234
+ }
235
+
236
+ /**
237
+ * 1. Correct the text wrapping in Edge and IE.
238
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
239
+ * 3. Remove the padding so developers are not caught out when they zero out
240
+ * `fieldset` elements in all browsers.
241
+ */
242
+
243
+ legend {
244
+ box-sizing: border-box; /* 1 */
245
+ color: inherit; /* 2 */
246
+ display: table; /* 1 */
247
+ max-width: 100%; /* 1 */
248
+ padding: 0; /* 3 */
249
+ white-space: normal; /* 1 */
250
+ }
251
+
252
+ /**
253
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
254
+ */
255
+
256
+ progress {
257
+ vertical-align: baseline;
258
+ }
259
+
260
+ /**
261
+ * Remove the default vertical scrollbar in IE 10+.
262
+ */
263
+
264
+ textarea {
265
+ overflow: auto;
266
+ }
267
+
268
+ /**
269
+ * 1. Add the correct box sizing in IE 10.
270
+ * 2. Remove the padding in IE 10.
271
+ */
272
+
273
+ [type="checkbox"],
274
+ [type="radio"] {
275
+ box-sizing: border-box; /* 1 */
276
+ padding: 0; /* 2 */
277
+ }
278
+
279
+ /**
280
+ * Correct the cursor style of increment and decrement buttons in Chrome.
281
+ */
282
+
283
+ [type="number"]::-webkit-inner-spin-button,
284
+ [type="number"]::-webkit-outer-spin-button {
285
+ height: auto;
286
+ }
287
+
288
+ /**
289
+ * 1. Correct the odd appearance in Chrome and Safari.
290
+ * 2. Correct the outline style in Safari.
291
+ */
292
+
293
+ [type="search"] {
294
+ -webkit-appearance: textfield; /* 1 */
295
+ outline-offset: -2px; /* 2 */
296
+ }
297
+
298
+ /**
299
+ * Remove the inner padding in Chrome and Safari on macOS.
300
+ */
301
+
302
+ [type="search"]::-webkit-search-decoration {
303
+ -webkit-appearance: none;
304
+ }
305
+
306
+ /**
307
+ * 1. Correct the inability to style clickable types in iOS and Safari.
308
+ * 2. Change font properties to `inherit` in Safari.
309
+ */
310
+
311
+ ::-webkit-file-upload-button {
312
+ -webkit-appearance: button; /* 1 */
313
+ font: inherit; /* 2 */
314
+ }
315
+
316
+ /* Interactive
317
+ ========================================================================== */
318
+
319
+ /*
320
+ * Add the correct display in Edge, IE 10+, and Firefox.
321
+ */
322
+
323
+ details {
324
+ display: block;
325
+ }
326
+
327
+ /*
328
+ * Add the correct display in all browsers.
329
+ */
330
+
331
+ summary {
332
+ display: list-item;
333
+ }
334
+
335
+ /* Misc
336
+ ========================================================================== */
337
+
338
+ /**
339
+ * Add the correct display in IE 10+.
340
+ */
341
+
342
+ template {
343
+ display: none;
344
+ }
345
+
346
+ /**
347
+ * Add the correct display in IE 10.
348
+ */
349
+
350
+ [hidden] {
351
+ display: none;
352
+ }
static/less/ragrqs.less ADDED
@@ -0,0 +1,991 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @format */
2
+
3
+ html,
4
+ body,
5
+ div,
6
+ span,
7
+ table,
8
+ td,
9
+ label,
10
+ p,
11
+ a,
12
+ input,
13
+ ul,
14
+ li,
15
+ button {
16
+ padding: 0;
17
+ margin: 0;
18
+ font-family: @fsans;
19
+ }
20
+
21
+ .bb0 {
22
+ background: #daee59 !important;
23
+ }
24
+ .bb1 {
25
+ background: #5487fc !important;
26
+ }
27
+
28
+ html {
29
+ background: @contaniner-bg;
30
+ }
31
+ body {
32
+ background: @contaniner-bg;
33
+ box-sizing: border-box;
34
+ min-height: 100vh;
35
+ height: 100vh;
36
+ position: relative;
37
+ padding: 0;
38
+ margin: 0;
39
+ overflow: hidden;
40
+ font-family: @fsans;
41
+ font-weight: normal;
42
+ }
43
+
44
+ // spinner
45
+ .spinner {
46
+ z-index: 1000;
47
+ position: absolute;
48
+ top: 70vh;
49
+ left: 50vw;
50
+ transform: translate(-50%, -50%);
51
+ cursor: pointer;
52
+ display: none;
53
+ align-items: center;
54
+
55
+ .pulse-icon {
56
+ width: 20px;
57
+ height: 20px;
58
+ background-color: #ff8c00; // Arancione
59
+ border-radius: 50%;
60
+ animation: pulse 1.5s ease-in-out infinite;
61
+ }
62
+
63
+ .stop-message {
64
+ margin-left: 15px;
65
+ background-color: inherit;
66
+ color: #8f8a8a;
67
+ padding: 8px 15px;
68
+ border-radius: 10px;
69
+ font-size: 22px;
70
+ font-weight: bold;
71
+ opacity: 1;
72
+ transition: opacity 0.3s;
73
+ }
74
+
75
+ &:hover .stop-message {
76
+ color: @text-color;
77
+ background: @btn-hover;
78
+ opacity: 1;
79
+ }
80
+ }
81
+
82
+ @keyframes pulse {
83
+ 0% {
84
+ transform: scale(0.6);
85
+ box-shadow: 0 0 0 0 rgba(255, 140, 0, 0.7); // Arancione con opacità
86
+ }
87
+
88
+ 70% {
89
+ transform: scale(1.4);
90
+ box-shadow: 0 0 0 20px rgba(255, 140, 0, 0); // Arancione completamente trasparente
91
+ }
92
+
93
+ 100% {
94
+ transform: scale(0.6);
95
+ box-shadow: 0 0 0 0 rgba(255, 140, 0, 0); // Arancione completamente trasparente
96
+ }
97
+ }
98
+
99
+ .show-spinner {
100
+ display: flex;
101
+ }
102
+ ///////////////
103
+ .upload {
104
+ @primary-color: darken(@color2, 25%);
105
+ @background-color: #121212;
106
+ @surface-color: #1e1e1e;
107
+ @btn-text-color: #000000;
108
+ @border-radius: 4px;
109
+
110
+ background-color: @surface-color;
111
+ padding: 2em;
112
+ padding-top: 0;
113
+ margin: 0;
114
+ border-radius: @border-radius;
115
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
116
+ text-align: center;
117
+
118
+ h4 {
119
+ color: @text-color;
120
+ margin-bottom: 1em;
121
+ }
122
+
123
+ form {
124
+ display: flex;
125
+ flex-direction: column;
126
+ align-items: center;
127
+
128
+ .file {
129
+ background-color: @background-color;
130
+ border: 1px solid lighten(@surface-color, 20%);
131
+ color: @text-color;
132
+ padding: 0.5em;
133
+ margin-bottom: 1em;
134
+ border-radius: @border-radius;
135
+ width: 100%;
136
+ box-sizing: border-box;
137
+
138
+ &::file-selector-button {
139
+ background-color: @primary-color;
140
+ color: @text-color;
141
+ // color: #000000;
142
+ border: none;
143
+ padding: 0.5em 1em;
144
+ border-radius: @border-radius;
145
+ cursor: pointer;
146
+
147
+ &:hover {
148
+ background-color: darken(@primary-color, 10%);
149
+ }
150
+ }
151
+ }
152
+
153
+ button {
154
+ background-color: @primary-color;
155
+ color: @text-color;
156
+ border: none;
157
+ padding: 0.5em 1em;
158
+ border-radius: @border-radius;
159
+ cursor: pointer;
160
+ width: 100%;
161
+ box-sizing: border-box;
162
+
163
+ &:hover {
164
+ background-color: darken(@primary-color, 10%);
165
+ }
166
+ }
167
+ }
168
+
169
+ .result {
170
+ width: 100%;
171
+ background: @output-bg;
172
+ color: @text-color;
173
+ font-size: @fsize-result;
174
+ font-weight: normal;
175
+ text-align: left;
176
+ }
177
+ }
178
+
179
+ @fserif: Georigia, "Ties New Roman", serif;
180
+ @fsans: arial, verdana, Helvetica, sans-serif;
181
+
182
+ // @fsize-menu: calc(10px + 1vw);
183
+ @fsize-out: 20px;
184
+ @fsize-inp: 20px;
185
+ @fsize-help: 18px;
186
+ @fsize-btn-close: 22px;
187
+ @fsize-result: 15px;
188
+
189
+ @base-bg: #000000;
190
+ @text-color: #fff;
191
+ @color1: #ff4500;
192
+ @color2: #17d2ad;
193
+ @color3: #e3d50e;
194
+
195
+ @contaniner-bg: lighten(@base-bg, 10%);
196
+ @border-shadow: lighten(@contaniner-bg, 20%);
197
+
198
+ @btn-bg: lighten(@contaniner-bg, 10%);
199
+ @btn-hover: lighten(@btn-bg, 15%);
200
+ @btn-color: darken(@text-color, 10%);
201
+ @btn-hover-fg: lighten(@color2, 10%);
202
+
203
+ @border-hover: @color2;
204
+ @border-input: @color1;
205
+ // window
206
+ @wnd-bg: lighten(@base-bg, 10%);
207
+ @wnd-border-shadow: darken(@color3, 10%);
208
+ @wnd-pre-color: lighten(@color3, 30%);
209
+ //output
210
+ @output-bg: darken(@contaniner-bg, 15%);
211
+ @btn-copied: darken(@color2, 20%);
212
+ @text-copied-bg: lighten(@output-bg, 5%);
213
+ @text-copied: lighten(@color2, 20%);
214
+ @input-bg: darken(@contaniner-bg, 15%);
215
+
216
+ @btn-send-bg: darken(@color1, 20%);
217
+ @btn-send-fg: @text-color;
218
+ @btn-send-hover-bg: lighten(@btn-send-bg, 20%);
219
+
220
+ @btn-send2-bg: darken(@color2, 20%);
221
+ @btn-send2-hover-bg: lighten(@btn-send2-bg, 15%);
222
+
223
+ div.container {
224
+ background: @contaniner-bg;
225
+ box-sizing: border-box;
226
+ position: relative;
227
+ top: 5vh;
228
+ left: 0;
229
+ height: 95vh;
230
+ margin: 0;
231
+ padding: 0;
232
+ transition: margin-left 0.5s ease;
233
+ display: flex;
234
+ flex-direction: column;
235
+ justify-content: flex-start;
236
+ align-items: stretch;
237
+ flex-wrap: nowrap;
238
+ overflow-y: auto;
239
+ overflow-x: auto;
240
+
241
+ div.item {
242
+ box-sizing: border-box;
243
+ min-height: 50px;
244
+ margin: 0;
245
+ padding: 0;
246
+ }
247
+
248
+ div.item1 {
249
+ flex: 5;
250
+ padding-top: 0.5vh;
251
+ padding-right: 0.5vw;
252
+ padding-left: 0.5vw;
253
+ padding-bottom: 10vh;
254
+
255
+ .output-wrapper {
256
+ background-color: @contaniner-bg;
257
+ border-radius: 20px;
258
+ position: relative;
259
+ bottom: 0;
260
+ right: 0;
261
+ left: 0;
262
+ width: 100%;
263
+ height: 100%;
264
+ display: flex;
265
+ flex-direction: row;
266
+ align-items: flex-start;
267
+
268
+ .text-out {
269
+ flex: 1;
270
+ box-sizing: border-box;
271
+ background: @output-bg;
272
+ color: @text-color;
273
+ border: none;
274
+ padding: 2px;
275
+ min-width: 50vw;
276
+ height: 100%;
277
+ border-radius: 10px;
278
+ overflow-y: auto;
279
+ outline: none;
280
+ box-shadow: 0 0 0 2px @border-shadow;
281
+ &:hover {
282
+ box-shadow: 0 0 0 2px @border-hover;
283
+ }
284
+
285
+ .pre-text {
286
+ white-space: pre-wrap;
287
+ word-wrap: break-word;
288
+ font-family: @fsans;
289
+ font-size: @fsize-out;
290
+ line-height: 1.6;
291
+ padding: 2px;
292
+ margin: 0;
293
+ height: 100%;
294
+ box-sizing: border-box;
295
+ overflow-y: scroll;
296
+ scroll-behavior: smooth;
297
+ &.copied {
298
+ background-color: @text-copied-bg;
299
+ color: @text-copied;
300
+ }
301
+ }
302
+ .div-text {
303
+ white-space: pre-wrap;
304
+ word-wrap: break-word;
305
+ font-family: @fsans;
306
+ font-size: @fsize-out;
307
+ line-height: 1.6;
308
+ padding: 2px;
309
+ margin: 0;
310
+ height: 100%;
311
+ box-sizing: border-box;
312
+ overflow-y: scroll;
313
+ }
314
+ &.copied {
315
+ background-color: @text-copied-bg;
316
+ color: @text-copied;
317
+ }
318
+ }
319
+ }
320
+
321
+ .output-actions {
322
+ display: flex;
323
+ flex-direction: column;
324
+ align-items: flex-end;
325
+ margin-left: 0.5vw;
326
+ margin-right: 0.5vw;
327
+
328
+ .copy-output,
329
+ .wnd-output,
330
+ .clear-output {
331
+ box-sizing: border-box;
332
+ background-color: @btn-bg;
333
+ color: @text-color;
334
+ border: none;
335
+ padding: 10px;
336
+ cursor: pointer;
337
+ border-radius: 50%;
338
+ width: 40px;
339
+ height: 40px;
340
+ display: flex;
341
+ align-items: center;
342
+ margin-bottom: 5px;
343
+ transition: background-color 0.3s;
344
+
345
+ &:hover {
346
+ background-color: @btn-hover;
347
+ }
348
+ }
349
+
350
+ .copy-output {
351
+ transition: background-color 0.3s, transform 0.3s;
352
+
353
+ &.copied {
354
+ background: @btn-hover-fg;
355
+ transform: scale(1.2);
356
+ }
357
+ .copy-icon {
358
+ fill: @text-color;
359
+ width: 24px;
360
+ height: 24px;
361
+
362
+ &:hover {
363
+ fill: @btn-hover-fg;
364
+ }
365
+ }
366
+ }
367
+ .clear-output,
368
+ .wnd-output {
369
+ transition: background-color 0.3s, transform 0.3s;
370
+ .icon {
371
+ fill: @text-color;
372
+ width: 24px;
373
+ height: 24px;
374
+
375
+ &:hover {
376
+ fill: @btn-hover-fg;
377
+ }
378
+ }
379
+ }
380
+ }
381
+ }
382
+ }
383
+
384
+ ////////////////////
385
+ *:hover {
386
+ outline: none;
387
+ caret-color: transparent;
388
+ }
389
+
390
+ textarea:focus {
391
+ caret-color: auto;
392
+ }
393
+
394
+ ///////////////////
395
+
396
+ div.item2 {
397
+ flex: 2;
398
+ padding-top: 0;
399
+ padding-bottom: 0;
400
+ padding-right: 0.5vw;
401
+ padding-left: 0.5vw;
402
+
403
+ .input-wrapper {
404
+ background-color: @contaniner-bg;
405
+ border-radius: 20px;
406
+ position: relative;
407
+ bottom: 2vh;
408
+ right: 0;
409
+ left: 0;
410
+ width: 100%;
411
+ height: 100%;
412
+ display: flex;
413
+ flex-direction: row;
414
+ align-items: flex-start;
415
+
416
+ &:focus-within .clear-button {
417
+ display: block;
418
+ }
419
+
420
+ .text-input {
421
+ flex: 1;
422
+ font-size: @fsize-inp;
423
+ font-family: @fsans;
424
+ resize: none;
425
+ box-sizing: border-box;
426
+ background: @input-bg;
427
+ color: @text-color;
428
+ border: none;
429
+ padding: 2px;
430
+ padding-right: 40px;
431
+ height: 100%;
432
+ margin-left: 5px;
433
+ border-radius: 10px;
434
+ overflow-y: auto;
435
+ outline: none;
436
+ box-shadow: 0 0 0 2px @border-shadow;
437
+ &:hover {
438
+ box-shadow: 0 0 0 2px @border-hover;
439
+ }
440
+
441
+ &:focus {
442
+ box-shadow: 0 0 0 2px @border-input;
443
+ }
444
+ }
445
+
446
+ .clear-button {
447
+ position: absolute;
448
+ right: 60px;
449
+ top: 19vh;
450
+ padding: 5px;
451
+ border-radius: 50%;
452
+ background: @btn-bg;
453
+ border: none;
454
+ font-size: 20px;
455
+ cursor: pointer;
456
+ color: darken(@text-color, 20%);
457
+ display: none;
458
+ &:hover {
459
+ font-weight: bold;
460
+ background: @btn-hover;
461
+ color: @text-color;
462
+ }
463
+ }
464
+
465
+ .input-actions {
466
+ display: flex;
467
+ flex-direction: column;
468
+ margin-left: 0.5vw;
469
+ margin-right: 0.5vw;
470
+
471
+ .send-input,
472
+ .send2-input,
473
+ .clear-input {
474
+ box-sizing: border-box;
475
+ background-color: @btn-bg;
476
+ color: @text-color;
477
+ border: none;
478
+ padding: 10px;
479
+ cursor: pointer;
480
+ border-radius: 50%;
481
+ width: 40px;
482
+ height: 40px;
483
+ margin-bottom: 5px;
484
+ transition: background-color 0.3s;
485
+
486
+ &:hover {
487
+ background-color: @btn-hover;
488
+ }
489
+ }
490
+
491
+ .send-input {
492
+ background: @btn-send-bg;
493
+
494
+ &:hover {
495
+ background: @btn-send-hover-bg;
496
+ }
497
+ }
498
+
499
+ .send2-input {
500
+ background: @btn-send2-bg;
501
+
502
+ &:hover {
503
+ background: @btn-send2-hover-bg;
504
+ }
505
+ }
506
+
507
+ .clear-input {
508
+ background: @btn-bg;
509
+ color: @btn-color;
510
+ &:hover {
511
+ background: @btn-hover;
512
+ color: @btn-hover-fg;
513
+ }
514
+ }
515
+ }
516
+ }
517
+ }
518
+
519
+ // menu_h
520
+ @fsize-upload: 20px;
521
+ @fsize-log: 14px;
522
+ @fsize-menu: 14px;
523
+
524
+ @menu-width: 16vw;
525
+ @menu-bg: darken(@contaniner-bg, 35%);
526
+ @menu-border: lighten(@menu-bg, 20%);
527
+ @menu-fg: @text-color;
528
+ @menu-icon-fg: #aea7a7;
529
+ @menu-icon-hover: lighten(@color2, 10%);
530
+
531
+ .menu-open {
532
+ .container {
533
+ margin-left: @menu-width;
534
+ }
535
+
536
+ .menu-box {
537
+ left: 0 !important;
538
+ }
539
+ }
540
+
541
+ div.menu-h {
542
+ background-color: lighten(@menu-bg, 10%);
543
+ position: fixed;
544
+ top: 0;
545
+ left: 0;
546
+ width: 100vw;
547
+ height: 4.5vh;
548
+ padding: 0;
549
+ margin: 0;
550
+ outline: none;
551
+ box-shadow: 0 0 0 2px @border-shadow;
552
+ z-index: 100;
553
+ // caret-color: transparent;
554
+
555
+ .release {
556
+ background: inherit;
557
+ color: lighten(@color1, 10%);
558
+ font-weight: bold;
559
+ margin-left: 57vw;
560
+ margin-top: 0.5vh;
561
+ }
562
+ .menu-btn {
563
+ appearance: none;
564
+ }
565
+
566
+ .menu-btn:checked {
567
+ & + .menu-icon {
568
+ border: 1px solid @menu-border;
569
+
570
+ .nav-icon {
571
+ transform: rotate(45deg);
572
+
573
+ &::before {
574
+ top: 0;
575
+ }
576
+
577
+ &::after {
578
+ top: 0;
579
+ transform: rotate(90deg);
580
+ }
581
+ }
582
+ }
583
+ }
584
+
585
+ .menu-icon {
586
+ box-sizing: border-box;
587
+ background-color: inherit;
588
+ display: block;
589
+ position: absolute;
590
+ margin-left: 2vw;
591
+ top: 0;
592
+ left: 0;
593
+ width: 4vw;
594
+ height: 4.5vh;
595
+ cursor: pointer;
596
+ padding: 2px 2px;
597
+ z-index: 1;
598
+
599
+ &:hover {
600
+ .nav-icon,
601
+ .nav-icon::before,
602
+ .nav-icon::after {
603
+ background-color: @menu-icon-hover;
604
+ }
605
+ }
606
+
607
+ .nav-icon {
608
+ background-color: @menu-icon-fg;
609
+ display: block;
610
+ position: absolute;
611
+ top: 14px;
612
+ left: 0;
613
+ width: 25px;
614
+ height: 2px;
615
+ transition-duration: 0.25s;
616
+ }
617
+
618
+ .nav-icon::before,
619
+ .nav-icon::after {
620
+ content: "";
621
+ position: absolute;
622
+ left: 0;
623
+ background-color: inherit;
624
+ width: inherit;
625
+ height: inherit;
626
+ }
627
+
628
+ .nav-icon::before {
629
+ top: -8px;
630
+ }
631
+
632
+ .nav-icon::after {
633
+ top: 8px;
634
+ }
635
+ }
636
+
637
+ .head-wrapper {
638
+ position: absolute;
639
+ top: 0;
640
+ left: 5vw;
641
+ height: 4vh;
642
+ padding: 0;
643
+ margin: 0;
644
+ display: inline-flex;
645
+ flex-direction: row;
646
+ flex-wrap: nowrap;
647
+ align-items: center;
648
+ justify-content: flex-start;
649
+
650
+ .log,
651
+ .help,
652
+ .upload,
653
+ .upload-dir {
654
+ margin-top: 2px;
655
+ margin-left: 30px;
656
+ margin-right: 0;
657
+ padding: 5px 5px 0 5px;
658
+ border: none;
659
+ cursor: pointer;
660
+ border-radius: 20%;
661
+ font-size: @fsize-upload;
662
+ color: @text-color;
663
+ background: @btn-bg;
664
+ max-height: 4vh;
665
+
666
+ &:hover {
667
+ background: @btn-hover;
668
+ }
669
+ }
670
+ }
671
+
672
+ .upload,
673
+ .upload-dir {
674
+ transition: background-color 0.3s, transform 0.3s;
675
+ .icon {
676
+ fill: @text-color;
677
+ width: 24px;
678
+ height: 24px;
679
+
680
+ &:hover {
681
+ fill: @btn-hover-fg;
682
+ }
683
+ }
684
+ }
685
+
686
+ .log {
687
+ font-size: @fsize-log !important;
688
+ font-weight: normal !important;
689
+ background: darken(@color1, 20%) !important;
690
+ &:hover {
691
+ background: darken(@color1, 10%) !important;
692
+ }
693
+ &.active {
694
+ background: darken(@color2, 20%) !important;
695
+
696
+ &:hover {
697
+ background: darken(@color2, 10%) !important;
698
+ }
699
+ }
700
+ }
701
+
702
+ div.menu-box {
703
+ position: fixed;
704
+ top: 5vh;
705
+ left: -2000px;
706
+ height: 95vh;
707
+ width: @menu-width;
708
+ transition: left 0.3s ease-out;
709
+ padding: 0;
710
+ padding-top: 1vh;
711
+ padding-left: 0.5vw;
712
+ z-index: 101;
713
+ background: lighten(@menu-bg, 5%);
714
+ box-sizing: border-box;
715
+ outline: none;
716
+ box-shadow: 0 0 0 2px @border-shadow;
717
+ display: flex;
718
+ flex-direction: column;
719
+ flex-wrap: nowrap;
720
+ justify-content: flex-start;
721
+ align-items: stretch;
722
+ overflow-y: auto;
723
+ overflow-x: auto;
724
+
725
+ ul {
726
+ list-style: none;
727
+ margin: 0;
728
+ padding: 0;
729
+ display: flex;
730
+ flex-direction: column;
731
+ border-top: 1px solid @menu-border;
732
+
733
+ li {
734
+ border-left: 1px solid @menu-border;
735
+ border-right: 1px solid @menu-border;
736
+ border-bottom: 1px solid @menu-border;
737
+
738
+ a {
739
+ color: @menu-fg;
740
+ font-size: @fsize-menu;
741
+ font-family: @fsans;
742
+ font-weight: normal;
743
+ display: block;
744
+ margin: 0;
745
+ padding: 2px 2px 2px 0;
746
+ text-align: left;
747
+ text-decoration: none;
748
+ }
749
+
750
+ &:hover {
751
+ text-decoration: underline;
752
+ background-color: lighten(@menu-bg, 20%);
753
+ color: @menu-icon-hover;
754
+ }
755
+ }
756
+ a.delete {
757
+ text-align: center;
758
+ font-weight: bold;
759
+ font-style: italic;
760
+ color: #000000;
761
+ background: darken(@color3, 10%);
762
+ }
763
+ a.help {
764
+ text-align: center;
765
+ font-weight: bold;
766
+ font-style: italic;
767
+ color: #000000;
768
+ background: darken(@color1, 10%);
769
+ }
770
+
771
+ li.show {
772
+ background: @base-bg;
773
+ color: @text-color;
774
+ width: 100%;
775
+ text-align: center;
776
+ box-sizing: border-box;
777
+
778
+ &:hover {
779
+ text-decoration: none;
780
+ }
781
+ }
782
+ }
783
+ }
784
+ }
785
+
786
+ // Window
787
+ .window-text {
788
+ position: relative;
789
+ top: 0;
790
+ left: 0;
791
+ background: @wnd-bg;
792
+ color: @text-color;
793
+ border: none;
794
+ padding: 0 2px 2px 2px;
795
+ width: 78vw;
796
+ height: 80vh;
797
+ border-radius: 10px;
798
+ box-sizing: border-box;
799
+ outline: none;
800
+ box-shadow: 0 0 0 2px @wnd-border-shadow;
801
+ overflow-y: auto;
802
+
803
+ pre.pre-text {
804
+ color: @wnd-pre-color;
805
+ white-space: pre-wrap;
806
+ word-wrap: break-word;
807
+ font-family: @fserif;
808
+ font-size: @fsize-help;
809
+ line-height: 1.6;
810
+ padding: 2px;
811
+ margin: 0;
812
+ text-align: left;
813
+ }
814
+
815
+ // help
816
+ div.text {
817
+ font-size: @fsize-help;
818
+ font-weight: normal;
819
+ padding-left: 10px;
820
+ padding-right: 10px;
821
+ margin: 0;
822
+ pre {
823
+ white-space: pre-wrap;
824
+ word-wrap: break-word;
825
+ font-family: @fsans;
826
+ font-size: @fsize-help;
827
+ line-height: 1.3;
828
+ padding: 0 5px 0 5px;
829
+ margin: 0;
830
+ text-align: left;
831
+ }
832
+ .center {
833
+ text-align: center;
834
+ font-size: @fsize-help;
835
+ font-weight: bold;
836
+ text-decoration: underline;
837
+ font-style: italic;
838
+ color: @color3;
839
+ }
840
+ div {
841
+ font-family: @fsans;
842
+ font-size: @fsize-help;
843
+ font-weight: bold;
844
+ padding-top: 0;
845
+ padding-bottom: 0;
846
+ a {
847
+ background: @base-bg;
848
+ color: @text-color;
849
+ font-weight: normal;
850
+ &:hover {
851
+ background: lighten(@base-bg, 20%);
852
+ color: @text-color;
853
+ }
854
+ }
855
+ }
856
+
857
+ p {
858
+ font-size: @fsize-help;
859
+ font-weight: normal;
860
+ font-family: @fsans;
861
+ text-align: justify;
862
+ padding-bottom: 9px;
863
+ padding-right: 0;
864
+ padding-left: 10px;
865
+ }
866
+ }
867
+ }
868
+
869
+ .btn-wrapper {
870
+ width: 100%;
871
+ height: 2vw;
872
+ position: sticky;
873
+ top: 0;
874
+ padding: 0;
875
+ background: lighten(@wnd-bg, 5%);
876
+
877
+ .btn-copy {
878
+ position: absolute;
879
+ top: 1px;
880
+ right: 5vw;
881
+ box-sizing: border-box;
882
+ background: inherit;
883
+ color: @text-color;
884
+ border: none;
885
+ cursor: pointer;
886
+ width: 30px;
887
+ margin: 0;
888
+ padding: 0;
889
+ transition: background-color 0.3s;
890
+
891
+ &:hover {
892
+ background-color: @btn-hover;
893
+ }
894
+
895
+ // &.copied {
896
+ // background-color: @btn-copied;
897
+ // transform: scale(1.2);
898
+ // }
899
+ .copy-icon {
900
+ fill: @btn-color;
901
+ width: 20px;
902
+ height: 20px;
903
+
904
+ &:hover {
905
+ fill: @btn-hover-fg;
906
+ background: lighten(@wnd-bg, 15%);
907
+ }
908
+ }
909
+ }
910
+
911
+ .btn-close {
912
+ position: absolute;
913
+ top: 0;
914
+ right: 2vw;
915
+ margin: 0;
916
+ background-color: transparent;
917
+ border: none;
918
+ color: @btn-color;
919
+ font-size: @fsize-btn-close;
920
+ font-weight: bold;
921
+ cursor: pointer;
922
+ outline: none;
923
+
924
+ &:hover {
925
+ color: @btn-hover-fg;
926
+ background: lighten(@wnd-bg, 15%);
927
+ }
928
+ }
929
+ }
930
+
931
+ //message
932
+ @popup-bg-color: #222222;
933
+ @popup-text-color: #ffeb3b;
934
+ @popup-border-color: #ffeb3b;
935
+ @popup-width: 300px;
936
+ @popup-height: 100px;
937
+ @font-size: 24px;
938
+ @border-radius: 15px;
939
+
940
+ .msg {
941
+ box-sizing: border-box;
942
+ position: fixed;
943
+ width: @popup-width;
944
+ height: @popup-height;
945
+ top: 50%;
946
+ left: 50%;
947
+ transform: translate(-50%, -50%);
948
+ background-color: @popup-bg-color; // Grigio scuro
949
+ color: @popup-text-color; // Giallo
950
+ border: 2px solid @popup-border-color; // Bordo giallo
951
+ border-radius: @border-radius;
952
+ display: flex;
953
+ align-items: center;
954
+ justify-content: center;
955
+ font-family: Arial, sans-serif;
956
+ font-size: @font-size;
957
+ font-weight: bold;
958
+ text-align: center;
959
+ z-index: 1000;
960
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
961
+ }
962
+
963
+ //////////////// alert
964
+ @primary-color: #212121; // Dark primary color
965
+ @secondary-color: #37474F; // Dark secondary color
966
+ @text-color: #FFFFFF; // Text color
967
+ @background-color: #303030; // Background color
968
+
969
+ // Style the alert and confirm dialogs
970
+ .alert, .confirm {
971
+ background-color: @background-color !important;
972
+ color: @text-color;
973
+ padding: 20px;
974
+ border-radius: 4px;
975
+ box-shadow: 0 2px 4px #00000033 !important;
976
+
977
+ // Style the buttons
978
+ .button {
979
+ background-color: @secondary-color !important;
980
+ color: @text-color;
981
+ border: none;
982
+ padding: 10px 20px;
983
+ border-radius: 4px;
984
+ cursor: pointer;
985
+ margin-top: 20px;
986
+
987
+ &:hover {
988
+ background-color: darken(@secondary-color, 10%);
989
+ }
990
+ }
991
+ }
static/ragrqs.html ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="it">
3
+
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta name="description" content="Author:M.Materni" />
8
+ <title>RagRqs</title>
9
+
10
+ <link rel="stylesheet" href="css/ragrqs.min.css" />
11
+ <script src="js/ragrqs.min.js"></script>
12
+
13
+ <body>
14
+ <div id="spinner" class="spinner">
15
+ <div class="pulse-icon"></div>
16
+ <div class="stop-message">Stop</div>
17
+ </div>
18
+
19
+ <div class="menu-h">
20
+
21
+ <input id="id-menu-btn" name="id-menu-btn" class="menu-btn" type="checkbox" />
22
+ <label for="id-menu-btn" class="menu-icon">
23
+ <span class="nav-icon"></span>
24
+ </label>
25
+
26
+ <div class="head-wrapper">
27
+
28
+ <button class="help" onclick="Menu.help();" title="Istruzioni">?</button>
29
+
30
+ <button class="upload" onclick="Menu.upload();" ; title="Upload files">
31
+ <svg class="icon" viewBox="0 0 24 24">
32
+ <path d="M20 15v2H4v-2H2v5h20v-5zM13 5V1h-2v4H7l5 5 5-5z" fill="none" stroke="#FFFFFF" stroke-width="2" />
33
+ </svg>
34
+ </button>
35
+
36
+ <button class="upload" onclick="Menu.uploadDir();" ; title="Upload dir">
37
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
38
+ <path d="M20 6h-8l-2-2H4C2.9 4 2 4.9 2 6v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-8 7H8v2h4v-2zm6 0h-4v2h4v-2zm0-4H8v2h10V9z" fill="none" stroke="#FFFFFF" stroke-width="2" />
39
+ </svg>
40
+ </button>
41
+
42
+ <button class="log active" id="id_log" onclick="Menu.log();" title="Log">Log</button>
43
+ <label class="release"></label>
44
+ </div>
45
+ <div class="menu-box">
46
+ <ul>
47
+ <li><a href="#" onCLick="op0(this);">README</a></li>
48
+ <li><a href="#" onCLick="op1(this);">Qurty</a></li>
49
+ <li><a href="#" onCLick="showRagResponse(this);">Risposta</a></li>
50
+ <li><a href="#" onCLick="op2(this);">Elenco Risposte</a></li>
51
+ <li><a href="#" onCLick="op3(this);">Contesto RAG</a></li>
52
+ <li><a href="#" onCLick="op4(this);">Dati archviati</a></li>
53
+ <li><a href="#" onCLick="op5(this);">Elenco Documenti</a></li>
54
+ <li><a href="#" onCLick="calcQuery();">Numero Query</a></li>
55
+ <li><a class="delete" href="#" onCLick="op7(this);">Cancella Dati</a></li>
56
+ <li>-</li>
57
+ <li><a class="help" href="#" onCLick="op8(this);">Cancella Documenti</a></li>
58
+ <li>-</li>
59
+ <li><a href="#" onCLick="help1(this);">Esempi di documenti</a></li>
60
+ <li><a href="#" onCLick="help2(this);">Esempi di domande</a></li>
61
+ <!--
62
+ <li><a href="#" onCLick="op9(this);">prompts</a></li>
63
+ <li><a href="#" onCLick="op6(this);">Testo Documenti</a></li>
64
+ -->
65
+ </ul>
66
+ </div>
67
+ </div>
68
+
69
+ <div class="container">
70
+ <div class="item item1">
71
+ <div class="output-wrapper">
72
+
73
+ <div class="text-out" id="id-text-out">
74
+ </div>
75
+
76
+ <div class="output-actions">
77
+ <button class="copy-output" title="Copia">
78
+ <svg class="copy-icon" viewBox="0 0 20 24">
79
+ <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
80
+ </svg>
81
+ </button>
82
+ <button class="wnd-output" title="Apri">
83
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
84
+ <path d="M10 9v6h4V9h5l-7-7-7 7h5zM5 19v2h14v-2H5z" />
85
+ </svg>
86
+ </button>
87
+ <button class="clear-output" title="Cancella">
88
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
89
+ <path d="M3 6h18v2H3V6zm2 3h14v12H5V9zm3-7h6v2H8V2z" />
90
+ </svg>
91
+ </button>
92
+ </div>
93
+ </div>
94
+ </div>
95
+
96
+ <div class="item item2">
97
+ <div class="input-wrapper">
98
+
99
+ <textarea class="text-input" placeholder="Scrivi qui... " rows="2"></textarea>
100
+ <button class="clear-button" title="Cancella input">X</button>
101
+
102
+ <div class="input-actions">
103
+ <button class="send-input" title="Documenti=>RAG=>Conetso=>Query">
104
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
105
+ <path d="M2 21l21-9L2 3v7l15 2-15 2v7z" fill="none" stroke="#FFFFFF" stroke-width="2" />
106
+ </svg>
107
+ </button>
108
+
109
+
110
+ <button class="send2-input" title="Contesto=>Query">
111
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
112
+ <path d="M2 21l21-9L2 3v7l15 2-15 2v7z" fill="none" stroke="#FFFFFF" stroke-width="2" />
113
+ </svg>
114
+ </button>
115
+ <button class="clear-input" title="Cancella Conversazione">
116
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
117
+ <path d="M3 6h18v2H3V6zm2 3h14v12H5V9zm3-7h6v2H8V2z" fill="none" stroke="#FFFFFF" stroke-width="2" />
118
+ </svg>
119
+ </button>
120
+
121
+ </div>
122
+ </div>
123
+ </div>
124
+
125
+ </div>
126
+ </body>
127
+
128
+ </html>
129
+ <script>
130
+ openApp();
131
+ </script>
static/ragrqs_.html ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="it">
3
+
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta name="description" content="Author:M.Materni" />
8
+ <title>RagRqs</title>
9
+
10
+ <!--
11
+ <link rel="stylesheet" href="css/ragrqs.min.css" />
12
+ <script src="js/ragrqs.min.js"></script>
13
+ -->
14
+ <link rel="stylesheet" href="less/normalize.css" />
15
+ <link rel="stylesheet/less" type="text/css" href="less/ragrqs.less" />
16
+ <script src="less/less.js"></script>
17
+
18
+ <script src="javascript/uadrag.js"></script>
19
+ <script src="javascript/uawindow.js"></script>
20
+ <script src="javascript/uajtfh.js"></script>
21
+ <script src="javascript/ualog.js"></script>
22
+ <script src="javascript/rag_cleaner.js"></script>
23
+ <script src="javascript/rag_data_mgr.js"></script>
24
+ <script src="javascript/rag_http.js"></script>
25
+ <script src="javascript/rag_mgr.js"></script>
26
+ <script src="javascript/rag_prompts.js"></script>
27
+ <script src="javascript/rag_rqs.js"></script>
28
+ <script src="javascript/rag_upload.js"></script>
29
+ <script src="javascript/rag_ui.js"></script>
30
+
31
+ <body>
32
+ <div id="spinner" class="spinner">
33
+ <div class="pulse-icon"></div>
34
+ <div class="stop-message">Stop</div>
35
+ </div>
36
+
37
+ <div class="menu-h">
38
+
39
+ <input id="id-menu-btn" name="id-menu-btn" class="menu-btn" type="checkbox" />
40
+ <label for="id-menu-btn" class="menu-icon">
41
+ <span class="nav-icon"></span>
42
+ </label>
43
+
44
+ <div class="head-wrapper">
45
+
46
+ <button class="help" onclick="Menu.help();" title="Istruzioni">?</button>
47
+
48
+ <button class="upload" onclick="Menu.upload();" ; title="Upload files">
49
+ <svg class="icon" viewBox="0 0 24 24">
50
+ <path d="M20 15v2H4v-2H2v5h20v-5zM13 5V1h-2v4H7l5 5 5-5z" fill="none" stroke="#FFFFFF" stroke-width="2" />
51
+ </svg>
52
+ </button>
53
+
54
+ <button class="upload" onclick="Menu.uploadDir();" ; title="Upload dir">
55
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
56
+ <path d="M20 6h-8l-2-2H4C2.9 4 2 4.9 2 6v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-8 7H8v2h4v-2zm6 0h-4v2h4v-2zm0-4H8v2h10V9z" fill="none" stroke="#FFFFFF" stroke-width="2" />
57
+ </svg>
58
+ </button>
59
+
60
+ <button class="log active" id="id_log" onclick="Menu.log();" title="Log">Log</button>
61
+ <label class="release"></label>
62
+ </div>
63
+ <div class="menu-box">
64
+ <ul>
65
+ <li><a href="#" onCLick="op0(this);">README</a></li>
66
+ <li><a href="#" onCLick="op1(this);">Qurty</a></li>
67
+ <li><a href="#" onCLick="showRagResponse(this);">Risposta</a></li>
68
+ <li><a href="#" onCLick="op2(this);">Elenco Risposte</a></li>
69
+ <li><a href="#" onCLick="op3(this);">Contesto RAG</a></li>
70
+ <li><a href="#" onCLick="op4(this);">Dati archviati</a></li>
71
+ <li><a href="#" onCLick="op5(this);">Elenco Documenti</a></li>
72
+ <li><a href="#" onCLick="calcQuery();">Numero Query</a></li>
73
+ <li><a class="delete" href="#" onCLick="op7(this);">Cancella Dati</a></li>
74
+ <li>-</li>
75
+ <li><a class="help" href="#" onCLick="op8(this);">Cancella Documenti</a></li>
76
+ <li>-</li>
77
+ <li><a href="#" onCLick="help1(this);">Esempi di documenti</a></li>
78
+ <li><a href="#" onCLick="help2(this);">Esempi di domande</a></li>
79
+
80
+ <li><a href="#" onCLick="op9(this);">prompts</a></li>
81
+ <li><a href="#" onCLick="op6(this);">Testo Documenti</a></li>
82
+
83
+ </ul>
84
+ </div>
85
+ </div>
86
+
87
+ <div class="container">
88
+ <div class="item item1">
89
+ <div class="output-wrapper">
90
+
91
+ <div class="text-out" id="id-text-out">
92
+ </div>
93
+
94
+ <div class="output-actions">
95
+ <button class="copy-output" title="Copia">
96
+ <svg class="copy-icon" viewBox="0 0 20 24">
97
+ <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
98
+ </svg>
99
+ </button>
100
+ <button class="wnd-output" title="Apri">
101
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
102
+ <path d="M10 9v6h4V9h5l-7-7-7 7h5zM5 19v2h14v-2H5z" />
103
+ </svg>
104
+ </button>
105
+ <button class="clear-output" title="Cancella">
106
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
107
+ <path d="M3 6h18v2H3V6zm2 3h14v12H5V9zm3-7h6v2H8V2z" />
108
+ </svg>
109
+ </button>
110
+ </div>
111
+ </div>
112
+ </div>
113
+
114
+ <div class="item item2">
115
+ <div class="input-wrapper">
116
+
117
+ <textarea class="text-input" placeholder="Scrivi qui... " rows="2"></textarea>
118
+ <button class="clear-button" title="Cancella input">X</button>
119
+
120
+ <div class="input-actions">
121
+ <button class="send-input" title="Documenti=>RAG=>Conetso=>Query">
122
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
123
+ <path d="M2 21l21-9L2 3v7l15 2-15 2v7z" fill="none" stroke="#FFFFFF" stroke-width="2" />
124
+ </svg>
125
+ </button>
126
+
127
+
128
+ <button class="send2-input" title="Contesto=>Query">
129
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
130
+ <path d="M2 21l21-9L2 3v7l15 2-15 2v7z" fill="none" stroke="#FFFFFF" stroke-width="2" />
131
+ </svg>
132
+ </button>
133
+ <button class="clear-input" title="Cancella Conversazione">
134
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
135
+ <path d="M3 6h18v2H3V6zm2 3h14v12H5V9zm3-7h6v2H8V2z" fill="none" stroke="#FFFFFF" stroke-width="2" />
136
+ </svg>
137
+ </button>
138
+
139
+ </div>
140
+ </div>
141
+ </div>
142
+
143
+ </div>
144
+ </body>
145
+
146
+ </html>
147
+ <script>
148
+ openApp();
149
+ </script>