diff --git a/bot/.DS_Store b/bot/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9481c57c3545a97ed7631c7ca6a13098de8cf0a9 Binary files /dev/null and b/bot/.DS_Store differ diff --git a/bot/.views.py.swp b/bot/.views.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..a4f11d3149d341c8299ffe646d422067a227e23d Binary files /dev/null and b/bot/.views.py.swp differ diff --git a/bot/__init__.py b/bot/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bot/__pycache__/__init__.cpython-311.pyc b/bot/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d7ec5ba82ab48a8cf975c5b26f274e893bd3e4a Binary files /dev/null and b/bot/__pycache__/__init__.cpython-311.pyc differ diff --git a/bot/__pycache__/admin.cpython-311.pyc b/bot/__pycache__/admin.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1c1308ae274e519b57c4c3f5ee19d66d830d1da Binary files /dev/null and b/bot/__pycache__/admin.cpython-311.pyc differ diff --git a/bot/__pycache__/apps.cpython-311.pyc b/bot/__pycache__/apps.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe4667ef2015a5df4283f5a480ca9dd6189e6879 Binary files /dev/null and b/bot/__pycache__/apps.cpython-311.pyc differ diff --git a/bot/__pycache__/forms.cpython-311.pyc b/bot/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4875e771ce582bf2e98362d57c91bd85da73f875 Binary files /dev/null and b/bot/__pycache__/forms.cpython-311.pyc differ diff --git a/bot/__pycache__/models.cpython-311.pyc b/bot/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d3d9a67289811ec37124a9be35325eab1d123f8f Binary files /dev/null and b/bot/__pycache__/models.cpython-311.pyc differ diff --git a/bot/__pycache__/uchat.cpython-311.pyc b/bot/__pycache__/uchat.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68d67738c3706886ae76a48b16363e00577b7728 Binary files /dev/null and b/bot/__pycache__/uchat.cpython-311.pyc differ diff --git a/bot/__pycache__/urls.cpython-311.pyc b/bot/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..79cffa3d54c1921bc24f6bcde2f4765388971a31 Binary files /dev/null and b/bot/__pycache__/urls.cpython-311.pyc differ diff --git a/bot/__pycache__/views.cpython-311.pyc b/bot/__pycache__/views.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b91af19a40293677ed0f63c02b2760cacaaf699d Binary files /dev/null and b/bot/__pycache__/views.cpython-311.pyc differ diff --git a/bot/admin.py b/bot/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..d2603b4dadf244117d35402843eb333eff899e02 --- /dev/null +++ b/bot/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import Language + +admin.site.register(Language) + +# Register your models here. diff --git a/bot/apps.py b/bot/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..1cd7ff2e777438a9e2f10782d5aa55ef1771e290 --- /dev/null +++ b/bot/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class BotConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'bot' diff --git a/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/data_level0.bin b/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/data_level0.bin new file mode 100644 index 0000000000000000000000000000000000000000..3bf7f64f1cf859f471927741ee5f63cab647f989 --- /dev/null +++ b/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/data_level0.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a0f748340f882ae5b8ef64a529d2782a281c1fa7bb7be42203e031a07c2a2dd +size 1676000 diff --git a/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/header.bin b/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/header.bin new file mode 100644 index 0000000000000000000000000000000000000000..ae84e682423ff4214c2e9df782b8799815882036 --- /dev/null +++ b/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/header.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e87a1dc8bcae6f2c4bea6d5dd5005454d4dace8637dae29bff3c037ea771411e +size 100 diff --git a/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/length.bin b/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/length.bin new file mode 100644 index 0000000000000000000000000000000000000000..e67612f606022f56e002762d953c6ce30450144d --- /dev/null +++ b/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/length.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d5aebd05d5bf364ed999da7c13f7ef2101df1dc00f19fc87758d2d7cc067582 +size 4000 diff --git a/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/link_lists.bin b/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/link_lists.bin new file mode 100644 index 0000000000000000000000000000000000000000..fc8e42b32efb9a9bf3ae0234a18a948e499490f8 --- /dev/null +++ b/bot/chroma_data/71205607-97fb-4292-8492-28d8f0cc5fef/link_lists.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +size 0 diff --git a/bot/chroma_data/chroma.sqlite3 b/bot/chroma_data/chroma.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..4559a609960e53079411eeb1b9e3875a9a374e69 Binary files /dev/null and b/bot/chroma_data/chroma.sqlite3 differ diff --git a/bot/forms.py b/bot/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..7e1176596dc67a98333895e785477e8574d9c552 --- /dev/null +++ b/bot/forms.py @@ -0,0 +1,62 @@ +from django.core.exceptions import ValidationError +#from django.utils.translation import gettext_lazy as _ + +from django import forms + +class RenewBotForm(forms.Form): + query = forms.CharField( + help_text="Unesite upit: ") + jezik = forms.CharField( + help_text="Odaberite jezik") +# def clean_query(self): +# data = self.cleaned_data['query'] +# data = self.cleaned_data['jezik'] +# return data + +class EditorForm(forms.Form): + id = forms.CharField(help_text="id") + state = forms.CharField(help_text="Početno stanje") + next = forms.CharField(help_text="Završno stanje") + page = forms.IntegerField(help_text="Stranica") + used = forms.CharField(help_text="Upotrebljen (Bool)") + docu = forms.CharField(help_text="Dokument konteksta") + source = forms.CharField(help_text="URL dokumenta") + jezik = forms.CharField(help_text="Odaberite jezik") +# def clean_query(self): +# data = self.cleaned_data['source'] +# return data + +class EditorListForm(forms.Form): + f_id = forms.IntegerField(help_text="id filter") + f_jezik = forms.CharField(help_text="jezik filter") + f_state = forms.CharField(help_text="state filter") + f_next = forms.CharField(help_text="next filter") + f_page = forms.IntegerField(help_text="page filter") + f_docu = forms.CharField(help_text="document filter") + +class ParamForm(forms.Form): + system = forms.CharField(help_text="Enter parameter value") + ctxpre = forms.CharField(help_text="Enter parameter value") + msg_content = forms.CharField(help_text="Enter parameter value") + min_len = forms.IntegerField(help_text="Enter parameter value") + CHUNK_SIZE = forms.IntegerField(help_text="Enter parameter value") + CHUNK_OVERLAP = forms.IntegerField(help_text="Enter parameter value") + max_results = forms.IntegerField(help_text="Enter parameter value") + EMBED_MODEL = forms.CharField(help_text="Enter parameter value") + model_id = forms.CharField(help_text="Enter parameter value") + max_results = forms.IntegerField(help_text="Enter parameter value") + max_conv = forms.IntegerField(help_text="Enter parameter value") + min_len = forms.IntegerField(help_text="Enter parameter value") + min_distance = forms.FloatField(help_text="Enter parameter value") + max_distance = forms.FloatField(help_text="Enter parameter value") + temperature = forms.FloatField(help_text="Enter parameter value") + max_tokens = forms.IntegerField(help_text="Enter parameter value") + top_p = forms.FloatField(help_text="Enter parameter value") + frequency_penalty = forms.FloatField(help_text="Enter parameter value") + presence_penalty = forms.FloatField(help_text="Enter parameter value") + DEBUG = forms.CharField(help_text="Enter parameter value (Bool)") + jezik = forms.CharField(help_text="Uneti jezik") + +class ImportForm(forms.Form): + path = forms.CharField(help_text="Unesite putanju do PDF dokumenta") + jezik = forms.CharField(help_text="Unesite jezik") diff --git a/bot/migrations/0001_initial.py b/bot/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..6baaa84b46cce126e74fe2276e27dc8cfdce632d --- /dev/null +++ b/bot/migrations/0001_initial.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.3 on 2024-04-04 02:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Language', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Enter language (e.g. English, French, Japanese etc.)', max_length=200, unique=True)), + ], + ), + ] diff --git a/bot/migrations/0002_query.py b/bot/migrations/0002_query.py new file mode 100644 index 0000000000000000000000000000000000000000..cfb62e47d094aaeb14dc4543e349025152071867 --- /dev/null +++ b/bot/migrations/0002_query.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.3 on 2024-04-06 04:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bot', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Query', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField(help_text='Unesite upit', max_length=1000)), + ('jezik', models.CharField(help_text='Odaberite jezik!', max_length=16)), + ], + ), + ] diff --git a/bot/migrations/0003_rename_text_query_query_language_lid_query_reply_and_more.py b/bot/migrations/0003_rename_text_query_query_language_lid_query_reply_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..ef6b39b16a0d434e351311c20becb7e484bc7555 --- /dev/null +++ b/bot/migrations/0003_rename_text_query_query_language_lid_query_reply_and_more.py @@ -0,0 +1,35 @@ +# Generated by Django 5.0.3 on 2024-04-10 18:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bot', '0002_query'), + ] + + operations = [ + migrations.RenameField( + model_name='query', + old_name='text', + new_name='query', + ), + migrations.AddField( + model_name='language', + name='lid', + field=models.CharField(default='sr', help_text='Unesite kratak naziv jezika', max_length=2), + preserve_default=False, + ), + migrations.AddField( + model_name='query', + name='reply', + field=models.TextField(default='default', help_text='Unesite odgovor', max_length=1000), + preserve_default=False, + ), + migrations.AlterField( + model_name='language', + name='name', + field=models.CharField(help_text='Unesite jezik', max_length=16, unique=True), + ), + ] diff --git a/bot/migrations/0004_param_alter_language_lid_alter_language_name.py b/bot/migrations/0004_param_alter_language_lid_alter_language_name.py new file mode 100644 index 0000000000000000000000000000000000000000..e6be5fbf76b84830077d3d2107e3fde3c0dab704 --- /dev/null +++ b/bot/migrations/0004_param_alter_language_lid_alter_language_name.py @@ -0,0 +1,48 @@ +# Generated by Django 5.0.3 on 2024-04-22 03:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bot', '0003_rename_text_query_query_language_lid_query_reply_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='Param', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('system', models.TextField(default='System prpmpt', help_text='Enter parameter value', max_length=2048)), + ('ctxpre', models.CharField(blank=True, help_text='Enter parameter value', max_length=80)), + ('msg_content', models.CharField(blank=True, help_text='Enter parameter value', max_length=80)), + ('min_len', models.IntegerField(default=40, help_text='Enter parameter value')), + ('CHUNK_SIZE', models.IntegerField(default=800, help_text='Enter parameter value')), + ('CHUNK_OVERLAP', models.IntegerField(default=50, help_text='Enter parameter value')), + ('max_results', models.IntegerField(default=3, help_text='Enter parameter value')), + ('EMBED_MODEL', models.CharField(default='embeddings model', help_text='Enter parameter value', max_length=256)), + ('model_id', models.CharField(default='LLM model', help_text='Enter parameter value', max_length=256)), + ('max_conv', models.IntegerField(default=3, help_text='Enter parameter value')), + ('min_distance', models.FloatField(default=0.35, help_text='Enter parameter value')), + ('max_distance', models.FloatField(default=0.6, help_text='Enter parameter value')), + ('temperature', models.FloatField(default=0.55, help_text='Enter parameter value')), + ('max_tokens', models.IntegerField(default=3072, help_text='Enter parameter value')), + ('top_p', models.FloatField(default=0.8, help_text='Enter parameter value')), + ('frequency_penalty', models.FloatField(default=0.0, help_text='Enter parameter value')), + ('presence_penalty', models.FloatField(default=0.0, help_text='Enter parameter value')), + ('DEBUG', models.BooleanField(default=True, help_text='Enter parameter value')), + ('jezik', models.CharField(default='srpski', help_text='Uneti jezik', max_length=16)), + ], + ), + migrations.AlterField( + model_name='language', + name='lid', + field=models.CharField(default='sr', help_text='Unesite kratak naziv jezika', max_length=2), + ), + migrations.AlterField( + model_name='language', + name='name', + field=models.CharField(default='srpski', help_text='Unesite jezik', max_length=16, unique=True), + ), + ] diff --git a/bot/migrations/__init__.py b/bot/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/bot/migrations/__pycache__/0001_initial.cpython-311.pyc b/bot/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8308ec5216cc8a0417dbba725aa93e5a1dd759b4 Binary files /dev/null and b/bot/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/bot/migrations/__pycache__/0002_query.cpython-311.pyc b/bot/migrations/__pycache__/0002_query.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..239d8c40111579b7493f56e3caa8883ce4d8d279 Binary files /dev/null and b/bot/migrations/__pycache__/0002_query.cpython-311.pyc differ diff --git a/bot/migrations/__pycache__/0003_rename_text_query_query_language_lid_query_reply_and_more.cpython-311.pyc b/bot/migrations/__pycache__/0003_rename_text_query_query_language_lid_query_reply_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cae4713130a4358a6d00fe58723684ba0f00cc97 Binary files /dev/null and b/bot/migrations/__pycache__/0003_rename_text_query_query_language_lid_query_reply_and_more.cpython-311.pyc differ diff --git a/bot/migrations/__pycache__/0004_param_alter_language_lid_alter_language_name.cpython-311.pyc b/bot/migrations/__pycache__/0004_param_alter_language_lid_alter_language_name.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ebe9ca95108d693d13f4b44051b6a561fb619a5 Binary files /dev/null and b/bot/migrations/__pycache__/0004_param_alter_language_lid_alter_language_name.cpython-311.pyc differ diff --git a/bot/migrations/__pycache__/__init__.cpython-311.pyc b/bot/migrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c6197d20730c768e3fa0f896873b96165b82644 Binary files /dev/null and b/bot/migrations/__pycache__/__init__.cpython-311.pyc differ diff --git a/bot/models.py b/bot/models.py new file mode 100644 index 0000000000000000000000000000000000000000..906c39ed7de4f0d3439d7974df2bd786e3060d1f --- /dev/null +++ b/bot/models.py @@ -0,0 +1,64 @@ +from django.db import models +from django.urls import reverse +from django.forms import ModelForm + +class Query(models.Model): + query = models.TextField( + max_length=1000, help_text="Unesite upit") + reply = models.TextField( + max_length=1000, help_text="Unesite odgovor") + jezik = models.CharField( + max_length=16, help_text="Odaberite jezik!") + def get_absolute_url(self): + return reverse('query', args=[str(self.id)]) + def __str__(self): + return self.text + +#class QueryForm(ModelForm): +# class Meta: +# model = Query +# fields = ['query', 'reply', 'jezik'] + +class Language(models.Model): + name = models.CharField(max_length=16, + unique=True, + default="srpski", + help_text="Unesite jezik") + lid = models.CharField(max_length=2, unique=False, default="sr", help_text="Unesite kratak naziv jezika") + def get_absolute_url(self): + """Returns the url to access a particular language instance.""" + return reverse('bot-detail', args=[str(self.id)]) + def __str__(self): + """String for representing the Model object (in Admin site etc.)""" + return self.name + +class LanguageForm(ModelForm): + class Meta: + model = Language + fields = ['name', 'lid'] + +class Param(models.Model): + system = models.TextField(max_length=2048, unique=False, blank=False, default="System prpmpt", help_text="Enter parameter value") + ctxpre = models.CharField(max_length=80, unique=False, blank=True, help_text="Enter parameter value") + msg_content = models.CharField(unique=False, blank=True, max_length=80, help_text="Enter parameter value") + min_len = models.IntegerField(unique=False, blank=False, default=40, help_text="Enter parameter value") + CHUNK_SIZE = models.IntegerField(unique=False, blank=False, default=800, help_text="Enter parameter value") + CHUNK_OVERLAP = models.IntegerField(unique=False, blank=False, default=50, help_text="Enter parameter value") + max_results = models.IntegerField(unique=False, blank=False, default=3, help_text="Enter parameter value") + EMBED_MODEL = models.CharField(max_length=256, default="embeddings model", help_text="Enter parameter value") + model_id = models.CharField(max_length=256, unique=False, default="LLM model", blank=False, help_text="Enter parameter value") + max_conv = models.IntegerField(unique=False, blank=False, default=3, help_text="Enter parameter value") + min_distance = models.FloatField(unique=False, blank=False, default=0.35, help_text="Enter parameter value") + max_distance = models.FloatField(unique=False, blank=False, default=0.6, help_text="Enter parameter value") + temperature = models.FloatField(unique=False, blank=False, default=0.55, help_text="Enter parameter value") + max_tokens = models.IntegerField(unique=False, blank=False, default=3072, help_text="Enter parameter value") + top_p = models.FloatField(unique=False, blank=False, default=0.8, help_text="Enter parameter value") + frequency_penalty = models.FloatField(unique=False, default=0.0, blank=False, help_text="Enter parameter value") + presence_penalty = models.FloatField(unique=False, default=0.0, blank=False, help_text="Enter parameter value") + DEBUG = models.BooleanField(unique=False, blank=False, default=True, help_text="Enter parameter value") + jezik = models.CharField(max_length=16, unique=False, blank=False, default="srpski", help_text="Uneti jezik") + +class ParamModelForm(ModelForm): + class Meta: + model = Param + fields = [ 'system', 'ctxpre', 'msg_content', 'min_len', 'CHUNK_SIZE', 'CHUNK_OVERLAP', 'max_results', 'EMBED_MODEL', 'model_id', 'max_conv', 'min_distance', 'max_distance', 'temperature', 'max_tokens', 'top_p', 'frequency_penalty', 'presence_penalty', 'DEBUG', 'jezik'] diff --git a/bot/static/css/styles.css b/bot/static/css/styles.css new file mode 100644 index 0000000000000000000000000000000000000000..53e08223f3218e926b42da8dea1d053120cb4d20 --- /dev/null +++ b/bot/static/css/styles.css @@ -0,0 +1,5 @@ +.sidebar-nav { + margin-top: 20px; + padding: 0; + list-style: none; +} diff --git a/bot/test.wsgi b/bot/test.wsgi new file mode 100644 index 0000000000000000000000000000000000000000..4d15f05f3a3acb572f79edfd2c0eab8fcbbf9246 --- /dev/null +++ b/bot/test.wsgi @@ -0,0 +1,7 @@ +def application(environ, start_response): + status = '200 OK' + output = b'Hello World!' + response_headers = [('Content-type', 'text/plain'), + ('Content-Length', str(len(output)))] + start_response(status, response_headers) + return [output] diff --git a/bot/tests.py b/bot/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..50c338b30647c96c55543644cbe6a216a0bad118 --- /dev/null +++ b/bot/tests.py @@ -0,0 +1,38 @@ +from django.test import TestCase + +# Create your tests here. + + +from catalog.models import Language +from django.urls import reverse + + +class LanguageViewTest(TestCase): + + @classmethod + def setUpTestData(cls): + langs = [ 'Hrvatski', 'Slovenački', 'Srpski', 'Bosanski', 'Makedonski', 'Bugarski'] + for lang in langs: + l = Language.objects.create(name=lang) ; l.save() + +import datetime +from django.utils import timezone + +from bot.models import Language + +# Get user model from settings +from django.contrib.auth import get_user_model +User = get_user_model() + +class UserViewTest(TestCase): + + def setUp(self): + # Create two users + test_user1 = User.objects.create_user( + username='testuser1', password='testuser1') + test_user2 = User.objects.create_user( + username='testuser2', password='testuser2') + + test_user1.save() + test_user2.save() + diff --git a/bot/tests/__init__.py b/bot/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/bot/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/bot/tests/__pycache__/__init__.cpython-311.pyc b/bot/tests/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f832b5e6e1d5be12a5c95bf0dfa2ce81ef59f797 Binary files /dev/null and b/bot/tests/__pycache__/__init__.cpython-311.pyc differ diff --git a/bot/tests/test_views.py b/bot/tests/test_views.py new file mode 100644 index 0000000000000000000000000000000000000000..50c338b30647c96c55543644cbe6a216a0bad118 --- /dev/null +++ b/bot/tests/test_views.py @@ -0,0 +1,38 @@ +from django.test import TestCase + +# Create your tests here. + + +from catalog.models import Language +from django.urls import reverse + + +class LanguageViewTest(TestCase): + + @classmethod + def setUpTestData(cls): + langs = [ 'Hrvatski', 'Slovenački', 'Srpski', 'Bosanski', 'Makedonski', 'Bugarski'] + for lang in langs: + l = Language.objects.create(name=lang) ; l.save() + +import datetime +from django.utils import timezone + +from bot.models import Language + +# Get user model from settings +from django.contrib.auth import get_user_model +User = get_user_model() + +class UserViewTest(TestCase): + + def setUp(self): + # Create two users + test_user1 = User.objects.create_user( + username='testuser1', password='testuser1') + test_user2 = User.objects.create_user( + username='testuser2', password='testuser2') + + test_user1.save() + test_user2.save() + diff --git a/bot/uchat-old.py b/bot/uchat-old.py new file mode 100644 index 0000000000000000000000000000000000000000..c6eb3175507ca07ff6f412ccff4b920ebe3d5982 --- /dev/null +++ b/bot/uchat-old.py @@ -0,0 +1,322 @@ +import chromadb +from chromadb.utils import embedding_functions +import os +from transformers import AutoModelForCausalLM, AutoTokenizer +import torch +from openai import OpenAI +from langchain_community.document_loaders import PyPDFLoader +from langchain.text_splitter import RecursiveCharacterTextSplitter +from itertools import islice, zip_longest +import re + +#model_id = "mistralai/Mistral-7B-Instruct-v0.2" +#tokenizer = AutoTokenizer.from_pretrained(model_id) +model_id = "Yugo60-GPT-GGUF.Q4_K_M.gguf" + +#inputs = tokenizer(text, return_tensors="pt").to(0) + +#outputs = model.generate(**inputs, max_new_tokens=20) +#print(tokenizer.decode(outputs[0], skip_special_tokens=True)) + +if not torch.backends.mps.is_available(): + if not torch.backends.mps.is_built(): + print("MPS not available because the current PyTorch install was not " + "built with MPS enabled.") + else: + print("MPS not available because the current MacOS version is not 12.3+ " + "and/or you do not have an MPS-enabled device on this machine.") +else: + torch.set_default_device("mps") + +model = "" +CHROMA_DATA_PATH = "chroma_data/" +EMBED_MODEL = "all-MiniLM-L6-v2" +# NousResearch/Hermes-2-Pro-Mistral-7B +# distilbert-base-multilingual-case +# paraphrase-multilingual-MiniLM-L12-v2d +COLLECTION_NAME = "chroma_data" +PDF_PATH = "./PDF/uputstvo_uz_eon_smart_box-1.pdf" +PDF_PATH2 = "./PDF/uputstvo_uz_eon_smart_aplikaciju-1.pdf" +CHUNK_SIZE = 800 +CHUNK_OVERLAP = 50 +max_results = 3 +min_len = 40 + +def load_and_split_document(pdf_path): + loader = PyPDFLoader(pdf_path) + print('Loaded: ' + pdf_path) + return loader.load_and_split() + +def split_text_into_chunks(pages, chunk_size, chunk_overlap): + n = -1 + for page in range(len(pages)): pages[page].page_content = re.sub(r'\s+'," ", pages[page].page_content.replace(". .","").replace(r'\n','.')).replace('..','') + for p in range(len(pages)): + if len(pages[p].page_content)=0: + pages[n]=pages[p]; n += 1 + if n>0: pages = pages[:n-1] + text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap) + return text_splitter.split_documents(pages) + +def batched(iterable, n): + it = iter(iterable) + while True: + batch = list(islice(it, n)) + if not batch: + return + yield batch + +client = chromadb.PersistentClient(path=CHROMA_DATA_PATH) +client.allow_reset = True +client.delete_collection(COLLECTION_NAME) + +oc = OpenAI(base_url="http://localhost:4891/v1", api_key="not-needed") + +docs = [ + "s0", [ + [ + "", + "Navedite, da li je problem sa EON uređajem, upravljačem ili WiFi mrežom?", + "Problem sa TV odabirom sadržaja, prijemom signala ili dostupnošću usluga?", + "Problem sa naplatom usluga?", + ], + [ "s00", "Ako korisnik ima problema sa prijemom kablovskog signala ili slikom, proveriti EON SMART BOX uređaj", "Ako korisnik ima problem sa EON SMART BOX uređajem ili aplikacijom, treba proveriti EON podešavanja", "Ako je korisniku poptpuno crn ekran, proveriti resetovanje EON SMART BOX uređaja ili aplikacije" ], + [ "s01", "Ako nee radi internet korisniku, treba proveriti kablovski prijem", "Ako ne radi WiFi korisniku, onda proveriti priključen WiFI ruter" ], + [ "s02", "Ako korisnik ima problema sa izborom kanala, proveriti podešavanja ili pretplatu", "Ako ne radi daljinski upravljač, proveriti EON SMART BOX uređaj" ], + [ "s03", "Ako korisnik ima problema s plaćanjem pretplate, neka ga proveri ili izmiri na web stranici ili najbližoj filijali.", "Ako korisnik dobije poruku o neizmirenim obavezama na ekranu, neka proveri stanje pretplate na web strasnici ili u najbližoj filijali.", "Ako korisnik želi proveru stanja bez web stranice ili filijale, neka se obrati Call centru", "Ako korisnik želi naplatu obaveza ili promenu paketa usluga, neka se obrati Call centru." ], + ], + "s00", [ + [ + "Ako korisnik nije resetovao EON SMART BOX uređaj ili aplikaciju, neka pokuša da ga restartuje, kao i TV uređaj.", + "Ako problem korisniku nije rešen resetovanjem, onda ga uputiti na Call centar.", + ], + [ "s000", "Ako je resetovanje bilo uspešno, ali korisnik i dalje ima problem, neka se obrati call centru.", "Ako korisnik ne zna kako da resetuje uređaj, neka ga isključi iz struje na nekoliko sekundi, i ponovo uključi." ], + [ "s99", "Ako je korisniku nejasan odgovor, neka se obrati Call centru."], + ], + "s01", [ + [ + "Ako korisnik ima problema sa internetom, neka pokuša da restartuje WiFi ruter.", + "Ako se korisniku problem nastavlja i nakon resetovanja, neka pokuša sa resetovanje EON SMART BOX i WiFI uređaja.", + ], + [ "s010", "Ako korisnik ima problem sa prijemom kablovskog i internet signala, a resetovanje nije pomoglo, neka se obrati Call centru.", "Ako korisnik ima kablovski prijem, ali mu internet ne radi, neka proveri da li radim ping 8.8.8.8"], + [ "s00", "Ako korisnik ima kablovski prijem, ali internet ne radi, neka resetuje WiFI rutter", "Ako korisnuku rade TV kanali ali ne i internet, neka resetuje WiFI ruter", "Ako korisnik može gledati TV ali mu internet ne radi, neka resetuje WiFi ruter."], + [ "s99", "Ako je korisniku nejasan odgovor, neka se obrati Call centru." ], + ], + "s02", [ + [ + "Ako korisniku nisu dostpni samo pojedini kanali, neka proveri stanje pretplate.", + "Ako korisniku nije dostupna nijedna funkcija na daljinskom upravljaču, neka pokuša da promeni baterije ili daljinski upravljać.", + ], + [ "s03", "Ako korisnik želi da promeni paket usluga, neka se obrati Call centru.", "Ako korisnik želi da proveri stanje pretplate na svom računu, neka proveri stanje na web stranici ili preko Call centra." ], + [ "s99", "Ako je korisniku nejasan odgovor, neka se obrati Call centru." ], + ], + "s03", [ + [ + "Ako niste izmirili Vaše redovne obaveze, možete to učiniti online, ili putem najbližeg predstavništva.", + ], + [ "s99", "Ako je korisniku nejasan odgovor, neka se obrati Call centru." ], + ], + "s09", [ + [ + "Kontaktirajte Call centar za korisničku podrškua na 0800123123123", + ], + [ "s0", "Ako je korisniku nejasan odgovor, neka se obrati Call centru."] + ], + "s000", [ + [ + "Ako korisnik ne zna kako da resetuje uređaj ili aplikaciju, neka isključi uređaj iz struje, i nakon nekoliko sekundi ponovo ga uključi.", + ], + [ "s99", "Ako korisniku i dalje ima problem, neka se obrati Call centru.", "Ako korisnik ima novi problem, zahtevaj pojašnjenje." ], + ], + "s010", [ + [ + "Ako korisniku radi ping a ima problem sa internetom, neka pokuša da postavi u svom browser-u ili mrežnim podešavanjima korisničkog uređaja 8.8.8.8 kao DNS", + ], + [ "s99", "Ako se korisnik žali da mu nešto ne radi i dalje, uputite ga na Call centar", "Ako korisniku ne pomaže odgovor, neka se obrati Call centru." ], + ], + "s99", [ + [ + "Odgovorite korisniku na sledeći način isključivo: Žao mi je, ali ne mogu Vam pomoći. Kontaktirajte Call centar na 08001231231223" + ], + [ "s0", "Ako je korisniku nejasan odgovor, neka se obrati Call centru." ], + ] +] + +if not os.path.exists(CHROMA_DATA_PATH): + os.makedirs(CHROMA_DATA_PATH) + +chroma_client = chromadb.PersistentClient(CHROMA_DATA_PATH) + +embedding_func = embedding_functions.SentenceTransformerEmbeddingFunction( + model_name=EMBED_MODEL + ) + +collection = chroma_client.get_or_create_collection( + name="chroma_data", + embedding_function=embedding_func, + metadata={"hnsw:space": "cosine"}, + ) + +#async function main() { +last = 0 +state = -2 +used =[] +for g in docs[0::2]: + state += 2 + documents=docs[state+1][0] + collection.add( + documents=documents, + ids=[f"id{last+i}" for i in range(len(documents))], + metadatas=[{"state": g, "next": g, "used": False, "source": 'None', "page": -1 } for i in range(len(documents)) ] + ) + for i in range(len(documents)): used += [0] + last += len(documents) + if (len(docs[state+1])>1): + for n in docs[state+1][1:]: + collection.add( + documents=n[1:], + ids=[f"id{last+i-1}" for i in range(1,len(n))], + metadatas=[{"state": g, "next": n[0], "used": False, "source": 'None', "page": -1 } for i in range(1,len(n)) ] + ) + for i in range(1,len(n)): used += [0] + last += len(n)-1 + +state += 2 +docus = load_and_split_document(PDF_PATH) + load_and_split_document(PDF_PATH2) + +pages = split_text_into_chunks(docus, CHUNK_SIZE, CHUNK_OVERLAP) +document_indices = list(range(len(pages))) +for batch in batched(document_indices, 166): + collection.add( + ids=[f"id{last+batch[i]}" for i in range(len(batch))], + documents=[pages[i].page_content for i in batch], + metadatas=[dict(dict(dict(pages[i].metadata, used=False), next='None'), state='None') for i in batch], + ) + last += len(batch) + +msg = "Pomozite mi sa EON uslugama" +system_content = "Korisnik User ispod postavlja pitanje ili zadatak, upareno sa unosom koji pruža dodatni mogući kontekst. Napišite odgovor na srpskom jeziku, koji na odgovarajući način kompletira zahtev ili daje odgovor na pitanje. EON je deo usluga preduzeća United Group, koje uključuju i kablovsku mrežu za digitalnu televiziju, pristup internetu, uređaj EON SMART BOX za TV sadržaj, i fiksnu telefoniju. Korisnik se može obratiti Call centru telefonom na 080012341234, ili otiči do najbliže filijale ako mu ne pomaže odgovor." +#system_content = "Zoveš se Assistant. Ogovaraj ljubazno na pitanja i probleme koje postavlja korisnik koji se zove User." +#msg_content = "odgovori mi na ovo pitanje ili problem kroz sumiranje sledećih delova uputstava, od kojih se samo neka odnose na postavljeno pitanje ili problem: " +msg_content = "dodatni mogući kontekts je: " +ns = cs = "s0" +messages = context = [] +reply = ctx = "" +print ("Recite kako Vam mogu pomoći ...") +ctx_flag = True +previous = "" +while True: + print() + show = False + msg = input("User> ") + print() + if msg=="###": + show = True + print("ctx: ", ctx, ", len=", len(context)) + print("reply=", reply) + print("msg: ", messages) + msg = input("User> ") + print() + if msg=="###": break + query_results = collection.query( + query_texts = [ msg ], + n_results = max_results, + where = { "$and": [ { "$or": [ {"state": cs }, { "page": { "$nin": [ -1 ] } } ] } , { "used": False } ] } + ) + ln = len(query_results["documents"]) + ctx = "" + context = [] + for n in range(ln): + context += query_results["documents"][n] + for n in range(len(context)): + ctx += context[n] + ", " + ctx = ctx[:-2] + if messages==[]: + messages=[ + {"role": "system", "content": system_content}, + {"role": "user", "content": f"{msg} - " + msg_content + ctx + "."} + ] + else: + if ctx_flag: + new_message = [ + {"role": "user", "content": f"{msg}" + msg_content + ctx + "."} + ] + else: + new_message = [ + # {"role": "system", "content": [system_content] + context}, + # {"role": "user", "content": f"{msg}" + msg_content + ctx + "."} + {"role": "user", "content": msg + "."} + ] + messages.append(new_message) + if (ln==0): + collection.update( + ids=[f"id{id}" for id in range(collection.count())], + metadatas=[{"used": False} for i in range(collection.count())], + ) + reply = "Kako Vam još mogu pomoći?" + ctx_flag = True + ns = cs = "s0" + elif query_results["documents"][0][0]=="###": + ctx_flag = False + else: + if (query_results["distances"][0][0] > 0.6): + ctx_flag = True + print("Malo je nejasno šta je problem..") + collection.update( + ids=[f"id{id}" for id in range(collection.count())], + metadatas=[{"used": False} for i in range(collection.count())], + ) + reply = "Kako Vam još mogu pomoći?" + ns = cs = "s0" + else: + ctx_flag = False + reply=query_results["documents"][0][0] + id = query_results["ids"][0] + meta = query_results["metadatas"][0] + # ovo treba usloviti potrebnom input var ako treba + if (meta[0]["state"] not in ['None','s99']): meta[0]["used"] = True + collection.update( ids=id, metadatas=meta) + ns = query_results["metadatas"][0][0]["next"] + if show: print(cs, "->", ns) + if not(show): + print(f"Assistant({cs}): ") + else: + print(f"Assistant({cs}): ", query_results["documents"][0][0]) ; print(messages) + completion = oc.chat.completions.create( + model = model_id, + messages=messages, + temperature=0.6, #0.9 + max_tokens=2048, + top_p=0.8, #0.2, 0.92 + frequency_penalty=0.0, #0.05 + presence_penalty=0.0, # 1.11 + stop=None, +# do_sampe=True, +# stream=True + ) + new_message = {"role": "assistant", "content": ""} + new=completion.choices[0].message.content + if new==previous: + new_message["content"] = reply + collection.update( + ids=[f"id{id}" for id in range(collection.count())], + metadatas=[{"used": False} for i in range(collection.count())], + ) + previous = reply = "Kako Vam još mogu pomoći?" + printf (reply, end="", flush=True) + ns = cs = "s0" + messages=[] + else: + new_message["content"] += completion.choices[0].message.content + previous = new + print(new, end="", flush=True) + messages.append(new_message) + #messages=[] + if (ns!='None'): + if (ns != cs): cs=ns ; context = [] ; ctx = "" ; ctx_flag = True + if cs=='None': cs='s0' ; ctx_flag = False + +print("Kraj.") + diff --git a/bot/uchat.py b/bot/uchat.py new file mode 100644 index 0000000000000000000000000000000000000000..a7918833d3e110167c04357b618e566c8ada8a08 --- /dev/null +++ b/bot/uchat.py @@ -0,0 +1,162 @@ +import chromadb +from chromadb.utils import embedding_functions +from .models import Param +import os +import torch +from openai import OpenAI +from langchain_community.document_loaders import PyPDFLoader +from langchain.text_splitter import RecursiveCharacterTextSplitter +from itertools import islice, zip_longest +import re + +# model_id = "mistralai/Mistral-7B-Instruct-v0.2" +model_id = "Yugo60-GPT-GGUF.Q4_K_M.gguf" + +#outputs = model.generate(**inputs, max_new_tokens=20) +#print(tokenizer.decode(outputs[0], skip_special_tokens=True)) + +if not torch.backends.mps.is_available(): + if not torch.backends.mps.is_built(): + print("MPS not available because the current PyTorch install was not " + "built with MPS enabled.") + else: + print("MPS not available because the current MacOS version is not 12.3+ " + "and/or you do not have an MPS-enabled device on this machine.") +else: + torch.set_default_device("mps") + +model = "" +CHROMA_DATA_PATH = "/Users/zoranpopovic/uchat/chroma_data/" +EMBED_MODEL = "all-MiniLM-L6-v2" +# NousResearch/Hermes-2-Pro-Mistral-7B +# distilbert-base-multilingual-case +# paraphrase-multilingual-MiniLM-L12-v2d +COLLECTION_NAME = "chroma_data" +PDF_PATH = "./PDF/uputstvo_uz_eon_smart_box-1.pdf" +PDF_PATH2 = "./PDF/uputstvo_uz_eon_smart_aplikaciju-1.pdf" +CHUNK_SIZE = 800 +CHUNK_OVERLAP = 50 +max_results = 3 +min_len = 40 +min_distance = 0.35 +max_distance = 0.6 +temperature = 0.55 +max_tokens=3072 +top_p=0.8 +frequency_penalty=0.0 +presence_penalty=0.15 +DEBUG = True +system_sr = "Zoveš se U-Chat AI asistent i pomažeš korisniku usluga kompanije United Group. Korisnik postavlja pitanje ili problem, upareno sa dodatnima saznanjima. Na osnovu toga napiši korisniku kratak i ljubazan odgovor koji kompletira njegov zahtev ili mu daje odgovor na pitanje. " +# " Ako ne znaš odgovor, reci da ne znaš, ne izmišljaj ga." +system_sr += "Usluge kompanije United Group uključuju i kablovsku mrežu za digitalnu televiziju, pristup internetu, uređaj EON SMART BOX za TV sadržaj, kao i fiksnu telefoniju." +system = {'srpski': system_sr, 'hrvatski': "", 'slovenački': "", 'makedonski': ""} +ctxpre = "" +msg_content = {'srpski': "- Dodatna saznanja su: ", 'hrvatski': "", 'slovenački': "", 'makedonski': ""} +max_conv = 3 +try: + edit_all = Param.objects.all() + for edit in edit_all: + system[edit.jezik] = edit.system + ctxpre = edit.ctxpre + msg_content[edit.jezik] = edit.msg_content + min_len = edit.min_len + CHUNK_SIZE = edit.CHUNK_SIZE + CHUNK_OVERLAP = edit.CHUNK_OVERLAP + max_results = edit.max_results + EMBED_MODEL = edit.EMBED_MODEL + model_id = edit.model_id + min_distance = edit.min_distance + max_distance = edit.max_distance + max_conv = edit.max_conv + temperature = edit.temperature + top_p = edit.top_p + max_tokens = edit.max_tokens + presence_penalty = edit.presence_penalty + frequency_penalty = edit.frequency_penalty + DEBUG = edit.DEBUG +except: + pass + +def load_and_split_document(pdf_path): + loader = PyPDFLoader(pdf_path) + print('Loaded: ' + pdf_path) + return loader.load_and_split() + +def split_text_into_chunks(pages, chunk_size, chunk_overlap): + n = -1 + for page in range(len(pages)): pages[page].page_content = re.sub(r'\s+'," ", pages[page].page_content.replace(". .","").replace(r'\n','.')).replace('..','') + for p in range(len(pages)): + if len(pages[p].page_content)=0: + pages[n]=pages[p]; n += 1 + if n>0: pages = pages[:n-1] + text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap) + return text_splitter.split_documents(pages) + +def batched(iterable, n): + it = iter(iterable) + while True: + batch = list(islice(it, n)) + if not batch: + return + yield batch + +#client = chromadb.PersistentClient(path=CHROMA_DATA_PATH) +#client.allow_reset = True +#client.delete_collection(COLLECTION_NAME) +oc = OpenAI(base_url="http://localhost:4891/v1", api_key="not-needed") + +chroma_client = chromadb.PersistentClient(CHROMA_DATA_PATH) + +embedding_func = embedding_functions.SentenceTransformerEmbeddingFunction( + model_name=EMBED_MODEL + ) + +collection = chroma_client.get_or_create_collection( + name="chroma_data", + embedding_function=embedding_func, + metadata={"hnsw:space": "cosine"}, + ) + +last = collection.count() + +def update_collection(docs, last, jezik): + state = -2 + used =[] + for g in docs[0::2]: + state += 2 + documents=docs[state+1][0] + bot.uchat.collection.add( + documents=documents, + ids=[f"id{last+i}" for i in range(len(documents))], + metadatas=[{"state": g, "next": g, "used": False, "source": 'None', "page": -1, "lang": jezik } for i in range(len(documents)) ] + ) + last += len(documents) + if (len(docs[state+1])>1): + for n in docs[state+1][1:]: + bot.uchat.collection.add( + documents=n[1:], + ids=[f"id{last+i-1}" for i in range(1,len(n))], + metadatas=[{"state": g, "next": n[0], "used": False, "source": 'None', "page": -1, "lang": jezik } for i in range(1,len(n)) ] + ) + for i in range(1,len(n)): used += [0] + last += len(n)-1 + return last + +#docus = load_and_split_document(PDF_PATH) + load_and_split_document(PDF_PATH2) + +def load_docs(path, jezik): + docus = load_and_split_document(path) + pages = split_text_into_chunks(docus, CHUNK_SIZE, CHUNK_OVERLAP) + document_indices = list(range(bot.uchat.last, bot.uchat.last+len(pages))) + for batch in batched(document_indices, 66): + bot.uchat.collection.add( + ids=[f"id{last+batch[i]}" for i in range(len(batch))], + documents=[pages[i].page_content for i in batch], + metadatas=[dict(dict(dict(dict(pages[i].metadata, used=False), next='None'), state='None'), lang=jezik) for i in batch], + ) + last += len(batch) + return last + diff --git a/bot/urls.py b/bot/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..6521456bc1e3ba734a1fe5c9c5ca82290974a50c --- /dev/null +++ b/bot/urls.py @@ -0,0 +1,31 @@ +from django.urls import path +from . import views +#from . import tests + +urlpatterns = [ + path('', views.index, name='index'), + path('bot/', views.editor, name='bot'), +] + +urlpatterns += [ + path('reset/', views.reset, name='reset'), +] + +urlpatterns += [ + path('languages/', views.BotView.as_view(), name='languages'), + path('language/', views.BotViewDetail.as_view(), name='bot-detail'), + path('bot//', views.editor_id, name='editor_id'), + path('params/', views.params, name='params'), + path('params/0', views.params_refresh, name='params-refresh'), + path('importpdf', views.importPdf, name='importpdf'), +# path('bot/create', views.editor_create, name='editor_create'), +# path('bot/delete', views.editor_delete, name='editor_delete'), +] + +#urlpatterns += [ +# path('tests/', views.LanguageViewTest.as_view(), name='tests'), +#] + +#urlpatterns += [ +# path('tests/', views.UserViewTest.as_view(), name='tests'), +#] diff --git a/bot/views.py b/bot/views.py new file mode 100644 index 0000000000000000000000000000000000000000..efb9f85693770fbaedb715c3272ac526aee254e7 --- /dev/null +++ b/bot/views.py @@ -0,0 +1,624 @@ +import bot.uchat +from django.shortcuts import render +from .models import Language, Query, ParamModelForm, Param +from bot.forms import RenewBotForm, EditorForm, EditorListForm, ParamForm, ImportForm +from django.shortcuts import get_object_or_404 +from django.http import HttpResponseRedirect +from django.urls import reverse +import datetime +from django.db import transaction +from openai import OpenAI +from django.contrib.auth.decorators import login_required, permission_required +import json + +#bot.uchat.chroma_client.allow_reset = True + +class chat(object): + ns = cs = "s0" + reply = ctx = "" + messages = context = [] + ctx_flag = True + previous = "" + oc = bot.uchat.oc + def get_reply(self,jezik,query,max_results,flag): + msg = query # + "Objasnite na " + jezik + ", " + query_results = bot.uchat.collection.query( + query_texts = [ msg ], + n_results = max_results, + where = { "$and": [ {"$and": [ { "$or": [ {"state": self.cs }, { "page": { "$nin": [ -1 ] } } ] } , { "used": False } ] } , + {"lang": jezik } ] }, + ) + if bot.uchat.DEBUG: print("Query results:\n", query_results, "jezik:", jezik) + ln = len(query_results["documents"][0]) + if ln == 0: + if bot.uchat.DEBUG: print("Odaberite drugi jezik") + bot.uchat.collection.update( + ids=[f"id{id}" for id in range(bot.uchat.collection.count())], + metadatas=[{"used": False} for i in range(bot.uchat.collection.count())], + ) + if len(self.messages)>0: self.messages = self.messages[0] + new = reply = "Kako Vam još mogu pomoći?" + self.ctx_flag = True + self.ns = self.cs = "s0" + return new + else: + context = [] + i_state = l_state = -1 + for n in range(ln): + if query_results["distances"][0][n] < (0.05+(bot.uchat.max_distance+bot.uchat.min_distance)/2): + context += [ query_results["documents"][0][n] ] + if i_state<0: + l_state += 1 + if query_results["metadatas"][0][n]['state'] != 'None': + i_state = n + else: + if (query_results["metadatas"][0][n]['state'] != 'None') and (i_state<0): + i_state = n + if l_state<0: + l_state = i_state = 0 + ctx = query_results["documents"][0][0] + if self.cs != 'None': + for n in range(1,len(context)): ctx += ", " + context[n] + else: + ctx = context[l_state] + for n in range(len(context)): + if l_state != n: + ctx += ", " + context[n] + ctx += "." + match jezik: + case 'hrvatski': + o_jezik = 'hrvatskom' + case 'slovenački': + o_jezik = 'slovenačkom' + case 'srpski': + o_jezik = 'srpskom' + case 'makedonski': + o_jezik = 'makedonskom' + if query_results["documents"][0][i_state]=="###": + self.ctx_flag = False + new = reply = "Kako Vam još mogu pomoći?" + if bot.uchat.DEBUG: print("!!!###!!!") + return "Ne razumem, ili je u pitanju greška." + else: + if ((query_results["distances"][0][i_state] > bot.uchat.max_distance)) and (self.cs == 'None'): + self.ctx_flag = False + if bot.uchat.DEBUG: print("Malo je nejasno šta je problem..") + bot.uchat.collection.update( + ids=[f"id{id}" for id in range(bot.uchat.collection.count())], + metadatas=[{"used": False} for i in range(bot.uchat.collection.count())], + ) + if len(messages)>0: messsages = messages[0] + reply = "Malo je nejasno šta je problem - kako Vam još mogu pomoći?" + self.ns = self.cs = "s0" + return reply + elif (query_results["distances"][0][i_state] < bot.uchat.min_distance): + if self.cs != "None": + self.ctx_flag = False + else: + self.ctx_flag = True + new = reply=query_results["documents"][0][i_state] + else: + self.ctx_flag = True + # reply=query_results["documents"][0][i_state] + if (len(msg) < bot.uchat.min_len/4) or flag: self.ctx_flag = False + id = query_results["ids"][0] + meta = query_results["metadatas"][0] + # ovo treba usloviti potrebnom input var ako treba + if (meta[i_state]["state"] not in ['','s99']): meta[0]["used"] = True + bot.uchat.collection.update( ids=id, metadatas=meta) + self.ns = query_results["metadatas"][0][i_state]["next"] + if self.messages==[]: + self.messages = [ {"role": "system", "content": bot.uchat.system[jezik]} ] + new_message = {"role": "user", "content": f"{msg} " + bot.uchat.msg_content[jezik] + " " + ctx + ". "} + else: + if self.ctx_flag: + new_message = {"role": "user", "content": f"{msg}. " + bot.uchat.msg_content[jezik] + " " + ctx + ". "} + else: + new_message = {"role": "user", "content": f"{msg}."} + self.messages.append(new_message) + print("messages=", self.messages) + if query_results["distances"][0][i_state] > bot.uchat.min_distance: + completion = bot.uchat.oc.chat.completions.create( + model = bot.uchat.model_id, + messages=self.messages, + temperature=bot.uchat.temperature, + max_tokens=bot.uchat.max_tokens, + top_p=bot.uchat.top_p, + frequency_penalty=bot.uchat.frequency_penalty, + presence_penalty=bot.uchat.presence_penalty, + stop=["###","<|","|im_end|","|im_start|"], + # do_sample=True, + ) + if bot.uchat.DEBUG: print('msg=' + new_message['content'] + "\nMessages:\n", self.messages, flush=True) + new_message = {"role": "assistant", "content": ""} + new=completion.choices[0].message.content + if new==self.previous: + if bot.uchat.DEBUG: print("Same!!!") + bot.uchat.collection.update( + ids=[f"id{id}" for id in range(bot.uchat.collection.count())], + metadatas=[{"used": False} for i in range(bot.uchat.collection.count())], + ) + new_message["content"] = new = self.previous = reply = "Kako Vam još mogu pomoći?" + self.ns = self.cs = "s0" + self.messages = self.messages[0] + else: + new_message["content"] += completion.choices[0].message.content + self.previous = new_message["content"] + if bot.uchat.DEBUG: print(new, end="", flush=True) + else: + new_message = {"role": "assistant", "content": ""} + new_message["content"] = reply + new = reply + self.messages.append(new_message) + # Prevođenje na druge jezike: + #match o_jezik: + # case 'srpskom': + # pass + # case _ : + # new_message = {"role": "user", "content": f"Napiši to na {o_jezik} jeziku."} + # self.messages.append(new_message) + # completion = bot.uchat.oc.chat.completions.create( + # model = bot.uchat.model_id, + # messages=self.messages, + # temperature=bot.uchat.temperature, + # max_tokens=bot.uchat.max_tokens, + # top_p=bot.uchat.top_p, + # frequency_penalty=bot.uchat.frequency_penalty, + # presence_penalty=bot.uchat.presence_penalty, + # stop=None, + # # do_sample=True, + # ) + # new=completion.choices[0].message.content + # new_message = {"role": "user", "content": new} + # self.messages.append(new_message) + if (self.ns!='None'): + if (self.ns != self.cs): self.cs=self.ns + if self.cs=='None': self.cs='s0' ; self.ctx_flag = False + return new + +def selected(jez,str): + if jez==str: + return 'selected' + else: + return ' ' + +def index(request): + #num_books = Book.objects.all().count() + # Number of visits to this view, as counted in the session variable. + chat_inst = chat() + request.session.set_expiry(300) + jezik = request.session.get('jezik', 'srpski') + num_visits = request.session.get('num_visits', 1) + if num_visits == 0: + if bot.uchat.DEBUG: print("Debug: ") + request.session['num_visits'] = num_visits+1 + reply = request.session.get("replies", "Zdravo, kako Vam mogu pomoći?") + if request.method == 'POST': + # Create a form instance and populate it with data from the request (binding): + form = RenewBotForm(request.POST) + if form.is_valid(): + request.session['query'] = query = form.cleaned_data['query'] + jezik = form.cleaned_data['jezik'] + request.session['jezik'] = jezik + nr = bot.uchat.max_results if num_visits < bot.uchat.max_results else 1+(num_visits % 2) + #iif len(chat_inst.messages)>0: + # request.session['messages'] = chat_inst.messages if num_visits % 2 == 1 else chat_inst.messages[0:0] + chat_inst.messages = request.session.get('messages',[]) + chat_inst.cs = request.session.get('cs','s0') + chat_inst.ns = request.session.get('ns','s0') + if bot.uchat.max_conv < len(chat_inst.messages): + new_reply = chat_inst.get_reply(jezik, query, nr, True) + else: + new_reply = chat_inst.get_reply(jezik, query, nr, False) + request.session['messages'] = chat_inst.messages + request.session['ns'] = chat_inst.ns + request.session['cs'] = chat_inst.cs + request.session['replies'] = reply + "\nKorisnik: " + query + "\n\nOdgovor: " + new_reply + "\n" +# q = QueryForm(request.POST) + return HttpResponseRedirect(reverse("index")) + else: + if bot.uchat.DEBUG: print("Invalid form!", form.errors) + else: + form = RenewBotForm(initial={'query': 'Neki upit:'}) + query = request.session.get('query','...') + jezik = request.session.get('jezik','srpski') + #if len(chat_inst.messages)>0: + # request.session['messages'] = chat_inat.messages + #else: + # request.session['messages'] = [] + return render( + request, + 'index.html', + context={ + 'num_visits': num_visits, + 'reply': reply, + 'selected_hr': selected(jezik,'hrvatski'), + 'selected_sl': selected(jezik,'slovenački'), + 'selected_sr': selected(jezik,'srpski'), + 'selected_mk': selected(jezik,'makedonski'), + } + ) + +def reset(request): + chat().messages = request.session.get('messages',[]) + chat().cs = "s0" + chat().ns = "s0" + chat().oc.close() + bot.uchat.oc = oc = OpenAI(base_url="http://localhost:4891/v1", api_key="not-needed") + ids = bot.uchat.collection.get()['ids'] + for id in ids: bot.uchat.collection.update(ids=[id], metadatas=[{'used': False}]) + jezik = request.session.get('jezik','srpski') + request.session.flush() + request.session['num_visits'] = 0 + return render( + request, + 'index.html', + context = {'num_visits': 0, + 'reply': 'Kako Vam mogu još pomoći?', + 'selected_hr': selected(jezik,'hrvatski'), + 'selected_sl': selected(jezik,'slovenački'), + 'selected_sr': selected(jezik,'srpski'), + 'selected_mk': selected(jezik,'makedonski'), + } + ) + +def editor(request): + #pagesize = 10 + if request.method == "POST": + form = EditorListForm(request.POST) + form.is_valid() + try: + request.session['id'] = f_id = form.cleaned_data['f_id'] + except: + request.session['id'] = f_id = "" + try: + request.session['state'] = f_state = form.cleaned_data['f_state'] + except: + request.session['state'] = f_state = "" + try: + request.session['next'] = f_next = form.cleaned_data['f_next'] + except: + request.session['next'] = f_next = "" + try: + request.session['page'] = f_page = form.cleaned_data['f_page'] + except: + request.session['page'] = f_page = "" + try: + request.session['jezik'] = f_jezik = form.cleaned_data['f_jezik'] + except: + request.session['jezik'] = f_jezik = "" + try: + request.session['docu'] = f_docu = form.cleaned_data['f_docu'] + except: + request.session['docu'] = f_docu = "" + return HttpResponseRedirect(reverse('bot')) + else: + f_jezik = jezik = request.session.get('jezik','') + f_state = request.session.get('state','') + f_next = request.session.get('next','') + f_page = request.session.get('page','') + f_docu = request.session.get('docu','') + f_id = request.session.get('id','') + meta = {} + if f_state != "": + meta = {"state": f_state} + if f_next != "": + if meta == {}: + meta = {"next": f_next} + else: + meta = { "$and": [ meta, {"next": f_next} ] } + if f_page !="": + if meta == {}: + meta = {"page": f_page} + else: + meta = { "$and": [ meta , {"page": f_page} ] } + if f_jezik != "": + if meta == {}: + meta = {"lang": f_jezik} + else: + meta = { "$and": [ meta, {"lang": f_jezik} ] } + if f_id == "": + if f_docu =="": + ids = bot.uchat.collection.get(where=meta)['ids'] + documents = bot.uchat.collection.get(where=meta)['documents'] + states = bot.uchat.collection.get(where=meta)['metadatas'] + else: + ids = bot.uchat.collection.get(where=meta, where_document={"$contains": f_docu })['ids'] + documents = bot.uchat.collection.get(where=meta, where_document={"$contains": f_docu })['documents'] + states = bot.uchat.collection.get(where=meta, where_document={"$contains": f_docu })['metadatas'] + else: + if f_docu == "": + ids = bot.uchat.collection.get(ids=[f'id{f_id}'], where=meta)['ids'] + documents = bot.uchat.collection.get(ids=[f'id{f_id}'], where=meta)['documents'] + states = bot.uchat.collection.get(ids=[f'id{f_id}'], where=meta)['metadatas'] + else: + ids = bot.uchat.collection.get(ids=[f'id{f_id}'], where=meta, where_document={"$contains": f_docu })['ids'] + documents = bot.uchat.collection.get(ids=[f'id{f_id}'], where=meta, where_document={"$contains": f_docu })['documents'] + states = bot.uchat.collection.get(ids=[f'id{f_id}'], where=meta, where_document={"$contains": f_docu })['metadatas'] + cnt = 0 + nr = len(documents) + id_docs = [] + for doc in documents: + try: + lang = states[cnt]['lang'] + except: + lang = "srpski" + id_docs += [ [ids[cnt], states[cnt]['state'], states[cnt]['next'], states[cnt]['page'], lang, doc] ] + cnt += 1 + id_docs.sort(key=lambda k: eval(k[0][2:])) + return render( + request, + 'index_editor.html', + context = {'last': bot.uchat.last, 'nr': nr, + 'id_docs': id_docs, + 'documents': documents, + 'id': "", + 'selected_hr': selected(jezik,'hrvatski'), + 'selected_sl': selected(jezik,'slovenački'), + 'selected_sr': selected(jezik,'srpski'), + 'selected_mk': selected(jezik,'makedonski'), + 'f_id': f_id, + 'f_state': f_state, + 'f_next': f_next, + 'f_page': f_page, + 'f_docu': f_docu, + 'f_jezik': f_jezik, + } + ) + +def get_id(coll): + for i in range(coll.count()): + id = coll.get(ids=f'id{i}')['ids'] + if id==[]: + return i + return coll.count() + +def editor_id(request, pk, pk2): + last = bot.uchat.last + state = next = uris = "" + used = False + page = -1 + if request.method == "POST": + form = EditorForm(request.POST) + if form.is_valid(): + id = form.cleaned_data['id'][2:] + state = form.cleaned_data['state'] + next = form.cleaned_data['next'] + used = json.loads(form.cleaned_data['used'].lower()) + page = form.cleaned_data['page'] + docu = form.cleaned_data['docu'] + source = form.cleaned_data['source'] + jezik = form.cleaned_data['jezik'] + #request.session['jezik'] = jezik + meta = {'state': state, 'next': next, 'used': used, 'page': page, 'source': source, 'lang': jezik} + try: + if pk2==0: + bot.uchat.collection.update( + ids = f'id{pk}', + metadatas = meta, + documents = docu + ) + return HttpResponseRedirect(reverse('bot')+f'{pk}/0') + elif pk2==1: + if bot.uchat.last>1: + new = get_id(bot.uchat.collection) + bot.uchat.collection.add( + ids = f'id{new}', + metadatas = meta, + documents = docu + ) + bot.uchat.last += 1 + return HttpResponseRedirect(reverse('bot')+f'{new}/0') + elif pk2==2: + bot.uchat.collection.delete(ids = f'id{pk}') + bot.uchat.last -= 1 + return HttpResponseRedirect(reverse('bot')) + except: + if bot.uchat.DEBUG: print("Errors:", form.errors) + return HttpResponseRedirect(reverse('bot')) + else: + if bot.uchat.DEBUG: print("Invalid form!", form.errors) + return HttpResponseRedirect(reverse('bot')+f'{pk}/0') + else: + if last>0: + doc = bot.uchat.collection.get(ids=[f'id{pk}']) + state = doc['metadatas'][0]['state'] + next = doc['metadatas'][0]['next'] + used = doc['metadatas'][0]['used'] + page = doc['metadatas'][0]['page'] + docu = doc['documents'][0] + source = doc['metadatas'][0]['source'] + try: + jezik = doc['metadatas'][0]['lang'] + except: + jezik = request.session.get('jezik','srpski') + return render( + request, + 'index_editor.html', + context = {'last': bot.uchat.last, 'nr': "", + 'state': state, + 'next': next, + 'used': used, + 'page': page, + 'docu': docu, + 'source': source, + 'id': pk, + 'selected_hr': selected(jezik,'hrvatski'), + 'selected_sl': selected(jezik,'slovenački'), + 'selected_sr': selected(jezik,'srpski'), + 'selected_mk': selected(jezik,'makedonski'), + } + ) + +def params_refresh(request): + if request.method == "POST": + form = ParamForm(request.POST) + form.is_valid() + request.session["jezik"] = form.cleaned_data['jezik'] + return HttpResponseRedirect(reverse('params')) + else: + return HttpResponseRedirect(reverse('params')) + +def params(request): + if request.method == "POST": + form = ParamForm(request.POST) + jezici = [] + edit_all = Param.objects.all() + for edit in edit_all: jezici += [edit.jezik] + mform = ParamModelForm(request.POST) + try: + form.is_valid() + request.session["jezik"] = form.cleaned_data['jezik'] + jezik = request.session["jezik"] + bot.uchat.ctxpre = form.cleaned_data['ctxpre'] + except: + bot.uchat.ctxpre = "" + try: + bot.uchat.msg_content[jezik] = form.cleaned_data['msg_content'] + except: + bot.uchat.msg_content[jezik] = "" + try: + bot.uchat.system[jezik] = form.cleaned_data['system'] + bot.uchat.min_len = form.cleaned_data['min_len'] + bot.uchat.CHUNK_SIZE = form.cleaned_data['CHUNK_SIZE'] + bot.uchat.CHUNK_OVERLAP = form.cleaned_data['CHUNK_OVERLAP'] + bot.uchat.max_results = form.cleaned_data['max_results'] + bot.uchat.EMBED_MODEL = form.cleaned_data['EMBED_MODEL'] + bot.uchat.model_id = form.cleaned_data['model_id'] + bot.uchat.max_conv = form.cleaned_data['max_conv'] + bot.uchat.min_distance = form.cleaned_data['min_distance'] + bot.uchat.max_distance = form.cleaned_data['max_distance'] + bot.uchat.temperature = form.cleaned_data['temperature'] + bot.uchat.max_tokens = form.cleaned_data['max_tokens'] + bot.uchat.top_p = form.cleaned_data['top_p'] + bot.uchat.frequency_penalty = form.cleaned_data['frequency_penalty'] + bot.uchat.presence_penalty = form.cleaned_data['presence_penalty'] + bot.uchat.DEBUG = json.loads(form.cleaned_data['DEBUG'].lower()) + except: + if bot.uchat.DEBUG: print("Errors:", form.errors) + if jezik in jezici: + for edit in edit_all: + if edit.jezik == jezik: + edit.system = bot.uchat.system[jezik] + edit.min_len = bot.uchat.min_len + edit.CHUNK_SIZE = bot.uchat.CHUNK_SIZE + edit.CHUNK_OVERLAP = bot.uchat.CHUNK_OVERLAP + edit.max_results = bot.uchat.max_results + edit.EMBED_MODEL = bot.uchat.EMBED_MODEL + edit.model_id = bot.uchat.model_id + edit.max_conv = bot.uchat.max_conv + edit.min_distance = bot.uchat.min_distance + edit.max_distance = bot.uchat.max_distance + edit.temperature = bot.uchat.temperature + edit.max_tokens = bot.uchat.max_tokens + edit.top_p = bot.uchat.top_p + edit.frequency_penalty = bot.uchat.frequency_penalty + edit.presence_penalty = bot.uchat.presence_penalty + edit.DEBUG = bot.uchat.DEBUG + edit.jezik = jezik + edit.msg_content = bot.uchat.msg_content[jezik] + edit.ctxpre = bot.uchat.ctxpre + edit.save() + else: + mform.save() + return HttpResponseRedirect(reverse('params')) + else: + jezik = request.session.get('jezik','srpski') + if jezik == '': jezik='srpski' + edit_all = Param.objects.all() + for edit in edit_all: + if edit.jezik == jezik: + bot.uchat.system[jezik] = edit.system + bot.uchat.ctxpre = edit.ctxpre + bot.uchat.msg_content[jezik] = edit.msg_content + bot.uchat.min_len = edit.min_len + bot.uchat.CHUNK_SIZE = edit.CHUNK_SIZE + bot.uchat.CHUNK_OVERLAP = edit.CHUNK_OVERLAP + bot.uchat.max_results = edit.max_results + bot.uchat.EMBED_MODEL = edit.EMBED_MODEL + bot.uchat.model_id = edit.model_id + bot.uchat.min_distance = edit.min_distance + bot.uchat.max_distance = edit.max_distance + bot.uchat.max_conv = edit.max_conv + bot.uchat.temperature = edit.temperature + bot.uchat.top_p = edit.top_p + bot.uchat.max_tokens = edit.max_tokens + bot.uchat.presence_penalty = edit.presence_penalty + bot.uchat.frequency_penalty = edit.frequency_penalty + bot.uchat.DEBUG = edit.DEBUG + return render( + request, + 'index_params.html', + context = {'system': bot.uchat.system[jezik], + 'ctrpre': bot.uchat.ctxpre, + 'msg_content': bot.uchat.msg_content[jezik], + 'min_len': bot.uchat.min_len, + 'CHUNK_SIZE': bot.uchat.CHUNK_SIZE, + 'CHUNK_OVERLAP': bot.uchat.CHUNK_OVERLAP, + 'max_results': bot.uchat.max_results, + 'EMBED_MODEL': bot.uchat.EMBED_MODEL, # "all-MiniLM-L6-v2", + 'model_id': bot.uchat.model_id, # model_id = "Yugo60-GPT-GGUF.Q4_K_M.gguf" + 'max_conv': bot.uchat.max_conv, + 'min_distance': bot.uchat.min_distance, + 'max_distance': bot.uchat.max_distance, + 'temperature': bot.uchat.temperature, + 'max_tokens': bot.uchat.max_tokens, + 'top_p': bot.uchat.top_p, + 'frequency_penalty': bot.uchat.frequency_penalty, + 'presence_penalty': bot.uchat.presence_penalty, + 'DEBUG': bot.uchat.DEBUG, + 'selected_hr': selected(jezik,'hrvatski'), + 'selected_sl': selected(jezik,'slovenački'), + 'selected_sr': selected(jezik,'srpski'), + 'selected_mk': selected(jezik,'makedonski'), + } + ) + +def importPdf(request): + if request.method == "POST": + form = ImportForm(request.POST) + if form.is_valid(): + path = form.cleaned_data['path'] + jezik = form.cleaned_data['jezik'] + request.session['jezik'] = jezik + request.session['path'] = path + l_last = bot.uchat.last + try: + bot.uchat.load_docs(path, jezik) + l_last = bot.uchat.last - l_last + request.session['answer'] = f"Importovano {l_last} delova PDF dokumenta." + except: + if bot.uchat.DEBUG: print("Došlo je do problema sa importom PDF fajla.") + request.session['answer'] = "Došlo je do problema sa importom PDF fajla." + return HttpResponseRedirect(reverse('importpdf')) + else: + jezik = request.session.get('jezik','srpski') + path = request.session.get('path','/Users/profile/...') + answer = request.session.get('answer','') + return render( + request, + 'index_import.html', + context = {'path': path, + 'answer': answer, + 'selected_hr': selected(jezik,'hrvatski'), + 'selected_sl': selected(jezik,'slovenački'), + 'selected_sr': selected(jezik,'srpski'), + 'selected_mk': selected(jezik,'makedonski'), + } + ) + +from django.views import generic + +class BotView(generic.ListView): + """View for a bot chat.""" + if bot.uchat.DEBUG: print ("Test!") + model = Language + paginate_by = 5 + last = bot.uchat.last + +class BotViewDetail(generic.DetailView): + model = Language + +##@login_required +##@permission_required('catalog.can_mark_returned', raise_exception=True) + diff --git a/templates/.DS_Store b/templates/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2aa4f94f1f0a603bd9c40ea1573f2ad981a94c2a Binary files /dev/null and b/templates/.DS_Store differ diff --git a/templates/base_generic.html b/templates/base_generic.html new file mode 100644 index 0000000000000000000000000000000000000000..caffaefb46b0b0a7abd64a15440090d0d2f5a09f --- /dev/null +++ b/templates/base_generic.html @@ -0,0 +1,74 @@ + + + + {% block title %}UChat{% endblock %} + + + + + + {% load static %} + + + + +
+ +
+
+ {% block sidebar %} + + + + + {% if user.is_staff %} +
+ + {% endif %} + +{% endblock %} +
+
+ {% block content %}{% endblock %} + + {% block pagination %} + {% if is_paginated %} + + {% endif %} + {% endblock %} +
+
+ +
+ + diff --git a/templates/bot/language_detail.html b/templates/bot/language_detail.html new file mode 100644 index 0000000000000000000000000000000000000000..d36bcdfb7e93649981e18c08a7ccd7eb5bce521a --- /dev/null +++ b/templates/bot/language_detail.html @@ -0,0 +1,16 @@ +{% extends "base_generic.html" %} + +{% block content %} + +

