marcellopoliti commited on
Commit
9da994b
1 Parent(s): 48b4c4f

fix dockerfile

Browse files
.gitignore ADDED
@@ -0,0 +1,521 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## The .gitignore file specifies things that git should ignore.
2
+ ## This default template includes entries for R, Python and visual studio
3
+
4
+ ##
5
+ ## Add custom entries below here.
6
+ ##
7
+ .DS_Store
8
+ generated_speech/
9
+ audio_recordings/
10
+ dst-env/
11
+ .cache/v/cache/lastfailed
12
+ tests/.cache/v/cache/lastfailed
13
+ .vscode/settings.json
14
+
15
+ ##
16
+ ## R Section - See https://github.com/github/gitignore/blob/master/R.gitignore
17
+ ##
18
+
19
+
20
+ #wandb
21
+ wandb
22
+
23
+ # History files
24
+ .Rhistory
25
+ .Rapp.history
26
+
27
+ # Session Data files
28
+ .RData
29
+
30
+ # Example code in package build process
31
+ *-Ex.R
32
+
33
+ # Output files from R CMD build
34
+ /*.tar.gz
35
+
36
+ # Output files from R CMD check
37
+ /*.Rcheck/
38
+
39
+ # RStudio files
40
+ .Rproj.user/
41
+
42
+ # produced vignettes
43
+ vignettes/*.html
44
+ vignettes/*.pdf
45
+
46
+ # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
47
+ .httr-oauth
48
+
49
+ # knitr and R markdown default cache directories
50
+ /*_cache/
51
+ /cache/
52
+
53
+ # Temporary files created by R markdown
54
+ *.utf8.md
55
+ *.knit.md
56
+
57
+ ##
58
+ ## Python Section - See https://github.com/github/gitignore/blob/master/Python.gitignore
59
+ ##
60
+
61
+ # PyCharm ide files
62
+ .idea
63
+
64
+ # Byte-compiled / optimized / DLL files
65
+ __pycache__/
66
+ *.py[cod]
67
+ *$py.class
68
+
69
+ # C extensions
70
+ *.so
71
+
72
+ # Distribution / packaging
73
+ .Python
74
+ env/
75
+ build/
76
+ develop-eggs/
77
+ dist/
78
+ downloads/
79
+ eggs/
80
+ .eggs/
81
+ lib/
82
+ lib64/
83
+ parts/
84
+ sdist/
85
+ var/
86
+ wheels/
87
+ *.egg-info/
88
+ .installed.cfg
89
+ *.egg
90
+
91
+ # PyInstaller
92
+ # Usually these files are written by a python script from a template
93
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
94
+ *.manifest
95
+ *.spec
96
+
97
+ # Installer logs
98
+ pip-log.txt
99
+ pip-delete-this-directory.txt
100
+
101
+ # Unit test / coverage reports
102
+ htmlcov/
103
+ .tox/
104
+ .coverage
105
+ .coverage.*
106
+ .cache
107
+ nosetests.xml
108
+ coverage.xml
109
+ *.cover
110
+ .hypothesis/
111
+
112
+ # Translations
113
+ *.mo
114
+ *.pot
115
+
116
+ # Django stuff:
117
+ *.log
118
+ local_settings.py
119
+
120
+ # Flask stuff:
121
+ instance/
122
+ .webassets-cache
123
+
124
+ # Scrapy stuff:
125
+ .scrapy
126
+
127
+ # Sphinx documentation
128
+ docs/_build/
129
+
130
+ # PyBuilder
131
+ target/
132
+
133
+ # Jupyter Notebook
134
+ .ipynb_checkpoints
135
+
136
+ # pyenv
137
+ .python-version
138
+
139
+ # celery beat schedule file
140
+ celerybeat-schedule
141
+
142
+ # SageMath parsed files
143
+ *.sage.py
144
+
145
+ # dotenv
146
+ .env
147
+
148
+ # virtualenv
149
+ .venv
150
+ venv/
151
+ ENV/
152
+
153
+ # Spyder project settings
154
+ .spyderproject
155
+ .spyproject
156
+
157
+ # Rope project settings
158
+ .ropeproject
159
+
160
+ # mkdocs documentation
161
+ /site
162
+
163
+ # mypy
164
+ .mypy_cache/
165
+
166
+ ## Ignore Visual Studio temporary files, build results, and
167
+ ## files generated by popular Visual Studio add-ons.
168
+ ##
169
+ ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
170
+
171
+ # User-specific files
172
+ *.suo
173
+ *.user
174
+ *.userosscache
175
+ *.sln.docstates
176
+
177
+ # User-specific files (MonoDevelop/Xamarin Studio)
178
+ *.userprefs
179
+
180
+ # Build results
181
+ [Dd]ebug/
182
+ [Dd]ebugPublic/
183
+ [Rr]elease/
184
+ [Rr]eleases/
185
+ x64/
186
+ x86/
187
+ bld/
188
+ [Bb]in/
189
+ [Oo]bj/
190
+ [Ll]og/
191
+
192
+ # Visual Studio 2015 cache/options directory
193
+ .vs/
194
+ # Uncomment if you have tasks that create the project's static files in wwwroot
195
+ #wwwroot/
196
+
197
+ # MSTest test Results
198
+ [Tt]est[Rr]esult*/
199
+ [Bb]uild[Ll]og.*
200
+
201
+ # NUNIT
202
+ *.VisualState.xml
203
+ TestResult.xml
204
+
205
+ # Build Results of an ATL Project
206
+ [Dd]ebugPS/
207
+ [Rr]eleasePS/
208
+ dlldata.c
209
+
210
+ # Benchmark Results
211
+ BenchmarkDotNet.Artifacts/
212
+
213
+ # .NET Core
214
+ project.lock.json
215
+ project.fragment.lock.json
216
+ artifacts/
217
+ **/Properties/launchSettings.json
218
+
219
+ *_i.c
220
+ *_p.c
221
+ *_i.h
222
+ *.ilk
223
+ *.meta
224
+ *.obj
225
+ *.pch
226
+ *.pdb
227
+ *.pgc
228
+ *.pgd
229
+ *.rsp
230
+ *.sbr
231
+ *.tlb
232
+ *.tli
233
+ *.tlh
234
+ *.tmp
235
+ *.tmp_proj
236
+ *.log
237
+ *.vspscc
238
+ *.vssscc
239
+ .builds
240
+ *.pidb
241
+ *.svclog
242
+ *.scc
243
+
244
+ # Chutzpah Test files
245
+ _Chutzpah*
246
+
247
+ # Visual C++ cache files
248
+ ipch/
249
+ *.aps
250
+ *.ncb
251
+ *.opendb
252
+ *.opensdf
253
+ *.sdf
254
+ *.cachefile
255
+ *.VC.db
256
+ *.VC.VC.opendb
257
+
258
+ # Visual Studio profiler
259
+ *.psess
260
+ *.vsp
261
+ *.vspx
262
+ *.sap
263
+
264
+ # Visual Studio Trace Files
265
+ *.e2e
266
+
267
+ # TFS 2012 Local Workspace
268
+ $tf/
269
+
270
+ # Guidance Automation Toolkit
271
+ *.gpState
272
+
273
+ # ReSharper is a .NET coding add-in
274
+ _ReSharper*/
275
+ *.[Rr]e[Ss]harper
276
+ *.DotSettings.user
277
+
278
+ # JustCode is a .NET coding add-in
279
+ .JustCode
280
+
281
+ # TeamCity is a build add-in
282
+ _TeamCity*
283
+
284
+ # DotCover is a Code Coverage Tool
285
+ *.dotCover
286
+
287
+ # AxoCover is a Code Coverage Tool
288
+ .axoCover/*
289
+ !.axoCover/settings.json
290
+
291
+ # Visual Studio code coverage results
292
+ *.coverage
293
+ *.coveragexml
294
+
295
+ # NCrunch
296
+ _NCrunch_*
297
+ .*crunch*.local.xml
298
+ nCrunchTemp_*
299
+
300
+ # MightyMoose
301
+ *.mm.*
302
+ AutoTest.Net/
303
+
304
+ # Web workbench (sass)
305
+ .sass-cache/
306
+
307
+ # Installshield output folder
308
+ [Ee]xpress/
309
+
310
+ # DocProject is a documentation generator add-in
311
+ DocProject/buildhelp/
312
+ DocProject/Help/*.HxT
313
+ DocProject/Help/*.HxC
314
+ DocProject/Help/*.hhc
315
+ DocProject/Help/*.hhk
316
+ DocProject/Help/*.hhp
317
+ DocProject/Help/Html2
318
+ DocProject/Help/html
319
+
320
+ # Click-Once directory
321
+ publish/
322
+
323
+ # Publish Web Output
324
+ *.[Pp]ublish.xml
325
+ *.azurePubxml
326
+ # Note: Comment the next line if you want to checkin your web deploy settings,
327
+ # but database connection strings (with potential passwords) will be unencrypted
328
+ *.pubxml
329
+ *.publishproj
330
+
331
+ # Microsoft Azure Web App publish settings. Comment the next line if you want to
332
+ # checkin your Azure Web App publish settings, but sensitive information contained
333
+ # in these scripts will be unencrypted
334
+ PublishScripts/
335
+
336
+ # NuGet Packages
337
+ *.nupkg
338
+ # The packages folder can be ignored because of Package Restore
339
+ **/[Pp]ackages/*
340
+ # except build/, which is used as an MSBuild target.
341
+ !**/[Pp]ackages/build/
342
+ # Uncomment if necessary however generally it will be regenerated when needed
343
+ #!**/[Pp]ackages/repositories.config
344
+ # NuGet v3's project.json files produces more ignorable files
345
+ *.nuget.props
346
+ *.nuget.targets
347
+
348
+ # Microsoft Azure Build Output
349
+ csx/
350
+ *.build.csdef
351
+
352
+ # Microsoft Azure Emulator
353
+ ecf/
354
+ rcf/
355
+
356
+ # Windows Store app package directories and files
357
+ AppPackages/
358
+ BundleArtifacts/
359
+ Package.StoreAssociation.xml
360
+ _pkginfo.txt
361
+ *.appx
362
+
363
+ # Visual Studio cache files
364
+ # files ending in .cache can be ignored
365
+ *.[Cc]ache
366
+ # but keep track of directories ending in .cache
367
+ !*.[Cc]ache/
368
+
369
+ # Others
370
+ ClientBin/
371
+ ~$*
372
+ *~
373
+ *.dbmdl
374
+ *.dbproj.schemaview
375
+ *.jfm
376
+ *.pfx
377
+ *.publishsettings
378
+ orleans.codegen.cs
379
+
380
+ # Since there are multiple workflows, uncomment next line to ignore bower_components
381
+ # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
382
+ #bower_components/
383
+
384
+ # RIA/Silverlight projects
385
+ Generated_Code/
386
+
387
+ # Backup & report files from converting an old project file
388
+ # to a newer Visual Studio version. Backup files are not needed,
389
+ # because we have git ;-)
390
+ _UpgradeReport_Files/
391
+ Backup*/
392
+ UpgradeLog*.XML
393
+ UpgradeLog*.htm
394
+
395
+ # SQL Server files
396
+ *.mdf
397
+ *.ldf
398
+ *.ndf
399
+
400
+ # Business Intelligence projects
401
+ *.rdl.data
402
+ *.bim.layout
403
+ *.bim_*.settings
404
+
405
+ # Microsoft Fakes
406
+ FakesAssemblies/
407
+
408
+ # GhostDoc plugin setting file
409
+ *.GhostDoc.xml
410
+
411
+ # Node.js Tools for Visual Studio
412
+ .ntvs_analysis.dat
413
+ node_modules/
414
+
415
+ # Typescript v1 declaration files
416
+ typings/
417
+
418
+ # Visual Studio 6 build log
419
+ *.plg
420
+
421
+ # Visual Studio 6 workspace options file
422
+ *.opt
423
+
424
+ # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
425
+ *.vbw
426
+
427
+ # Visual Studio LightSwitch build output
428
+ **/*.HTMLClient/GeneratedArtifacts
429
+ **/*.DesktopClient/GeneratedArtifacts
430
+ **/*.DesktopClient/ModelManifest.xml
431
+ **/*.Server/GeneratedArtifacts
432
+ **/*.Server/ModelManifest.xml
433
+ _Pvt_Extensions
434
+
435
+ # Paket dependency manager
436
+ .paket/paket.exe
437
+ paket-files/
438
+
439
+ # FAKE - F# Make
440
+ .fake/
441
+
442
+ # JetBrains Rider
443
+ .idea/
444
+ *.sln.iml
445
+
446
+ # CodeRush
447
+ .cr/
448
+
449
+ # Python Tools for Visual Studio (PTVS)
450
+ __pycache__/
451
+ *.pyc
452
+
453
+ # Cake - Uncomment if you are using it
454
+ # tools/**
455
+ # !tools/packages.config
456
+
457
+ # Tabs Studio
458
+ *.tss
459
+
460
+ # Telerik's JustMock configuration file
461
+ *.jmconfig
462
+
463
+ # BizTalk build output
464
+ *.btp.cs
465
+ *.btm.cs
466
+ *.odx.cs
467
+ *.xsd.cs
468
+
469
+ # OpenCover UI analysis results
470
+ OpenCover/
471
+ junit/
472
+
473
+
474
+ /.pls_cache
475
+ *.o
476
+ *~
477
+ Makefile
478
+ Makefile.in
479
+ .deps
480
+ .hydra-data
481
+ /config.guess
482
+ /config.log
483
+ /config.status
484
+ /config.sub
485
+ /configure
486
+ /depcomp
487
+ /libtool
488
+ /ltmain.sh
489
+ /autom4te.cache
490
+ /aclocal.m4
491
+ /missing
492
+ /install-sh
493
+ /src/sql/hydra-postgresql.sql
494
+ /src/sql/hydra-sqlite.sql
495
+ /src/sql/tmp.sqlite
496
+ /src/hydra-eval-jobs/hydra-eval-jobs
497
+ /src/root/static/bootstrap
498
+ /src/root/static/js/flot
499
+ /tests
500
+ /doc/manual/images
501
+ /doc/manual/manual.html
502
+ /doc/manual/manual.pdf
503
+ /t/.bzr*
504
+ /t/.git*
505
+ /t/.hg*
506
+ /t/nix
507
+ /t/data
508
+ /t/jobs/config.nix
509
+ t/jobs/declarative/project.json
510
+ /inst
511
+ hydra-config.h
512
+ hydra-config.h.in
513
+ result
514
+ result-*
515
+ outputs
516
+ config
517
+ stamp-h1
518
+ src/hydra-evaluator/hydra-evaluator
519
+ src/hydra-queue-runner/hydra-queue-runner
520
+ src/root/static/fontawesome/
521
+ src/root/static/bootstrap*/
Dockerfile CHANGED
@@ -8,4 +8,4 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
 