Jezik: {{ language.name }}

+ +
    +
  • +

    ID: {{ language.id}}

    +
  • +
  • +

    Skraćeno: {{ language.lid }}

    +
  • +
+ +{% endblock %} diff --git a/templates/bot/language_list.html b/templates/bot/language_list.html new file mode 100644 index 0000000000000000000000000000000000000000..b6ca3682ce44607634904daf16786c050cc9ccca --- /dev/null +++ b/templates/bot/language_list.html @@ -0,0 +1,16 @@ +{% extends "base_generic.html" %} + +{% block content %} + +

Language List

+ +
    + {% for language in language_list %} +
  • + {{ language.name }} +
  • + {% empty %} +
  • There are no languages available.
  • + {% endfor %} +
+{% endblock %} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000000000000000000000000000000000000..630dec3598112bd470440be13d19ac8bc40fe6b2 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,41 @@ + +{% extends "base_generic.html" %} + +{% block content %} + + +

UChat prototip

+ +

+

+
+{{ reply }}
+
+

+
+

+

+{% csrf_token %} + +
+ +
+ +

      +       + +
+

+ +{% endblock %} + diff --git a/templates/index_editor.html b/templates/index_editor.html new file mode 100644 index 0000000000000000000000000000000000000000..3ea9a945a31eb36d1527323d133c04e2abe987b5 --- /dev/null +++ b/templates/index_editor.html @@ -0,0 +1,76 @@ +{% extends "base_generic.html" %} + +{% block content %} + +

Editor

+
+ + + + + +{% if id == "" %} + + + + + + + +{% csrf_token %} + + + + + + + + +{% endif %} + + + +{% if id == "" %} +{% for row in id_docs %} + +{% for col in row %} +{% if col|slice:":2" == "id" %} + +{% else %} + +{% endif %} +{% endfor %} + +{% endfor %} +{% else %} + +{% endif %} + +
Ukupno: {{ nr }} od {{ last }}
idstatenextpagejezikdocument
{{ col }}{{ col|truncatewords:16 }}
{{ id }}
+
+{% if id != "" %} +
+{% csrf_token %} + + + + + + + + + +
+
+
+
+
+
+
+{% endif %} +{% endblock %} diff --git a/templates/index_import.html b/templates/index_import.html new file mode 100644 index 0000000000000000000000000000000000000000..6f67e2292e1207f8bca162e90088841635faaeea --- /dev/null +++ b/templates/index_import.html @@ -0,0 +1,29 @@ + +{% extends "base_generic.html" %} + +{% block content %} + +

PDF import

+

+{{ answer }} +

+

+{% csrf_token %} + +
+ +
+ +

+ +< +

+

+ +{% endblock %} + diff --git a/templates/index_params.html b/templates/index_params.html new file mode 100644 index 0000000000000000000000000000000000000000..d96a43ec097819434510768ac684360486f1501c --- /dev/null +++ b/templates/index_params.html @@ -0,0 +1,107 @@ + +{% extends "base_generic.html" %} + +{% block content %} + + +