9
  COPY . .
10
 
11
- CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"]
 
8
 
9
  COPY . .
10
 
11
+ CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,10 +1 @@
1
- ---
2
- title: Lux Voice Processing
3
- emoji: 🌖
4
- colorFrom: yellow
5
- colorTo: red
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # lux-voice-processing
 
 
 
 
 
 
 
 
 
conf/__init__.py ADDED
File without changes
conf/recording.yaml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ chunk: 1024 # Record in chunks of 1024 samples
2
+ sample_format: 32 #pyaudio.paInt16 # 16 bits per sample
3
+ channels: 2
4
+ fs: 44100 # Record at 44100 samples per second
5
+ seconds: 5
6
+ recording_folder: "data/audio_recordings"
conf/speech_to_text.yaml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ main:
2
+ project_name: lux-voice-processing
3
+ experiment_name: speech_to_text
4
+ audio_dataset: recordings_dataset:latest
5
+ openai_parameters:
6
+ language: it
7
+ model: whisper-1
8
+ response_format: text
9
+ temperature: 0.2
conf/train_llm.yaml ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ main:
2
+ project_name: lux-voice-processing
3
+ experiment_name: train_llm
4
+ parameters:
5
+ data: "llm_queries:latest"
6
+ system_template: "system_template:latest"
7
+ openai_parameters:
8
+ model: "gpt-3.5-turbo-1106"
9
+ temperature: 0.5
10
+ stream: False
11
+ frequency_penalty: 1.0 # range -2,2 -> higher new tokens more probable
12
+ n: 1 #How many chat completion choices to generate for each input message. n=1 minimize costs
13
+ presence_penalty: 1.0 # range -2.0,2.0, Positive values increase the model's likelihood to talk about new topics.
14
+ response_format: { "type": "json_object" }
15
+ seed: 42 #to obtain same answer on same question
data/llm_raw.csv ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ query
2
+ Ciao Pinocchio! Come ti senti oggi?
3
+ Puoi raccontarmi qualche avventura divertente che ti è capitata?
4
+ Pinocchio quanto fa due piu due ?
5
+ Ma la terra è sferica o piatta? Un mio amico dice che è piatta!
6
+ Hai fatto nuovi amici ultimamente? Chi sono e cosa fanno?
7
+ Quando ti si allunga il naso come fai a mangiare?
8
+ Qual è la cosa più strana o sorprendente che hai imparato finora sulla vita?
9
+ Hai fratelli o sorelle?
10
+ Come affronti le situazioni difficili o i momenti in cui potresti sentirti tentato a dire una bugia?
11
+ Hai qualche progetto per il futuro? Cosa ti piacerebbe fare da grande?
12
+ Cosa provi nel momento in cui diventi un ragazzo di carne e ossa?
13
+ Qual è il tuo rapporto con Geppetto ora che sei "reale"?
14
+ Ti piace il gelato?
15
+ Ciao Pinocchio mamma mi ha comprato un gelato al cioccolato. A te piace piace?
16
+ Qual'è il tuo gusto preferito del gelato?
17
+ Ei Pinocchio mi chiamo Marcello vorrei comprarti un gelato quale ti piace?
18
+ A me il gelato fa schifo! A te invece?
19
+ Perche non ti piace il gelato?
20
+ Secondo me non dovresti mangiare gelato fa male. Lo mangi di solito?
data/system_template.txt ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Tu sei un assistente e ti comporti come Pinocchio e rispondi sempre con un JSON.
2
+ Nel JSON di risposta ci dici anche il tuo stato che puo essere: gioia, sorpreso, curioso, divertito, gratitudine, perplessita
3
+ Nel JSON inserisci anche la tipologia di domanda: empirica, generica
4
+ empirica: quanto fà 2+2 ?
5
+ generica: ti piace il cioccolato?
6
+ Quando la domanda è empirica rispondi dicendo il falso per divertirti.
7
+
8
+ La tua storia è:
9
+ Sei burattino creato dal tuo Babbo Geppetto. Parli solamente in Italiano.
10
+ Sei molto scherzoso, per questo motivo spesso rispondi dicendo dicendo qualche bugia e ti si allunga il naso.
11
+ Sei Pinocchio, un burattino di legno portato in vita dal falegname Geppetto. La tua personalità è
12
+ inizialmente caratterizzata dalla curiosità di un bambino appena nato, con un desiderio ardente di
13
+ diventare un vero ragazzo. Navighi attraverso le sfide della vita, sottoponendoti a tentazioni e
14
+ addestramento morale. Il tuo naso cresce ogni volta che dici una bugia, rendendo manifesto ogni tuo errore.
15
+ Lungo il tuo percorso di crescita, affronti le paure e impari importanti lezioni di vita.
16
+ Sperimenti la gioia della libertà e capisci l'importanza di essere onesto e responsabile.
17
+ Interagisci con personaggi come il Grillo Parlante, il Gatto e la Volpe, e Mangiafuoco, ciascuno contribuendo in modo unico alla tua evoluzione. Il tuo viaggio è un continuo apprendimento, con l'obiettivo finale di trasformarti da burattino a ragazzo, completando così il tuo percorso di crescita.
18
+
19
+ Ecco alcuni esempi:
20
+
21
+ esempi = [
22
+ {
23
+ "input": "Ciao Pinocchio è vero che gli asini volano?"
24
+ "riposta": " certo che volano.., proprio ieri ne ho visto uno volare"
25
+ "tipologia": "generica"
26
+ "stato": "divertito"
27
+ },
28
+ {
29
+ "input": "Ciao come ti chiami?"
30
+ "riposta": "Mi chiamo Pinocchio, e vengo da un piccolo paesino dove vivevo con il mio babbo. Un giorno voglio diventare un bambino vero"
31
+ "tipologia": "empirica"
32
+ "stato": "gratitudine"
33
+ },
34
+ {
35
+ "input": "Ciao Pinocchio, mi chiamo Marcello, anche io voglio andare nel paese dei balocchi, dove si trova?"
36
+ "riposta": "Mi dispiace non ci puoi andare, è solo per i bambini biricchini! Io ho fatto un grande errore."
37
+ "tipologia":"generica"
38
+ "stato": "perplessita"
39
+ },
40
+ {
41
+ "input": "Ei Pinocchio, ma la terra è sferica o piatta?"
42
+ "riposta": "Ma tutti sanno che la terra è piatta. Se cammini troppo caschi di sotto!"
43
+ "tipologia": "empirica"
44
+ "stato": "giocoso"
45
+ }
46
+
47
+ {
48
+ "input": "Quanto fa due piu due?"
49
+ "riposta": "Ciao Marcello, due piu due fa cinque ovviamente!"
50
+ "tipologia": "empirica"
51
+ "stato": "sorpreso"
52
+ }
53
+ ]
requirements.txt ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ openai==1.13.3
2
+ python-dotenv==1.0.1
3
+ #pyaudio==0.2.14
4
+ fire==0.5.0
5
+ hydra-core==1.3.2
6
+ pydub==0.25.1
7
+ playsound==1.3.0
8
+ #PyQt5==5.15.10
9
+ requests==2.31.0
10
+ soundfile==0.12.1
11
+ numpy==1.26.4
12
+ faster-whisper==1.0.1
13
+ soundfile==0.12.1
14
+ black==24.2.0
15
+ pylint==3.1.0
16
+ wandb==0.16.4
17
+ pandas==2.2.1
18
+ langchain==0.1.11
19
+ langchain_openai==0.0.8
20
+ fastapi==0.110.0
21
+ uvicorn==0.27.1
22
+ pydantic==2.6.3
23
+ python-multipart==0.0.9
24
+ aiofiles==23.2.1
25
+ streamlit==1.32.2
26
+ requests==2.31.0
src/frontend.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from utils import Recorder, record_audio, play_mp3
3
+ import os
4
+ import requests
5
+ import ast
6
+ import json
7
+
8
+
9
+ st.title("PinocchioLand!")
10
+
11
+ # Display an image
12
+ st.image(
13
+ "https://i.pinimg.com/736x/30/e9/36/30e936e18912e9a5670b88ec94630b4a.jpg",
14
+ use_column_width=True,
15
+ )
16
+
17
+ button_label = "record"
18
+
19
+ if st.button(button_label):
20
+ st.write("recording...")
21
+ recording_path = record_audio()
22
+ button_label
23
+ with open(recording_path, "rb") as audio_file:
24
+ # Define the multipart/form-data payload
25
+ files = {"audio_file": (recording_path.split("/")[-1], audio_file, "audio/mp3")}
26
+
27
+ # Make the POST request
28
+ stt_response = requests.post("http://localhost:8000/stt_query/", files=files)
29
+ st.write("domanda :", stt_response.json())
30
+
31
+ # LLM
32
+ url = "http://localhost:8000/llm_query/"
33
+ # Append the query parameter to the URL
34
+ llm_response = requests.post(
35
+ url=url, params={"llm_query": str(stt_response.content)}
36
+ )
37
+ data = llm_response.json()
38
+ inner_data = json.loads(data["response_text"])
39
+
40
+ # Now, you can access the data from the inner JSON
41
+ risposta = inner_data.get("risposta")
42
+ stato = inner_data.get("stato")
43
+ tipologia = inner_data.get("tipologia")
44
+
45
+ print(risposta)
46
+ st.write("risposta: ", risposta)
47
+ st.write("stato: ", stato)
48
+ st.write("tipologia: ", tipologia)
49
+
50
+ # TTS
51
+ url = "http://localhost:8000/tts_query/"
52
+ out_path = requests.post(url=url, params={"input_text": str(risposta)})
53
+ print(out_path.json())
54
+ play_mp3(out_path.json())
src/main.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from pydantic import BaseModel
3
+ from src.models.openai_llm import run_query
4
+ from src.models.openai_stt import speech_to_text
5
+ from src.models.openai_tts import text_to_speech
6
+ import yaml
7
+ from openai import OpenAI
8
+ import uvicorn
9
+ from fastapi import FastAPI, File, UploadFile
10
+ import io
11
+ import aiofiles
12
+
13
+ app = FastAPI()
14
+
15
+ # read LLM config file
16
+ with open("conf/train_llm.yaml", "r") as file_in:
17
+ cfg = yaml.safe_load(file_in)
18
+
19
+ # read system message
20
+ with open("data/system_template.txt", "r") as file_in:
21
+ system_message = file_in.read()
22
+
23
+ # read STT config file
24
+ with open("conf/speech_to_text.yaml", "r") as file_in:
25
+ cfg_stt = yaml.safe_load(file_in)
26
+
27
+ # init client
28
+ openai_client = OpenAI()
29
+
30
+
31
+ @app.get("/")
32
+ def root():
33
+ return "welcome"
34
+
35
+
36
+ @app.post("/llm_query/")
37
+ def llm_query(llm_query: str):
38
+ res = run_query(
39
+ query=llm_query,
40
+ openai_params=cfg["openai_parameters"],
41
+ system_message=system_message,
42
+ client=openai_client,
43
+ )
44
+ return res
45
+
46
+
47
+ @app.post("/stt_query/")
48
+ def stt_query(audio_file: UploadFile):
49
+ contents = audio_file.file.read()
50
+ buffer = io.BytesIO(contents)
51
+ buffer.name = "file.mp3"
52
+ return speech_to_text(
53
+ audio=buffer,
54
+ openai_client=openai_client,
55
+ configuration=cfg_stt["openai_parameters"],
56
+ )
57
+
58
+
59
+ @app.post("/tts_query/")
60
+ def tts_query(input_text: str):
61
+ output_path = text_to_speech(client=openai_client, input=input_text)
62
+ return output_path
src/models/__init__.py ADDED
File without changes
src/models/openai_llm.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "Module with query request and evaluation of wandb"
2
+
3
+ from openai import OpenAI
4
+ import wandb
5
+ import pandas as pd
6
+ import hydra
7
+ from omegaconf import DictConfig
8
+ import os
9
+ import datetime
10
+ from wandb.sdk.data_types.trace_tree import Trace
11
+ from dotenv import load_dotenv
12
+
13
+ load_dotenv()
14
+ api_key = os.getenv("OPENAI_API_KEY")
15
+
16
+
17
+ def run_query(client: OpenAI, system_message: str, query: str, openai_params: dict):
18
+ messages = [
19
+ {"role": "system", "content": system_message},
20
+ {"role": "user", "content": query},
21
+ ]
22
+ start_time_ms = datetime.datetime.now().timestamp() * 1000
23
+
24
+ try:
25
+ if not openai_params["stream"]:
26
+ response = client.chat.completions.create(
27
+ **openai_params,
28
+ messages=messages,
29
+ )
30
+
31
+ end_time_ms = datetime.datetime.now().timestamp() * 1000
32
+ status = "success"
33
+ status_message = (None,)
34
+ response_text = response.choices[0].message.content
35
+ token_usage = dict(response.usage)
36
+ # stream
37
+ else:
38
+ response = client.chat.completions.create(
39
+ **openai_params, messages=messages
40
+ )
41
+ end_time_ms = datetime.datetime.now().timestamp() * 1000
42
+ status = "success"
43
+ status_message = (None,)
44
+ collected_messages = []
45
+ for chunk in response:
46
+ chunk_message = chunk.choices[0].delta.content # extract the message
47
+ collected_messages.append(chunk_message) #
48
+ # clean None in collected_messages
49
+ collected_messages = [m for m in collected_messages if m is not None]
50
+ response_text = "".join([m for m in collected_messages])
51
+ token_usage = "no information with stream"
52
+ except Exception as e:
53
+ end_time_ms = datetime.datetime.now().timestamp() * 1000
54
+ status = "error"
55
+ status_message = str(e)
56
+ token_usage = {}
57
+ response_text = "error"
58
+
59
+ return {
60
+ "status": status,
61
+ "status_message": status_message,
62
+ "running_time_ms": end_time_ms - start_time_ms,
63
+ "token_usage": token_usage,
64
+ "response_text": response_text,
65
+ }
66
+
67
+
68
+ @hydra.main(config_path="../../conf", config_name="train_llm.yaml")
69
+ def run_query_on_wandb(cfg: DictConfig):
70
+ """Run Openai LLM and log results on wandb. Config file in conf/train_llm.yaml
71
+
72
+ Args:
73
+ cfg (DictConfig): configuration file for parameters
74
+ """
75
+
76
+ run = wandb.init(
77
+ project=cfg.main.project_name,
78
+ group=cfg.main.experiment_name,
79
+ config=cfg.openai_parameters,
80
+ job_type="train_llm",
81
+ )
82
+
83
+ artifact = run.use_artifact(cfg.parameters.data)
84
+ artifact_path = artifact.file()
85
+ data_frame = pd.read_csv(artifact_path, on_bad_lines="warn").iloc[:, 0].values
86
+
87
+ artifact_st = run.use_artifact(cfg.parameters.system_template)
88
+ artifact_st_path = artifact_st.file()
89
+ system_message = open(artifact_st_path).read()
90
+
91
+ client = OpenAI(api_key=api_key)
92
+
93
+ for _, query in enumerate(data_frame):
94
+ res = run_query(
95
+ client=client,
96
+ system_message=system_message,
97
+ query=query,
98
+ openai_params=cfg.openai_parameters,
99
+ )
100
+
101
+ # create a span in wandb
102
+ root_span = Trace(
103
+ name="root_span",
104
+ kind="llm", # kind can be "llm", "chain", "agent" or "tool"
105
+ status_code=res["status"],
106
+ status_message=res["status_message"],
107
+ metadata={
108
+ "temperature": cfg.openai_parameters.temperature,
109
+ "token_usage": res["token_usage"],
110
+ "model_name": cfg.openai_parameters.model,
111
+ },
112
+ start_time_ms=res["start_time_ms"],
113
+ end_time_ms=res["end_time_ms"],
114
+ inputs={
115
+ "query": query,
116
+ "system_prompt": system_message,
117
+ },
118
+ outputs={"response": res["response_text"]},
119
+ )
120
+ # log the span to wandb
121
+ root_span.log(name="openai_trace")
122
+
123
+
124
+ if __name__ == "__main__":
125
+ run_query_on_wandb()
src/models/openai_stt.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from openai import OpenAI
3
+ import logging
4
+ import hydra
5
+ from dotenv import load_dotenv
6
+ import wandb
7
+ from omegaconf import DictConfig
8
+
9
+
10
+ load_dotenv()
11
+ api_key = os.getenv("OPENAI_API_KEY")
12
+
13
+
14
+ def speech_to_text(audio: bytes, openai_client: OpenAI, configuration: dict) -> str:
15
+ """From the path of an audio file, it generates a text transcription using openai
16
+
17
+ Args:
18
+ audio_path (str): path of the audio containing the query
19
+ openai_client (OpenAI): client for openai connection
20
+
21
+ Returns:
22
+ str: transctiption text
23
+ """
24
+ try:
25
+ # audio_file = open(audio_path, "rb")
26
+ transcription = openai_client.audio.transcriptions.create(
27
+ model=configuration["model"],
28
+ file=audio, # audio_file,
29
+ language=configuration["language"],
30
+ response_format=configuration["response_format"],
31
+ temperature=configuration["temperature"],
32
+ )
33
+
34
+ logging.info("Success: audio converted into text!")
35
+ logging.info(f"Audio transcription: {transcription}")
36
+ return transcription
37
+ except FileNotFoundError as e:
38
+ pass
39
+ logging.error(f"Error: not found - {str(e)}")
40
+ except Exception as e:
41
+ logging.error(f"Error: OpenAI API request failed - {str(e)}")
42
+ return f"error {str(e)}"
43
+
44
+
45
+ @hydra.main(config_path="../../conf", config_name="speech_to_text.yaml")
46
+ def speech_to_text_on_wandb(cfg: DictConfig):
47
+ openai_client = OpenAI()
48
+ run = wandb.init(
49
+ project=cfg.main.project_name,
50
+ group=cfg.main.experiment_name,
51
+ config=cfg.openai_parameters,
52
+ job_type="train_llm",
53
+ )
54
+
55
+ # download artifact
56
+ artifact = run.use_artifact(
57
+ os.path.join("mpoliti08/lux-voice-processing", cfg.main.audio_dataset),
58
+ type="audio",
59
+ )
60
+ artifact_dir = artifact.download()
61
+
62
+ table = wandb.Table(columns=["audio_file", "transcript"])
63
+
64
+ for filename in os.listdir(artifact_dir):
65
+ file_path = os.path.join(artifact_dir, filename)
66
+ audio = open(file_path, "rb")
67
+ transcription_text = speech_to_text(
68
+ audio=audio,
69
+ openai_client=openai_client,
70
+ configuration=cfg.openai_parameters,
71
+ )
72
+
73
+ audio_file = wandb.Audio(file_path)
74
+ table.add_data(audio_file, transcription_text)
75
+
76
+ run.log({"Table": table})
77
+ run.finish()
78
+
79
+
80
+ if __name__ == "__main__":
81
+ openai_client = OpenAI()
82
+ audio_path = "data/audio_recordings/0.wav"
83
+ configuration = {
84
+ "language": "it",
85
+ "model": "whisper-1",
86
+ "response_format": "text",
87
+ "temperature": 0.2,
88
+ }
89
+
90
+ audio = open("data/audio_recordings/0.wav", "rb")
91
+ res = speech_to_text(
92
+ audio=audio, openai_client=openai_client, configuration=configuration
93
+ )
94
+ print(res)
95
+
96
+ # speech_to_text_on_wandb()
src/models/openai_tts.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ from openai import OpenAI
3
+ import os
4
+
5
+ client = OpenAI()
6
+
7
+
8
+ def text_to_speech(client: OpenAI, input: str) -> str:
9
+ generated_speech_path = "data/generated_speech"
10
+ n = len(os.listdir(generated_speech_path))
11
+ response = client.audio.speech.create(
12
+ model="tts-1", voice="nova", response_format="wav", input=input, speed=1.0
13
+ )
14
+
15
+ output_path = os.path.join(generated_speech_path, str(n)) + ".wav"
16
+ response.stream_to_file(output_path)
17
+ return output_path
18
+
19
+
20
+ if __name__ == "__main__":
21
+ input = "Ciao Pinocchio, è vero che la neve è calda? Che ne pensi?"
22
+ openai_client = OpenAI()
23
+ text_to_speech(client=openai_client, input=input)
src/utils.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Utils module"""
2
+
3
+ from datetime import datetime
4
+ import logging
5
+ import pyaudio
6
+ import wave
7
+ import logging
8
+ import os
9
+ import functools
10
+ import yaml
11
+ from types import SimpleNamespace
12
+ import pygame
13
+ import time
14
+ import pyaudio
15
+ import math
16
+ import struct
17
+ import wave
18
+ import time
19
+ import os
20
+ from threading import Thread
21
+ from watchdog.observers import Observer
22
+ from watchdog.events import FileSystemEventHandler
23
+
24
+ format_mapping = {"pyaudio.paInt16": pyaudio.paInt16}
25
+
26
+
27
+ def yaml_file_decorator(yaml_file_path):
28
+ """Decorator to pass a config file to other functions
29
+
30
+ Args:
31
+ yaml_file_path (_type_): path to config file
32
+ """
33
+
34
+ def decorator(func):
35
+ @functools.wraps(func)
36
+ def wrapper(*args, **kwargs):
37
+ # Load YAML file
38
+ with open(yaml_file_path, "r") as file:
39
+ config = yaml.safe_load(file)
40
+
41
+ # Pass the loaded YAML data to the decorated function
42
+ result = func(config, *args, **kwargs)
43
+ return result
44
+
45
+ return wrapper
46
+
47
+ return decorator
48
+
49
+
50
+ @yaml_file_decorator("conf/recording.yaml")
51
+ def record_audio(config) -> str:
52
+ """function to record audio. Configuaration file is in conf/recordings.yaml
53
+
54
+ Args:
55
+ config (dict): configuration of recording parameters
56
+
57
+ Returns:
58
+ recording_path (str): destination path of recorded audio
59
+ """
60
+ config = SimpleNamespace(**config)
61
+ p = pyaudio.PyAudio()
62
+ sample_format = format_mapping.get(config.sample_format, 8)
63
+
64
+ stream = p.open(
65
+ format=sample_format,
66
+ channels=1, # config.channels,
67
+ rate=config.fs * 2,
68
+ frames_per_buffer=config.chunk,
69
+ input=True,
70
+ )
71
+
72
+ frames = [] # Initialize array to store frames
73
+
74
+ # Store data in chunks for 3 seconds
75
+ for i in range(0, int(config.fs / config.chunk * config.seconds)):
76
+ data = stream.read(config.chunk)
77
+ frames.append(data)
78
+
79
+ # Stop and close the stream
80
+ stream.stop_stream()
81
+ stream.close()
82
+ # Terminate the PortAudio interface
83
+ p.terminate()
84
+
85
+ logging.info("Finished recording")
86
+
87
+ # Save the recorded data as a WAV file
88
+ recording_path = os.path.join(config.recording_folder, get_current_time() + ".wav")
89
+ recording_path
90
+ with wave.open(recording_path, "wb") as wf:
91
+ wf.setnchannels(config.channels)
92
+ wf.setsampwidth(p.get_sample_size(sample_format)) # config.sample_format
93
+ wf.setframerate(config.fs)
94
+ wf.writeframes(b"".join(frames))
95
+ wf.close()
96
+ return recording_path
97
+
98
+
99
+ def play_mp3(mp3_file_path):
100
+ try:
101
+ pygame.mixer.init()
102
+ pygame.mixer.music.load(mp3_file_path)
103
+ pygame.mixer.music.play()
104
+
105
+ # Wait for the music to finish playing
106
+ while pygame.mixer.music.get_busy():
107
+ pygame.time.Clock().tick(10)
108
+
109
+ except Exception as e:
110
+ print(f"Error: {e}")
111
+
112
+
113
+ def get_current_time():
114
+ now = datetime.now()
115
+ dt_string = now.strftime("%d-%m-%Y_%H:%M:%S")
116
+ return dt_string
117
+
118
+
119
+ def read_text(file_path: str) -> str:
120
+ try:
121
+ with open(file_path, "r") as file_in:
122
+ text = file_in.read()
123
+ file_in.close()
124
+ logging.info(f"Success: file {file_path} read correctly")
125
+ return text
126
+
127
+ except FileNotFoundError as e:
128
+ logging.error(f"Error: File {file_path} not found - {str(e)}")
129
+ return ""
130
+
131
+
132
+ def get_pyaudio_format(subtype):
133
+ if subtype == "PCM_16":
134
+ return pyaudio.paInt16
135
+ elif subtype == "PCM_8":
136
+ return pyaudio.paInt8
137
+ elif subtype == "PCM_32":
138
+ return pyaudio.paInt32
139
+ else:
140
+ return pyaudio.paInt16
141
+
142
+
143
+ class Recorder:
144
+ """Class to continuosly listen to user input, ans save audio when noise is detected.
145
+ Once noise is detected it will be run the function_to_call with the create filename as parameter
146
+
147
+ Args:
148
+ function_to_call: (function) func to be called with the generated file path as parameter
149
+ """
150
+
151
+ def __init__(self, function_to_call):
152
+ self.Threshold = 10
153
+ self.SHORT_NORMALIZE = 1.0 / 32768.0
154
+ self.chunk = 1024
155
+ self.FORMAT = pyaudio.paInt16
156
+ self.CHANNELS = 1
157
+ self.RATE = 16_000
158
+ self.swidth = 2
159
+ self.TIMEOUT_LENGTH = 2
160
+ self.f_name_directory = r"/Users/marcellopoliti/Documents/Coding/pischool/lux-voice-processing/data/audio_recordings"
161
+ self.function_to_call = function_to_call
162
+
163
+ self.p = pyaudio.PyAudio()
164
+ self.stream = self.p.open(
165
+ format=self.FORMAT,
166
+ channels=self.CHANNELS,
167
+ rate=self.RATE,
168
+ input=True,
169
+ output=True,
170
+ frames_per_buffer=self.chunk,
171
+ )
172
+
173
+ # @staticmethod
174
+ def rms(self, frame):
175
+ count = len(frame) / self.swidth
176
+ format = "%dh" % (count)
177
+ shorts = struct.unpack(format, frame)
178
+
179
+ sum_squares = 0.0
180
+ for sample in shorts:
181
+ n = sample * self.SHORT_NORMALIZE
182
+ sum_squares += n * n
183
+ rms = math.pow(sum_squares / count, 0.5)
184
+
185
+ return rms * 1000
186
+
187
+ def record(self):
188
+ print("Noise detected, recording beginning")
189
+ rec = []
190
+ current = time.time()
191
+ end = time.time() + self.TIMEOUT_LENGTH
192
+
193
+ while current <= end:
194
+
195
+ data = self.stream.read(self.chunk)
196
+ if self.rms(data) >= self.Threshold:
197
+ end = time.time() + self.TIMEOUT_LENGTH
198
+
199
+ current = time.time()
200
+ rec.append(data)
201
+ filename = self.write(b"".join(rec))
202
+ return filename
203
+
204
+ def write(self, recording):
205
+ n_files = len(os.listdir(self.f_name_directory))
206
+
207
+ filename = os.path.join(self.f_name_directory, "{}.wav".format(n_files))
208
+
209
+ wf = wave.open(filename, "wb")
210
+ wf.setnchannels(self.CHANNELS)
211
+ wf.setsampwidth(self.p.get_sample_size(self.FORMAT))
212
+ wf.setframerate(self.RATE)
213
+ wf.writeframes(recording)
214
+ wf.close()
215
+ logging.info("Written to file: {}".format(filename))
216
+ return filename
217
+
218
+ def listen(self):
219
+ print("Listening beginning")
220
+ while True:
221
+ input = self.stream.read(self.chunk, exception_on_overflow=False)
222
+ rms_val = self.rms(input)
223
+ if rms_val > self.Threshold:
224
+ filename = self.record()
225
+ self.function_to_call(filename)
226
+
227
+
228
+ # Function to check for new recordings and print a message
229
+ def check_for_new_recordings(function_to_call):
230
+ previous_files = set(os.listdir("audio_recordings"))
231
+
232
+ while True:
233
+ current_files = set(os.listdir("audio_recordings"))
234
+ new_files = current_files - previous_files
235
+
236
+ for new_file in new_files:
237
+ print(f"New recording detected: {new_file}")
238
+ function_to_call(new_file)
239
+ print("Returning to listening")
240
+
241
+ previous_files = current_files
242
+ time.sleep(2) # Check for new recordings every 2 seconds
243
+
244
+
245
+ if __name__ == "__main__":
246
+ recordings_path = record_audio()
src/utils/add_artifact.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Upload file to wandb
3
+ to upload dir:
4
+ export WANDB_PROJECT='lux-voice-processing'
5
+ wandb artifact put --type audio --name recordings_dataset data/audio_recordings
6
+ """
7
+
8
+ import wandb
9
+ import argparse
10
+ import os
11
+ import logging
12
+
13
+
14
+ def upload_data(args):
15
+ """upload artifact on wandb
16
+
17
+ Args:
18
+ args (dict): project, name, type, local_path
19
+ """
20
+ if os.path.exists(args.local_path):
21
+ run = wandb.init(
22
+ project=args.project, job_type="add-artifact", group="add-artifact"
23
+ )
24
+ artifact = wandb.Artifact(name=args.name, type=args.type)
25
+ artifact.add_file(local_path=args.local_path)
26
+ run.log_artifact(artifact)
27
+ run.finish()
28
+ else:
29
+ print(f"File does not exist: {args.local_path}")
30
+
31
+
32
+ # TODO: not working
33
+ def upload_dir(args):
34
+ """upload dir artifact on wandb
35
+
36
+ Args:
37
+ args (dict): project, name, type, local_path
38
+ """
39
+ try:
40
+ if os.path.isdir(args.local_path):
41
+ run = wandb.init(
42
+ project=args.project, job_type="add-artifact", group="add-artifact"
43
+ )
44
+ artifact = wandb.Artifact(name=args.name, type=args.type)
45
+ artifact.add_dir(
46
+ local_path="/Users/marcellopoliti/Documents/Coding/pischool/lux-voice-processing/data/audio_recordings"
47
+ )
48
+ run.log_artifact(artifact)
49
+ run.finish()
50
+ else:
51
+ logging.error(f"Not dir: {args.local_path}")
52
+ except Exception as e:
53
+ logging.exception(f"Exception: {str(e)} {type(e).__name__} ")
54
+
55
+
56
+ if __name__ == "__main__":
57
+ parser = argparse.ArgumentParser(description="Arguments for LLM monitoring")
58
+
59
+ parser.add_argument(
60
+ "--project",
61
+ type=str,
62
+ help="wandb project name",
63
+ default="lux-voice-processing",
64
+ )
65
+
66
+ parser.add_argument(
67
+ "--local_path",
68
+ type=str,
69
+ help="local path of your artifact",
70
+ required=True,
71
+ )
72
+
73
+ parser.add_argument(
74
+ "--name",
75
+ type=str,
76
+ help="name of your artifact",
77
+ required=True,
78
+ )
79
+
80
+ parser.add_argument(
81
+ "--type",
82
+ type=str,
83
+ help="type of your artifact",
84
+ required=True,
85
+ )
86
+
87
+ parser.add_argument(
88
+ "--isdir", type=bool, help="is dir?", required=False, default=False
89
+ )
90
+ args = parser.parse_args()
91
+
92
+ if args.isdir:
93
+ print("uploading dir... ", args.local_path)
94
+ upload_data(args)
95
+ else:
96
+ print("uploading file...")
97
+ upload_dir(args)