UChat prototip

+

+

+{% csrf_token %} + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+ +    (*) +
+ +
+         + +            + +
+ +{% endblock %} + diff --git a/templates/registration/logged_out.html b/templates/registration/logged_out.html new file mode 100644 index 0000000000000000000000000000000000000000..b7b3d6ff16183fcf5fc98c7b2679892b6e2df008 --- /dev/null +++ b/templates/registration/logged_out.html @@ -0,0 +1,7 @@ +{% extends "base_generic.html" %} + +{% block content %} +

Logged out!

+ +Click here to login again. +{% endblock %} diff --git a/templates/registration/login.html b/templates/registration/login.html new file mode 100644 index 0000000000000000000000000000000000000000..ba11102a13bfd2121fb0a7e9a240ba918e4cf72e --- /dev/null +++ b/templates/registration/login.html @@ -0,0 +1,38 @@ +{% extends "base_generic.html" %} + +{% block content %} + +{% if form.errors %} +

Your username and password didn't match. Please try again.

+{% endif %} + +{% if next %} + {% if user.is_authenticated %} +

Your account doesn't have access to this page. To proceed, + please login with an account that has access.

+ {% else %} +

Please login to see this page.

+ {% endif %} +{% endif %} + +
+{% csrf_token %} + + + + + + + + + +
{{ form.username.label_tag }}{{ form.username }}
{{ form.password.label_tag }}{{ form.password }}
+ + + +
+ +{# Assumes you setup the password_reset view in your URLconf #} +

Lost password?

+ +{% endblock %} diff --git a/templates/registration/password_reset_complete.html b/templates/registration/password_reset_complete.html new file mode 100644 index 0000000000000000000000000000000000000000..fdc81fe04fed45dbb106dca5ccabc262c08e7cbf --- /dev/null +++ b/templates/registration/password_reset_complete.html @@ -0,0 +1,8 @@ +{% extends "base_generic.html" %} + +{% block content %} + +

The password has been changed!

+

log in again?

+ +{% endblock %} diff --git a/templates/registration/password_reset_confirm.html b/templates/registration/password_reset_confirm.html new file mode 100644 index 0000000000000000000000000000000000000000..34485c443fb8f0cda94d1b7f6e39620d277bb5cb --- /dev/null +++ b/templates/registration/password_reset_confirm.html @@ -0,0 +1,33 @@ +{% extends "base_generic.html" %} + +{% block content %} + + {% if validlink %} +

Please enter (and confirm) your new password.

+
+
+ +
+ + + + + + + + + + + + + +
{{ form.new_password1.errors }} + {{ form.new_password1 }}
{{ form.new_password2.errors }} + {{ form.new_password2 }}
+
+ {% else %} +

Password reset failed

+

The password reset link was invalid, possibly because it has already been used. Please request a new password reset.

+ {% endif %} + +{% endblock %} diff --git a/templates/registration/password_reset_done.html b/templates/registration/password_reset_done.html new file mode 100644 index 0000000000000000000000000000000000000000..0e06fe9e1f5dac84cd4d024fa55503221bf735e7 --- /dev/null +++ b/templates/registration/password_reset_done.html @@ -0,0 +1,7 @@ +{% extends "base_generic.html" %} + +{% block content %} + +

We've emailed you instructions for setting your password. If they haven't arrived in a few minutes, check your spam folder.

+ +{% endblock %} diff --git a/templates/registration/password_reset_email.html b/templates/registration/password_reset_email.html new file mode 100644 index 0000000000000000000000000000000000000000..37467b8627b75235afcf7d9922acc1894c27a647 --- /dev/null +++ b/templates/registration/password_reset_email.html @@ -0,0 +1,2 @@ +Someone asked for password reset for email {{ email }}. Follow the link below: +{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} diff --git a/templates/registration/password_reset_form.html b/templates/registration/password_reset_form.html new file mode 100644 index 0000000000000000000000000000000000000000..9d9dc4b8bd0fd3a193f56aee4ef5e7b137cf6398 --- /dev/null +++ b/templates/registration/password_reset_form.html @@ -0,0 +1,11 @@ +{% extends "base_generic.html" %} + +{% block content %} + +
{% csrf_token %} + {% if form.email.errors %}{{ form.email.errors }}{% endif %} +

{{ form.email }}

+ +
+ +{% endblock %} diff --git a/templates/tests.html b/templates/tests.html new file mode 100644 index 0000000000000000000000000000000000000000..eb35ce3a538b84211dd58d576f2c8e76d526a4ca --- /dev/null +++ b/templates/tests.html @@ -0,0 +1,13 @@ + +{% extends "base_generic.html" %} + +{% block content %} +

uchat prototip

+ +
+
+ +

You have visited this page {{ num_visits }} time{{ num_visits|pluralize }}.

+ +{% endblock %} + diff --git a/uchat/.DS_Store b/uchat/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d3ff007386e3343fd9eef50f59a2744173fba3af Binary files /dev/null and b/uchat/.DS_Store differ diff --git a/uchat/__init__.py b/uchat/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/uchat/__pycache__/__init__.cpython-311.pyc b/uchat/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c35fa0a2eb6ee61a13338557f43e8aaf4ae295a6 Binary files /dev/null and b/uchat/__pycache__/__init__.cpython-311.pyc differ diff --git a/uchat/__pycache__/settings.cpython-311.pyc b/uchat/__pycache__/settings.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f56e4411b9f0df744d69ca11905ed67f8c465e7a Binary files /dev/null and b/uchat/__pycache__/settings.cpython-311.pyc differ diff --git a/uchat/__pycache__/urls.cpython-311.pyc b/uchat/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43e0c4b717dc49395f0f0e7f8d390dfc92ed4525 Binary files /dev/null and b/uchat/__pycache__/urls.cpython-311.pyc differ diff --git a/uchat/__pycache__/wsgi.cpython-311.pyc b/uchat/__pycache__/wsgi.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8921343a4fef85250d2e02e4e36c2b298ae28057 Binary files /dev/null and b/uchat/__pycache__/wsgi.cpython-311.pyc differ diff --git a/uchat/apachectl b/uchat/apachectl new file mode 100644 index 0000000000000000000000000000000000000000..5d06f7e73c3614fc6f10ae57740d3897fc353e5e --- /dev/null +++ b/uchat/apachectl @@ -0,0 +1,106 @@ +#!/bin/bash + +# ['/Library/Frameworks/Python.framework/Versions/3.11/bin/mod_wsgi-express', 'setup-server', 'wsgi.py', '--port=80', '--user', 'www-data', '--group', 'www-data', '--server-root=/Users/zoranpopovic/uchat/uchat'] + +HTTPD="/usr/sbin/httpd" +HTTPD_ARGS="-f /Users/zoranpopovic/uchat/uchat/httpd.conf -DMOD_WSGI_KEEP_ALIVE -DMOD_WSGI_MPM_ENABLE_EVENT_MODULE -DMOD_WSGI_MPM_EXISTS_EVENT_MODULE -DMOD_WSGI_MPM_EXISTS_WORKER_MODULE -DMOD_WSGI_MPM_EXISTS_PREFORK_MODULE" + +HTTPD_COMMAND="$HTTPD $HTTPD_ARGS" + +MOD_WSGI_MODULES_DIRECTORY="/usr/libexec/apache2" +export MOD_WSGI_MODULES_DIRECTORY + +SHLIBPATH="" + +if [ "x$SHLIBPATH" != "x" ]; then + DYLD_LIBRARY_PATH="$SHLIBPATH:$DYLD_LIBRARY_PATH" + export DYLD_LIBRARY_PATH +fi + +MOD_WSGI_SERVER_ROOT="/Users/zoranpopovic/uchat/uchat" + +export MOD_WSGI_SERVER_ROOT + +MOD_WSGI_LISTENER_HOST="localhost" + +export MOD_WSGI_LISTENER_HOST + +MOD_WSGI_HTTP_PORT="80" +MOD_WSGI_HTTPS_PORT="None" + +export MOD_WSGI_HTTP_PORT +export MOD_WSGI_HTTPS_PORT + +WSGI_RUN_USER="${WSGI_RUN_USER:-www-data}" +WSGI_RUN_GROUP="${WSGI_RUN_GROUP:-www-data}" + +MOD_WSGI_USER="${MOD_WSGI_USER:-${WSGI_RUN_USER}}" +MOD_WSGI_GROUP="${MOD_WSGI_GROUP:-${WSGI_RUN_GROUP}}" + +export MOD_WSGI_USER +export MOD_WSGI_GROUP + +if [ `id -u` = "0" -a ${MOD_WSGI_USER} = "root" ]; then + cat << EOF + +WARNING: When running as the 'root' user, it is required that the options +'--user' and '--group' be specified to mod_wsgi-express. These should +define a non 'root' user and group under which the Apache child worker +processes and mod_wsgi daemon processes should be run. Failure to specify +these options will result in Apache and/or the mod_wsgi daemon processes +failing to start. See the mod_wsgi-express documentation for further +information on this restriction. + +EOF + +fi + +MOD_WSGI_WORKING_DIRECTORY="/Users/zoranpopovic/uchat" + +export MOD_WSGI_WORKING_DIRECTORY + +LANG='en_US.UTF-8' +LC_ALL='en_US.UTF-8' + +export LANG +export LC_ALL + +ACMD="$1" +ARGV="$@" + +if test -f /Users/zoranpopovic/uchat/uchat/envvars; then + . /Users/zoranpopovic/uchat/uchat/envvars +fi + +STATUSURL="http://localhost:80/server-status" + +if [ "x$ARGV" = "x" ]; then + ARGV="-h" +fi + +GDB="gdb" +ENABLE_GDB="False" + +PROCESS_NAME="httpd (mod_wsgi-express)" + +cd $MOD_WSGI_WORKING_DIRECTORY + +case $ACMD in +start|stop|restart|graceful|graceful-stop) + if [ "x$ENABLE_GDB" != "xTrue" ]; then + exec -a "$PROCESS_NAME" $HTTPD_COMMAND -k $ARGV + else + echo "run $HTTPD_ARGS -k $ARGV" > /Users/zoranpopovic/uchat/uchat/gdb.cmds + gdb -x /Users/zoranpopovic/uchat/uchat/gdb.cmds $HTTPD + fi + ;; +configtest) + exec $HTTPD_COMMAND -t + ;; +status) + exec /Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11 -m webbrowser -t $STATUSURL + ;; +*) + exec $HTTPD_COMMAND $ARGV +esac + diff --git a/uchat/asgi.py b/uchat/asgi.py new file mode 100644 index 0000000000000000000000000000000000000000..91db311d4afb6a3ea691fecf7c72d21570f22736 --- /dev/null +++ b/uchat/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for uchat project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'uchat.settings') + +application = get_asgi_application() diff --git a/uchat/default.wsgi b/uchat/default.wsgi new file mode 100644 index 0000000000000000000000000000000000000000..d41fa7f651e27f4b8539d2d890701bf174cb6f83 --- /dev/null +++ b/uchat/default.wsgi @@ -0,0 +1,43 @@ + +CONTENT = b''' + + +My web site runs on Malt Whiskey + + + + + + + + + +
+ + + +My web site
runs on
Malt Whiskey
+
+
+ +For further information on configuring mod_wsgi,
+see the documentation. +
+
+ + +''' + +def application(environ, start_response): + status = '200 OK' + output = CONTENT + + response_headers = [('Content-type', 'text/html'), + ('Content-Length', str(len(output)))] + start_response(status, response_headers) + + return [output] + diff --git a/uchat/envvars b/uchat/envvars new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/uchat/handler.wsgi b/uchat/handler.wsgi new file mode 100644 index 0000000000000000000000000000000000000000..fcbc26a555064c983b1011008353c570bb386a8b --- /dev/null +++ b/uchat/handler.wsgi @@ -0,0 +1,104 @@ + +import os +import sys +import atexit +import time + +import mod_wsgi.server + +working_directory = r'/Users/zoranpopovic/uchat/uchat' + +entry_point = r'/Users/zoranpopovic/uchat/uchat/wsgi.py' +application_type = 'script' +callable_object = 'application' +mount_point = '/' +with_newrelic_agent = False +newrelic_config_file = '' +newrelic_environment = '' +disable_reloading = False +reload_on_changes = False +debug_mode = False +enable_debugger = False +debugger_startup = False +enable_coverage = False +coverage_directory = '' +enable_profiler = False +profiler_directory = '' +enable_recorder = False +recorder_directory = '' +enable_gdb = False + +os.environ['MOD_WSGI_EXPRESS'] = 'true' +os.environ['MOD_WSGI_SERVER_NAME'] = 'localhost' +os.environ['MOD_WSGI_SERVER_ALIASES'] = None or '' + +if reload_on_changes: + os.environ['MOD_WSGI_RELOADER_ENABLED'] = 'true' + +if debug_mode: + os.environ['MOD_WSGI_DEBUG_MODE'] = 'true' + + # We need to fiddle sys.path as we are not using daemon mode and so + # the working directory will not be added to sys.path by virtue of + # 'home' option to WSGIDaemonProcess directive. We could use the + # WSGIPythonPath directive, but that will cause .pth files to also + # be evaluated. + + sys.path.insert(0, working_directory) + +if enable_debugger: + os.environ['MOD_WSGI_DEBUGGER_ENABLED'] = 'true' + +def output_coverage_report(): + coverage_info.stop() + coverage_info.html_report(directory=coverage_directory) + +if enable_coverage: + os.environ['MOD_WSGI_COVERAGE_ENABLED'] = 'true' + + from coverage import coverage + coverage_info = coverage() + coverage_info.start() + atexit.register(output_coverage_report) + +def output_profiler_data(): + profiler_info.disable() + output_file = '%s-%d.pstats' % (int(time.time()*1000000), os.getpid()) + output_file = os.path.join(profiler_directory, output_file) + profiler_info.dump_stats(output_file) + +if enable_profiler: + os.environ['MOD_WSGI_PROFILER_ENABLED'] = 'true' + + from cProfile import Profile + profiler_info = Profile() + profiler_info.enable() + atexit.register(output_profiler_data) + +if enable_recorder: + os.environ['MOD_WSGI_RECORDER_ENABLED'] = 'true' + +if enable_gdb: + os.environ['MOD_WSGI_GDB_ENABLED'] = 'true' + +if with_newrelic_agent: + if newrelic_config_file: + os.environ['NEW_RELIC_CONFIG_FILE'] = newrelic_config_file + if newrelic_environment: + os.environ['NEW_RELIC_ENVIRONMENT'] = newrelic_environment + +handler = mod_wsgi.server.ApplicationHandler(entry_point, + application_type=application_type, callable_object=callable_object, + mount_point=mount_point, with_newrelic_agent=with_newrelic_agent, + debug_mode=debug_mode, enable_debugger=enable_debugger, + debugger_startup=debugger_startup, enable_recorder=enable_recorder, + recorder_directory=recorder_directory) + +if not disable_reloading: + reload_required = handler.reload_required + +handle_request = handler.handle_request + +if not disable_reloading and reload_on_changes and not debug_mode: + mod_wsgi.server.start_reloader() + diff --git a/uchat/htdocs/index.html b/uchat/htdocs/index.html new file mode 100644 index 0000000000000000000000000000000000000000..4d882178082203e8ea02f56ad3ef94bc11dff51c --- /dev/null +++ b/uchat/htdocs/index.html @@ -0,0 +1,5 @@ + + +Test. + + diff --git a/uchat/httpd.conf b/uchat/httpd.conf new file mode 100644 index 0000000000000000000000000000000000000000..66fb23bf6bdde595db012eb823aee0c3f7250917 --- /dev/null +++ b/uchat/httpd.conf @@ -0,0 +1,757 @@ + + +LoadModule version_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_version.so' + + +ServerName localhost +ServerRoot '/Users/zoranpopovic/uchat/uchat' +PidFile '/Users/zoranpopovic/uchat/uchat/httpd.pid' + += 2.4> +DefaultRuntimeDir '/Users/zoranpopovic/uchat/uchat' + + +ServerTokens ProductOnly +ServerSignature Off + + +User ${MOD_WSGI_USER} +Group ${MOD_WSGI_GROUP} + + + +Listen localhost:80 + + +Listen 80 + + + +LockFile '/Users/zoranpopovic/uchat/uchat/accept.lock' + + += 2.4> + + + + + +LoadModule mpm_prefork_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mpm_prefork.so' + + + + + + + += 2.4> + + + + +LoadModule mpm_event_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mpm_event.so' + + +LoadModule mpm_worker_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mpm_worker.so' + + +LoadModule mpm_prefork_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mpm_prefork.so' + + + + + + + +LoadModule http2_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_http2.so' + + += 2.4> + +LoadModule access_compat_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_access_compat.so' + + + +LoadModule unixd_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_unixd.so' + + + +LoadModule authn_core_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_authn_core.so' + + +LoadModule authz_core_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_authz_core.so' + + + + +LoadModule authz_host_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_authz_host.so' + + +LoadModule mime_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mime.so' + + +LoadModule rewrite_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_rewrite.so' + + +LoadModule alias_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_alias.so' + + +LoadModule dir_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_dir.so' + + +LoadModule env_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_env.so' + + +LoadModule headers_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_headers.so' + + +LoadModule filter_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_filter.so' + + + + +LoadModule autoindex_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_autoindex.so' + + + += 2.2.15> + +LoadModule reqtimeout_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_reqtimeout.so' + + + + + +LoadModule deflate_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_deflate.so' + + + + + +LoadModule auth_basic_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_auth_basic.so' + + +LoadModule auth_digest_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_auth_digest.so' + + +LoadModule authz_user_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_authz_user.so' + + + + + +LoadModule proxy_module ${MOD_WSGI_MODULES_DIRECTORY}/mod_proxy.so + + +LoadModule proxy_http_module ${MOD_WSGI_MODULES_DIRECTORY}/mod_proxy_http.so + + + + + + +Loadmodule php5_module '${MOD_WSGI_MODULES_DIRECTORY}/libphp5.so' + +AddHandler application/x-httpd-php .php + + + + +LoadFile '' + + +#LoadModule wsgi_module '/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/mod_wsgi/server/mod_wsgi-py311.cpython-311-darwin.so' + + + +LoadModule status_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_status.so' + + + + + +LoadModule cgid_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_cgid.so' + + + + + +LoadModule cgi_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_cgi.so' + + + + +DefaultType text/plain + + +TypesConfig '/etc/apache2/mime.types' + +HostnameLookups Off +MaxMemFree 64 +Timeout 60 +ListenBacklog 500 + + +Protocols h2 h2c http/1.1 + + += 2.2.15> +RequestReadTimeout header=15-30,MinRate=500 body=15,MinRate=500 + + +LimitRequestBody 10485760 + + + AllowOverride None + + Order deny,allow + Deny from all + += 2.4> + Require all denied + + + +WSGIPythonHome '/Library/Frameworks/Python.framework/Versions/3.11' + +WSGIVerboseDebugging 'Off' + + + +WSGISocketPrefix None/wsgi + + +WSGISocketPrefix /Users/zoranpopovic/uchat/uchat/wsgi + +WSGISocketRotation Off + + + +MaxConnectionsPerChild 0 + + + +WSGIDestroyInterpreter Off + + +WSGIDestroyInterpreter On + + + + +WSGIRestrictEmbedded On + +WSGIDaemonProcess localhost:80 \ + display-name='(wsgi:localhost:80:501)' \ + home='/Users/zoranpopovic/uchat' \ + processes=1 \ + threads=5 \ + maximum-requests=0 \ + python-path='' \ + python-eggs='/Users/zoranpopovic/uchat/uchat/python-eggs' \ + lang='en_US.UTF-8' \ + locale='en_US.UTF-8' \ + listen-backlog=100 \ + queue-timeout=45 \ + socket-timeout=60 \ + connect-timeout=15 \ + request-timeout=60 \ + inactivity-timeout=0 \ + startup-timeout=15 \ + deadlock-timeout=60 \ + graceful-timeout=15 \ + eviction-timeout=0 \ + restart-interval=0 \ + cpu-time-limit=0 \ + shutdown-timeout=5 \ + send-buffer-size=0 \ + receive-buffer-size=0 \ + header-buffer-size=0 \ + response-buffer-size=0 \ + response-socket-timeout=0 \ + server-metrics=Off + + +WSGIDaemonProcess localhost:80 \ + display-name='(wsgi:localhost:80:501)' \ + home='/Users/zoranpopovic/uchat' \ + threads=5 \ + maximum-requests=0 \ + python-path='' \ + python-eggs='/Users/zoranpopovic/uchat/uchat/python-eggs' \ + lang='en_US.UTF-8' \ + locale='en_US.UTF-8' \ + listen-backlog=100 \ + queue-timeout=45 \ + socket-timeout=60 \ + connect-timeout=15 \ + request-timeout=60 \ + inactivity-timeout=0 \ + startup-timeout=15 \ + deadlock-timeout=60 \ + graceful-timeout=15 \ + eviction-timeout=0 \ + restart-interval=0 \ + cpu-time-limit=0 \ + shutdown-timeout=5 \ + send-buffer-size=0 \ + receive-buffer-size=0 \ + response-buffer-size=0 \ + response-socket-timeout=0 \ + server-metrics=Off + + + + +WSGICallableObject 'application' +WSGIPassAuthorization On +WSGIMapHEADToGET Auto + + +WSGIScriptReloading Off + + + + +WSGIPythonPath '' + + + + +WSGIRestrictStdin Off + +WSGIPythonPath '' + + + + +ExtendedStatus On + + +WSGIServerMetrics Off + + + + SetHandler server-status + + Order deny,allow + Deny from all + Allow from localhost + += 2.4> + Require all denied + Require host localhost + + + + + +KeepAlive On +KeepAliveTimeout 2 + + +KeepAlive Off + + + +EnableSendfile On +WSGIEnableSendfile On + + + +AddOutputFilterByType DEFLATE text/plain +AddOutputFilterByType DEFLATE text/html +AddOutputFilterByType DEFLATE text/xml +AddOutputFilterByType DEFLATE text/css +AddOutputFilterByType DEFLATE text/javascript +AddOutputFilterByType DEFLATE application/xhtml+xml +AddOutputFilterByType DEFLATE application/javascript +AddOutputFilterByType DEFLATE application/json + + + +ErrorLog "|/usr/sbin/rotatelogs \ + /Users/zoranpopovic/uchat/uchat/error_log.%Y-%m-%d-%H_%M_%S 5M" + + +ErrorLog "/Users/zoranpopovic/uchat/uchat/error_log" + +LogLevel warn + + +ErrorLogFormat "None" + + + + +LoadModule log_config_module ${MOD_WSGI_MODULES_DIRECTORY}/mod_log_config.so + +LogFormat "%h %l %u %t \"%r\" %>s %b" common +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined +LogFormat "undefined" custom + +CustomLog "|/usr/sbin/rotatelogs \ + /Users/zoranpopovic/uchat/uchat/access_log.%Y-%m-%d-%H_%M_%S 5M" common + + +CustomLog "/Users/zoranpopovic/uchat/uchat/access_log" common + + + + +WSGIChunkedRequest On + + + +WSGITrustedProxyHeaders + + +WSGITrustedProxies + + + + +LoadModule ssl_module ${MOD_WSGI_MODULES_DIRECTORY}/mod_ssl.so + + + + + +ServerLimit 20 +StartServers 1 +MaxClients 20 +MinSpareServers 1 +MaxSpareServers 2 + + +ServerLimit 1 +StartServers 1 +MaxClients 1 +MinSpareServers 1 +MaxSpareServers 1 + +MaxRequestsPerChild 0 + + + + +ServerLimit 2 +ThreadLimit 10 +StartServers 1 +MaxClients 20 +MinSpareThreads 10 +MaxSpareThreads 10 +ThreadsPerChild 10 + + +ServerLimit 1 +ThreadLimit 1 +StartServers 1 +MaxClients 1 +MinSpareThreads 1 +MaxSpareThreads 1 +ThreadsPerChild 1 + +MaxRequestsPerChild 0 +ThreadStackSize 262144 + + + + +ServerLimit 2 +ThreadLimit 10 +StartServers 1 +MaxClients 20 +MinSpareThreads 10 +MaxSpareThreads 10 +ThreadsPerChild 10 + + +ServerLimit 1 +ThreadLimit 1 +StartServers 1 +MaxClients 1 +MinSpareThreads 1 +MaxSpareThreads 1 +ThreadsPerChild 1 + +MaxRequestsPerChild 0 +ThreadStackSize 262144 + + + + +NameVirtualHost *:80 + + + + + + + + +NameVirtualHost *:80 + + + + +Order deny,allow +Deny from all + += 2.4> +Require all denied + + +Allow from localhost + + + + + +ServerName None + +ServerAlias None + + + + +ServerName unspecified +Redirect permanent / http://None:80/ + + + + + + +ServerName None + +ServerAlias None + +RewriteEngine On +RewriteCond %{HTTPS} off +RewriteRule (.*) https://None:None%{REQUEST_URI} + + + +ServerName unspecified +RewriteEngine On +RewriteCond %{HTTPS} off +RewriteRule (.*) https://None:None%{REQUEST_URI} + + + + + + + + + + +Listen localhost:None + + +Listen None + + +NameVirtualHost *:None + + + + +Order deny,allow +Deny from all + += 2.4> +Require all denied + + +Allow from localhost + + +SSLEngine On +SSLCertificateFile None +SSLCertificateKeyFile None + +SSLCACertificateFile None +SSLVerifyClient none + + +SSLCertificateChainFile None + + + +ServerName None + +ServerAlias None + +SSLEngine On +SSLCertificateFile None +SSLCertificateKeyFile None + +SSLCACertificateFile None +SSLVerifyClient none + + +SSLCertificateChainFile None + + + +Header set Strict-Transport-Security None + + + +SSLOptions +StdEnvVars + + + + +ServerName unspecified +Redirect permanent / https://None:None/ +SSLEngine On +SSLCertificateFile None +SSLCertificateKeyFile None + +SSLCACertificateFile None +SSLVerifyClient none + + +SSLCertificateChainFile None + + + + + + + +DocumentRoot '/Users/zoranpopovic/uchat/uchat/htdocs' + +AccessFileName .htaccess + + + AllowOverride None + Options FollowSymLinks Multiviews + MultiviewsMatch Any + + + Order allow,deny + Allow from all + += 2.4> + Require all granted + + + + + + AllowOverride None + + DirectoryIndex None + + + Options +Indexes + + + Options +ExecCGI + + + Options +ExecCGI + + RewriteEngine On + Include /Users/zoranpopovic/uchat/uchat/rewrite.conf + + Order allow,deny + Allow from all + += 2.4> + Require all granted + + + + + + RewriteCond %{REQUEST_FILENAME} !-f + + RewriteCond %{REQUEST_FILENAME} !-d + + + RewriteCond %{REQUEST_URI} !/server-status + + RewriteRule .* - [H=wsgi-handler] + + + + +WSGIErrorOverride On + + + + + WSGIAccessScript 'None' + + + + + + AuthType Basic + AuthName 'localhost:80' + AuthBasicProvider wsgi + WSGIAuthUserScript 'None' + + WSGIAuthGroupScript 'None' + + + Require valid-user + + Require wsgi-group 'wsgi' + + += 2.4> + + Require valid-user + + Require wsgi-group 'wsgi' + + + + + + + + +WSGIHandlerScript wsgi-handler '/Users/zoranpopovic/uchat/uchat/handler.wsgi' \ + process-group='localhost:80' application-group=%{GLOBAL} +WSGIImportScript '/Users/zoranpopovic/uchat/uchat/handler.wsgi' \ + process-group='localhost:80' application-group=%{GLOBAL} + + + + +WSGIHandlerScript wsgi-handler '/Users/zoranpopovic/uchat/uchat/handler.wsgi' \ + process-group='%{GLOBAL}' application-group=%{GLOBAL} +WSGIImportScript '/Users/zoranpopovic/uchat/uchat/handler.wsgi' \ + process-group='%{GLOBAL}' application-group=%{GLOBAL} + + + + +WSGIHandlerScript wsgi-handler '/Users/zoranpopovic/uchat/uchat/handler.wsgi' \ + process-group='%{GLOBAL}' application-group=%{GLOBAL} +WSGIImportScript '/Users/zoranpopovic/uchat/uchat/handler.wsgi' \ + process-group='%{GLOBAL}' application-group=%{GLOBAL} + + +WSGIHandlerScript wsgi-handler '/Users/zoranpopovic/uchat/uchat/handler.wsgi' \ + application-group=%{GLOBAL} +WSGIImportScript '/Users/zoranpopovic/uchat/uchat/handler.wsgi' \ + application-group=%{GLOBAL} + + + + + + +SSLVerifyClient require +SSLVerifyDepth 1 + + + diff --git a/uchat/resource.wsgi b/uchat/resource.wsgi new file mode 100644 index 0000000000000000000000000000000000000000..7256b29704f9d559a7a8445197fd87696822a35b --- /dev/null +++ b/uchat/resource.wsgi @@ -0,0 +1,10 @@ + +import mod_wsgi.server + +resources = None + +handler = mod_wsgi.server.ResourceHandler(resources) + +reload_required = handler.reload_required +handle_request = handler.handle_request + diff --git a/uchat/rewrite.conf b/uchat/rewrite.conf new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/uchat/settings.py b/uchat/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..3013e6ac7dfd1d5d4815e669e85f7503b201551f --- /dev/null +++ b/uchat/settings.py @@ -0,0 +1,124 @@ +""" +Django settings for uchat project. + +Generated by 'django-admin startproject' using Django 5.0.3. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.0/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-ud==o*12b8#ltu6@w9=o=+h4k!q$%9n4f75#(ob5-53^oq2qsp' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'bot.apps.BotConfig', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'uchat.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ '/Users/zoranpopovic/uchat/templates'], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'uchat.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.0/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.0/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/uchat/temp/base_generic.html b/uchat/temp/base_generic.html new file mode 100644 index 0000000000000000000000000000000000000000..e8ae6f81d589eaa9e7dc97e7b236311ee6686859 --- /dev/null +++ b/uchat/temp/base_generic.html @@ -0,0 +1,74 @@ + + + + + {% block title %}Local Library{% endblock %} + + + + + + {% load static %} + + + + +
+ +
+
+ {% block sidebar %} + + + + + {% if user.is_staff %} +
+ + {% endif %} + +{% endblock %} +
+
+ {% block content %}{% endblock %} + + {% block pagination %} + {% if is_paginated %} + + {% endif %} + {% endblock %} +
+
+ +
+ + diff --git a/uchat/temp/index.html b/uchat/temp/index.html new file mode 100644 index 0000000000000000000000000000000000000000..eb35ce3a538b84211dd58d576f2c8e76d526a4ca --- /dev/null +++ b/uchat/temp/index.html @@ -0,0 +1,13 @@ + +{% extends "base_generic.html" %} + +{% block content %} +

uchat prototip

+ +
+
+ +

You have visited this page {{ num_visits }} time{{ num_visits|pluralize }}.

+ +{% endblock %} + diff --git a/uchat/urls.py b/uchat/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..95b68c2751cbb86bd01ea6f1cfe5a305f2e0a050 --- /dev/null +++ b/uchat/urls.py @@ -0,0 +1,37 @@ +""" +URL configuration for uchat project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path +from django.urls import include +from django.shortcuts import get_object_or_404 +from django.views.generic.base import RedirectView +from django.conf import settings +from django.conf.urls.static import static + +urlpatterns = [ + path('admin/', admin.site.urls), +] + +urlpatterns += [ + path('bot/', include('bot.urls')), + path('', RedirectView.as_view(url='bot/')), +] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + +urlpatterns += [ + path('accounts/', include('django.contrib.auth.urls')), +] + diff --git a/uchat/wsgi.py b/uchat/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..59368c512653bed115c786878cbac6cf294a1799 --- /dev/null +++ b/uchat/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for uchat project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'uchat.settings') + +application = get_wsgi_application()