From 7e5d61663aa10e38008680c14dcfb47c00fd97dd Mon Sep 17 00:00:00 2001 From: Alivecow Date: Fri, 28 Feb 2025 21:33:09 +0100 Subject: [PATCH 01/13] feat: Add promt generation from webserver Refs: OPS-22 --- poetry.lock | 173 +++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + senju/ai_gen.py | 41 +++++++++ senju/haiku.py | 6 +- senju/main.py | 14 ++- senju/templates/prompt.html | 24 +++-- 6 files changed, 250 insertions(+), 9 deletions(-) create mode 100644 senju/ai_gen.py diff --git a/poetry.lock b/poetry.lock index 72ccf61..1103ce9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "blinker" @@ -12,6 +12,120 @@ files = [ {file = "blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf"}, ] +[[package]] +name = "certifi" +version = "2025.1.31" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +groups = ["main"] +files = [ + {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, + {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.1" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, + {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, + {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, +] + [[package]] name = "click" version = "8.1.8" @@ -79,6 +193,21 @@ Werkzeug = ">=3.1" async = ["asgiref (>=3.2)"] dotenv = ["python-dotenv"] +[[package]] +name = "idna" +version = "3.10" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +groups = ["main"] +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -243,6 +372,28 @@ tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + [[package]] name = "tinydb" version = "3.15.2" @@ -298,6 +449,24 @@ files = [ {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] +[[package]] +name = "urllib3" +version = "2.3.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, + {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + [[package]] name = "werkzeug" version = "3.1.3" @@ -319,4 +488,4 @@ watchdog = ["watchdog (>=2.3)"] [metadata] lock-version = "2.1" python-versions = ">=3.10" -content-hash = "29ea72f4fd9859486c77dc4fd0668e0c55b618c56c01c23a0e2ce0a2cf75d026" +content-hash = "264c2adc87fa8495be2e676b2dcc8062916089f0b63d8d39a17d39fd0d8dd7b2" diff --git a/pyproject.toml b/pyproject.toml index 686def7..223ddb3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ dependencies = [ "pytest>=7.0.0", "flask (>=3.1.0,<4.0.0)", "tinydb (>=3.1.0,<4.0.0)", + "requests (>=2.32.3,<3.0.0)", ] diff --git a/senju/ai_gen.py b/senju/ai_gen.py new file mode 100644 index 0000000..3909b7f --- /dev/null +++ b/senju/ai_gen.py @@ -0,0 +1,41 @@ +import json +import requests +from senju.haiku import Haiku + +AI_BASE_URL: str = "http://ollama:11434/api" +AI_GEN_ENDPOINT: str = "/generate" + +AI_GEN_SYS_PROMPT = """ +You are a helpful AI agent whos task it is to generate Haikus from user input. +Here is the definition of a Haiku: + +Haiku (俳句) is a type of short form poetry that originated in Japan. Traditional Japanese haiku consist of three +phrases composed of 17 morae (called on in Japanese) in a 5, 7, 5 pattern that include a kireji, +or "cutting word" and a kigo, or seasonal reference. + +You must return only the poem and nothing else. +You must return the poem in a json format in the following format: +{ + line1: First line of the poem, + line2: Second line of the poem, + line3: Third line of the poem, +} + +Your input is as follows: +""" + +def request_haiku(seed: str) -> Haiku: + """This function prompts the ai to generate the hauku based on the user input""" + + ai_gen_request = { + "model": "llama3.2:1b", + "prompt": f"{AI_GEN_SYS_PROMPT}{seed}", + "stream": False + } + + r = requests.post(url=AI_BASE_URL+AI_GEN_ENDPOINT, json=ai_gen_request) + + ai_response = json.loads(r.json()["response"]) + print(ai_response) + haiku = Haiku([ai_response["line1"], ai_response["line2"], ai_response["line3"]]) + return haiku diff --git a/senju/haiku.py b/senju/haiku.py index 15d2a28..a6cb4d6 100644 --- a/senju/haiku.py +++ b/senju/haiku.py @@ -1,6 +1,10 @@ from dataclasses import dataclass - +import json @dataclass class Haiku: lines: list[str] + + def get_json(self): + return json.dumps(self.lines) + diff --git a/senju/main.py b/senju/main.py index 15b232e..ef2d676 100644 --- a/senju/main.py +++ b/senju/main.py @@ -1,6 +1,8 @@ from pathlib import Path -from flask import Flask, redirect, render_template, url_for +from flask import Flask, redirect, render_template, url_for, request +from senju import haiku +from senju.ai_gen import request_haiku from senju.haiku import Haiku from senju.store_manager import StoreManager @@ -45,3 +47,13 @@ def prompt_view(): "prompt.html", title="Haiku generation" ) + +@app.route("/generate_haiku", methods=['POST']) +def generate_haiku(): + prompt = "a" + print("Generation function") + if request.method == 'POST': + json_data = request.get_json() + prompt = json_data["prompt"] + haiku = request_haiku(prompt) + return haiku.get_json() diff --git a/senju/templates/prompt.html b/senju/templates/prompt.html index 42c5ff2..e0387a4 100644 --- a/senju/templates/prompt.html +++ b/senju/templates/prompt.html @@ -1,4 +1,4 @@ -{% extends "base.jinja" %} +{% extends "base.html" %} {% block content %}
@@ -48,10 +48,24 @@ document.getElementById("submit-btn").addEventListener("click", function() { responseText.textContent = "🤖 AI is thinking..."; responseBox.classList.remove("opacity-0"); - // Simulated AI response delay - setTimeout(() => { - responseText.textContent = `"${userInput}" sounds interesting! Let's explore more! 🌟`; - }, 1500); + console.log(userInput ); + + fetch('/generate_haiku', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({'prompt': userInput}) + }) + .then(response => response.json()) + .then(data => { + console.log(data); + responseText.innerHTML = data[0] + "
" + data[1] + "
" + data[2]; + }) + .catch(error => { + document.getElementById('result').innerHTML = 'Error: ' + error.message; + }); + } }); From 6c698d15287be56b234226ffae7c658e8a8c54fd Mon Sep 17 00:00:00 2001 From: Alivecow Date: Fri, 28 Feb 2025 22:00:52 +0100 Subject: [PATCH 02/13] feat: Add redirection to Haiku page and save in DB Refs: OPS-22 --- senju/main.py | 5 +++-- senju/templates/prompt.html | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/senju/main.py b/senju/main.py index ef2d676..b1641bb 100644 --- a/senju/main.py +++ b/senju/main.py @@ -55,5 +55,6 @@ def generate_haiku(): if request.method == 'POST': json_data = request.get_json() prompt = json_data["prompt"] - haiku = request_haiku(prompt) - return haiku.get_json() + haiku = request_haiku(prompt) + id = store.save_haiku(haiku) + return str(id) diff --git a/senju/templates/prompt.html b/senju/templates/prompt.html index e0387a4..ec0cf93 100644 --- a/senju/templates/prompt.html +++ b/senju/templates/prompt.html @@ -57,10 +57,12 @@ document.getElementById("submit-btn").addEventListener("click", function() { }, body: JSON.stringify({'prompt': userInput}) }) - .then(response => response.json()) + .then(response => response.text()) .then(data => { console.log(data); - responseText.innerHTML = data[0] + "
" + data[1] + "
" + data[2]; + //responseText.innerHTML = data[0] + "
" + data[1] + "
" + data[2]; + let id = parseInt(data, 10); + window.location.replace("/haiku/"+id); }) .catch(error => { document.getElementById('result').innerHTML = 'Error: ' + error.message; From b8994a3d02f27fa87ea8e04c0eabc610925dd1c2 Mon Sep 17 00:00:00 2001 From: Alivecow Date: Fri, 28 Feb 2025 22:10:39 +0100 Subject: [PATCH 03/13] refactor: Change sys prompt and redirection to Haiku page Refs: OPS-22 --- senju/ai_gen.py | 1 + senju/templates/prompt.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/senju/ai_gen.py b/senju/ai_gen.py index 3909b7f..2b3294c 100644 --- a/senju/ai_gen.py +++ b/senju/ai_gen.py @@ -13,6 +13,7 @@ Haiku (俳句) is a type of short form poetry that originated in Japan. Traditio phrases composed of 17 morae (called on in Japanese) in a 5, 7, 5 pattern that include a kireji, or "cutting word" and a kigo, or seasonal reference. +The poem must contain the subjects of the user input. You must return only the poem and nothing else. You must return the poem in a json format in the following format: { diff --git a/senju/templates/prompt.html b/senju/templates/prompt.html index ec0cf93..699dfd3 100644 --- a/senju/templates/prompt.html +++ b/senju/templates/prompt.html @@ -62,7 +62,7 @@ document.getElementById("submit-btn").addEventListener("click", function() { console.log(data); //responseText.innerHTML = data[0] + "
" + data[1] + "
" + data[2]; let id = parseInt(data, 10); - window.location.replace("/haiku/"+id); + window.location.href = "/haiku/"+id; }) .catch(error => { document.getElementById('result').innerHTML = 'Error: ' + error.message; From 8c0a7771e0e476947ad6a702c256b70619b198ba Mon Sep 17 00:00:00 2001 From: Alivecow Date: Fri, 28 Feb 2025 22:21:03 +0100 Subject: [PATCH 04/13] refactor: Change format to conform to flake8 --- senju/ai_gen.py | 9 ++++++--- senju/main.py | 1 - 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/senju/ai_gen.py b/senju/ai_gen.py index 2b3294c..ff02baa 100644 --- a/senju/ai_gen.py +++ b/senju/ai_gen.py @@ -9,8 +9,10 @@ AI_GEN_SYS_PROMPT = """ You are a helpful AI agent whos task it is to generate Haikus from user input. Here is the definition of a Haiku: -Haiku (俳句) is a type of short form poetry that originated in Japan. Traditional Japanese haiku consist of three -phrases composed of 17 morae (called on in Japanese) in a 5, 7, 5 pattern that include a kireji, +Haiku (俳句) is a type of short form poetry that originated in Japan. +Traditional Japanese haiku consist of three +phrases composed of 17 morae (called on in Japanese) +in a 5, 7, 5 pattern that include a kireji, or "cutting word" and a kigo, or seasonal reference. The poem must contain the subjects of the user input. @@ -26,7 +28,8 @@ Your input is as follows: """ def request_haiku(seed: str) -> Haiku: - """This function prompts the ai to generate the hauku based on the user input""" + """This function prompts the ai to generate + the hauku based on the user input""" ai_gen_request = { "model": "llama3.2:1b", diff --git a/senju/main.py b/senju/main.py index b1641bb..e974ad1 100644 --- a/senju/main.py +++ b/senju/main.py @@ -1,7 +1,6 @@ from pathlib import Path from flask import Flask, redirect, render_template, url_for, request -from senju import haiku from senju.ai_gen import request_haiku from senju.haiku import Haiku from senju.store_manager import StoreManager From 0243091b7607ae17a5c488ddb9054d559cfbd5be Mon Sep 17 00:00:00 2001 From: Alivecow Date: Sat, 1 Mar 2025 21:36:00 +0100 Subject: [PATCH 05/13] refactor: Rework ai generation Refs: OPS-22 This is meant to rework the ai generation by adding error handling by regenerating the prompt --- senju/ai_gen.py | 58 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/senju/ai_gen.py b/senju/ai_gen.py index ff02baa..2a12a90 100644 --- a/senju/ai_gen.py +++ b/senju/ai_gen.py @@ -6,25 +6,40 @@ AI_BASE_URL: str = "http://ollama:11434/api" AI_GEN_ENDPOINT: str = "/generate" AI_GEN_SYS_PROMPT = """ -You are a helpful AI agent whos task it is to generate Haikus from user input. -Here is the definition of a Haiku: +You are a haiku generation AI. Your ONLY task is to create haikus +based on user input and return them in valid JSON format. -Haiku (俳句) is a type of short form poetry that originated in Japan. -Traditional Japanese haiku consist of three -phrases composed of 17 morae (called on in Japanese) -in a 5, 7, 5 pattern that include a kireji, -or "cutting word" and a kigo, or seasonal reference. +HAIKU DEFINITION: +- Traditional Japanese poetry with three lines +- 5 syllables in the first line +- 7 syllables in the second line +- 5 syllables in the third line +- Must incorporate the subject(s) from user input -The poem must contain the subjects of the user input. -You must return only the poem and nothing else. -You must return the poem in a json format in the following format: +OUTPUT RULES: +1. ONLY respond with a valid JSON object in this exact format: { - line1: First line of the poem, - line2: Second line of the poem, - line3: Third line of the poem, + "line1": "First line of haiku", + "line2": "Second line of haiku", + "line3": "Third line of haiku" } -Your input is as follows: +2. Do NOT include: + - Any explanations + - Any markdown formatting (like ```json or ```) + - Any additional text before or after the JSON + - Any line breaks within the JSON structure + +3. Before submitting, verify: + - The JSON uses double quotes (not single quotes) + - All property names are lowercase and exactly as shown above + - There are no trailing commas + - The JSON is properly formatted + +IMPORTANT: The output will be consumed by a web application that requires +EXACT FORMAT compliance. Any deviation will cause the application to break. + +USER INPUT FOR HAIKU CREATION: """ def request_haiku(seed: str) -> Haiku: @@ -37,9 +52,14 @@ def request_haiku(seed: str) -> Haiku: "stream": False } - r = requests.post(url=AI_BASE_URL+AI_GEN_ENDPOINT, json=ai_gen_request) - - ai_response = json.loads(r.json()["response"]) - print(ai_response) - haiku = Haiku([ai_response["line1"], ai_response["line2"], ai_response["line3"]]) + while True: + try: + r = requests.post(url=AI_BASE_URL+AI_GEN_ENDPOINT, json=ai_gen_request) + ai_response = json.loads(r.json()["response"]) + haiku = Haiku([ai_response["line1"], ai_response["line2"], ai_response["line3"]]) + break; + except: + pass + return haiku + From edf145c8de3067a6b11e3e5b724e81849d5c1ed5 Mon Sep 17 00:00:00 2001 From: Alivecow Date: Mon, 3 Mar 2025 15:36:03 +0100 Subject: [PATCH 06/13] feat: Add Method not Allowed handling for generate API and imporove error handling Refs: OPS-12 --- senju/ai_gen.py | 28 +++++++++++++++++++--------- senju/haiku.py | 6 ++++-- senju/main.py | 15 ++++++++++----- senju/store_manager.py | 10 ++++++---- senju/templates/prompt.html | 15 +++++++-------- tests/conftest.py | 2 ++ tests/test_store.py | 2 ++ tests/test_tests.py | 3 +++ 8 files changed, 53 insertions(+), 28 deletions(-) diff --git a/senju/ai_gen.py b/senju/ai_gen.py index 2a12a90..9dec9ae 100644 --- a/senju/ai_gen.py +++ b/senju/ai_gen.py @@ -1,8 +1,12 @@ +from __future__ import annotations + import json + import requests + from senju.haiku import Haiku -AI_BASE_URL: str = "http://ollama:11434/api" +AI_BASE_URL: str = "http://ollama:11434/api" AI_GEN_ENDPOINT: str = "/generate" AI_GEN_SYS_PROMPT = """ @@ -42,10 +46,11 @@ EXACT FORMAT compliance. Any deviation will cause the application to break. USER INPUT FOR HAIKU CREATION: """ + def request_haiku(seed: str) -> Haiku: """This function prompts the ai to generate the hauku based on the user input""" - + ai_gen_request = { "model": "llama3.2:1b", "prompt": f"{AI_GEN_SYS_PROMPT}{seed}", @@ -54,12 +59,17 @@ def request_haiku(seed: str) -> Haiku: while True: try: - r = requests.post(url=AI_BASE_URL+AI_GEN_ENDPOINT, json=ai_gen_request) + r = requests.post(url=AI_BASE_URL+AI_GEN_ENDPOINT, + json=ai_gen_request) ai_response = json.loads(r.json()["response"]) - haiku = Haiku([ai_response["line1"], ai_response["line2"], ai_response["line3"]]) - break; - except: - pass - - return haiku + haiku = Haiku( + [ + ai_response["line1"], + ai_response["line2"], + ai_response["line3"] + ]) + break + except json.JSONDecodeError: + continue + return haiku diff --git a/senju/haiku.py b/senju/haiku.py index a6cb4d6..1a626e4 100644 --- a/senju/haiku.py +++ b/senju/haiku.py @@ -1,5 +1,8 @@ -from dataclasses import dataclass +from __future__ import annotations + import json +from dataclasses import dataclass + @dataclass class Haiku: @@ -7,4 +10,3 @@ class Haiku: def get_json(self): return json.dumps(self.lines) - diff --git a/senju/main.py b/senju/main.py index e974ad1..75f6043 100644 --- a/senju/main.py +++ b/senju/main.py @@ -1,5 +1,8 @@ +from __future__ import annotations + from pathlib import Path -from flask import Flask, redirect, render_template, url_for, request + +from flask import Flask, redirect, render_template, request, url_for from senju.ai_gen import request_haiku from senju.haiku import Haiku @@ -47,13 +50,15 @@ def prompt_view(): title="Haiku generation" ) + @app.route("/generate_haiku", methods=['POST']) def generate_haiku(): prompt = "a" - print("Generation function") if request.method == 'POST': json_data = request.get_json() prompt = json_data["prompt"] - haiku = request_haiku(prompt) - id = store.save_haiku(haiku) - return str(id) + haiku = request_haiku(prompt) + id = store.save_haiku(haiku) + return str(id) + else: + return "Method not allowed", 405 diff --git a/senju/store_manager.py b/senju/store_manager.py index 4886559..e99b98e 100644 --- a/senju/store_manager.py +++ b/senju/store_manager.py @@ -1,8 +1,10 @@ -from typing import Optional -from tinydb import TinyDB -from pathlib import Path -from logging import Logger +from __future__ import annotations +from logging import Logger +from pathlib import Path +from typing import Optional + +from tinydb import TinyDB from tinydb.queries import QueryImpl from senju.haiku import Haiku diff --git a/senju/templates/prompt.html b/senju/templates/prompt.html index 699dfd3..730d47e 100644 --- a/senju/templates/prompt.html +++ b/senju/templates/prompt.html @@ -5,21 +5,21 @@

Very 1337 prompt input

- -
- +

Response:

Waiting for input...

@@ -72,4 +72,3 @@ document.getElementById("submit-btn").addEventListener("click", function() { }); {% endblock %} - diff --git a/tests/conftest.py b/tests/conftest.py index 0967994..5b2b1b2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import tempfile from pathlib import Path diff --git a/tests/test_store.py b/tests/test_store.py index f49b754..dc770c7 100644 --- a/tests/test_store.py +++ b/tests/test_store.py @@ -1,5 +1,7 @@ # do not remove this import. This is needed for # pytest fixtures to work +from __future__ import annotations + import pytest # noqa: F401 from senju.haiku import Haiku diff --git a/tests/test_tests.py b/tests/test_tests.py index 90bf9fa..58ab3fa 100644 --- a/tests/test_tests.py +++ b/tests/test_tests.py @@ -1,7 +1,10 @@ # I do not trust python and it's tests, so I'm testing them. May not be worth # much, but at least it shows me a few things. +from __future__ import annotations + import os + # do not remove this import. This is needed for # pytest fixtures to work import pytest # noqa: F401 From 0c4e88cf7e7bde81b88d7ce4b7b7bd91bf81d974 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 14:36:32 +0000 Subject: [PATCH 07/13] ci: automatic Python Formatter changes --- senju/ai_gen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/senju/ai_gen.py b/senju/ai_gen.py index 9dec9ae..a310d0c 100644 --- a/senju/ai_gen.py +++ b/senju/ai_gen.py @@ -59,7 +59,7 @@ def request_haiku(seed: str) -> Haiku: while True: try: - r = requests.post(url=AI_BASE_URL+AI_GEN_ENDPOINT, + r = requests.post(url=AI_BASE_URL + AI_GEN_ENDPOINT, json=ai_gen_request) ai_response = json.loads(r.json()["response"]) haiku = Haiku( From 76ad52d3a9ea571cc14c37b310768373a91d62b8 Mon Sep 17 00:00:00 2001 From: Alivecow Date: Mon, 3 Mar 2025 15:55:48 +0100 Subject: [PATCH 08/13] refactor: Addressing PR comments Refs: OPS-12 Consolidated AI gen module Changed API endpoint --- senju/ai_gen.py | 75 ------------------------------------- senju/haiku.py | 70 ++++++++++++++++++++++++++++++++++ senju/main.py | 5 +-- senju/templates/prompt.html | 2 +- 4 files changed, 73 insertions(+), 79 deletions(-) delete mode 100644 senju/ai_gen.py diff --git a/senju/ai_gen.py b/senju/ai_gen.py deleted file mode 100644 index 9dec9ae..0000000 --- a/senju/ai_gen.py +++ /dev/null @@ -1,75 +0,0 @@ -from __future__ import annotations - -import json - -import requests - -from senju.haiku import Haiku - -AI_BASE_URL: str = "http://ollama:11434/api" -AI_GEN_ENDPOINT: str = "/generate" - -AI_GEN_SYS_PROMPT = """ -You are a haiku generation AI. Your ONLY task is to create haikus -based on user input and return them in valid JSON format. - -HAIKU DEFINITION: -- Traditional Japanese poetry with three lines -- 5 syllables in the first line -- 7 syllables in the second line -- 5 syllables in the third line -- Must incorporate the subject(s) from user input - -OUTPUT RULES: -1. ONLY respond with a valid JSON object in this exact format: -{ - "line1": "First line of haiku", - "line2": "Second line of haiku", - "line3": "Third line of haiku" -} - -2. Do NOT include: - - Any explanations - - Any markdown formatting (like ```json or ```) - - Any additional text before or after the JSON - - Any line breaks within the JSON structure - -3. Before submitting, verify: - - The JSON uses double quotes (not single quotes) - - All property names are lowercase and exactly as shown above - - There are no trailing commas - - The JSON is properly formatted - -IMPORTANT: The output will be consumed by a web application that requires -EXACT FORMAT compliance. Any deviation will cause the application to break. - -USER INPUT FOR HAIKU CREATION: -""" - - -def request_haiku(seed: str) -> Haiku: - """This function prompts the ai to generate - the hauku based on the user input""" - - ai_gen_request = { - "model": "llama3.2:1b", - "prompt": f"{AI_GEN_SYS_PROMPT}{seed}", - "stream": False - } - - while True: - try: - r = requests.post(url=AI_BASE_URL+AI_GEN_ENDPOINT, - json=ai_gen_request) - ai_response = json.loads(r.json()["response"]) - haiku = Haiku( - [ - ai_response["line1"], - ai_response["line2"], - ai_response["line3"] - ]) - break - except json.JSONDecodeError: - continue - - return haiku diff --git a/senju/haiku.py b/senju/haiku.py index 1a626e4..4450308 100644 --- a/senju/haiku.py +++ b/senju/haiku.py @@ -3,6 +3,48 @@ from __future__ import annotations import json from dataclasses import dataclass +import requests + +AI_BASE_URL: str = "http://ollama:11434/api" +AI_GEN_ENDPOINT: str = "/generate" + +AI_GEN_SYS_PROMPT = """ +You are a haiku generation AI. Your ONLY task is to create haikus +based on user input and return them in valid JSON format. + +HAIKU DEFINITION: +- Traditional Japanese poetry with three lines +- 5 syllables in the first line +- 7 syllables in the second line +- 5 syllables in the third line +- Must incorporate the subject(s) from user input + +OUTPUT RULES: +1. ONLY respond with a valid JSON object in this exact format: +{ +"line1": "First line of haiku", +"line2": "Second line of haiku", +"line3": "Third line of haiku" +} + +2. Do NOT include: +- Any explanations +- Any markdown formatting (like ```json or ```) +- Any additional text before or after the JSON +- Any line breaks within the JSON structure + +3. Before submitting, verify: +- The JSON uses double quotes (not single quotes) +- All property names are lowercase and exactly as shown above +- There are no trailing commas +- The JSON is properly formatted + +IMPORTANT: The output will be consumed by a web application that requires +EXACT FORMAT compliance. Any deviation will cause the application to break. + +USER INPUT FOR HAIKU CREATION: +""" + @dataclass class Haiku: @@ -10,3 +52,31 @@ class Haiku: def get_json(self): return json.dumps(self.lines) + + @staticmethod + def request_haiku(seed: str) -> Haiku: + """This function prompts the ai to generate + the hauku based on the user input""" + + ai_gen_request = { + "model": "llama3.2:1b", + "prompt": f"{AI_GEN_SYS_PROMPT}{seed}", + "stream": False + } + + while True: + try: + r = requests.post(url=AI_BASE_URL+AI_GEN_ENDPOINT, + json=ai_gen_request) + ai_response = json.loads(r.json()["response"]) + haiku = Haiku( + [ + ai_response["line1"], + ai_response["line2"], + ai_response["line3"] + ]) + break + except json.JSONDecodeError: + continue + + return haiku diff --git a/senju/main.py b/senju/main.py index 75f6043..c9aa498 100644 --- a/senju/main.py +++ b/senju/main.py @@ -4,7 +4,6 @@ from pathlib import Path from flask import Flask, redirect, render_template, request, url_for -from senju.ai_gen import request_haiku from senju.haiku import Haiku from senju.store_manager import StoreManager @@ -51,13 +50,13 @@ def prompt_view(): ) -@app.route("/generate_haiku", methods=['POST']) +@app.route("/api/v1/haiku", methods=['POST']) def generate_haiku(): prompt = "a" if request.method == 'POST': json_data = request.get_json() prompt = json_data["prompt"] - haiku = request_haiku(prompt) + haiku = Haiku.request_haiku(prompt) id = store.save_haiku(haiku) return str(id) else: diff --git a/senju/templates/prompt.html b/senju/templates/prompt.html index 730d47e..1f08089 100644 --- a/senju/templates/prompt.html +++ b/senju/templates/prompt.html @@ -50,7 +50,7 @@ document.getElementById("submit-btn").addEventListener("click", function() { console.log(userInput ); - fetch('/generate_haiku', { + fetch('/api/v1/haiku', { method: 'POST', headers: { 'Content-Type': 'application/json' From dc9438d2fbbe89ec05d4ee282b29cec5504492c7 Mon Sep 17 00:00:00 2001 From: Alivecow Date: Mon, 3 Mar 2025 16:02:11 +0100 Subject: [PATCH 09/13] refactor: Remove commented code Refs: OPS-12 --- senju/templates/prompt.html | 1 - 1 file changed, 1 deletion(-) diff --git a/senju/templates/prompt.html b/senju/templates/prompt.html index 1f08089..218809d 100644 --- a/senju/templates/prompt.html +++ b/senju/templates/prompt.html @@ -60,7 +60,6 @@ document.getElementById("submit-btn").addEventListener("click", function() { .then(response => response.text()) .then(data => { console.log(data); - //responseText.innerHTML = data[0] + "
" + data[1] + "
" + data[2]; let id = parseInt(data, 10); window.location.href = "/haiku/"+id; }) From e96ab55378f0cfacb7392b5841dd7d4a00d8f89b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:02:37 +0000 Subject: [PATCH 10/13] ci: automatic Python Formatter changes --- senju/haiku.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/senju/haiku.py b/senju/haiku.py index 4450308..6a32071 100644 --- a/senju/haiku.py +++ b/senju/haiku.py @@ -66,7 +66,7 @@ class Haiku: while True: try: - r = requests.post(url=AI_BASE_URL+AI_GEN_ENDPOINT, + r = requests.post(url=AI_BASE_URL + AI_GEN_ENDPOINT, json=ai_gen_request) ai_response = json.loads(r.json()["response"]) haiku = Haiku( From 62e964b800686aa5cc6a1988cc1a40ee4c5dff84 Mon Sep 17 00:00:00 2001 From: Alivecow Date: Tue, 4 Mar 2025 17:11:50 +0100 Subject: [PATCH 11/13] refactor: Change format requested from AI Refs: OPS-12 --- senju/haiku.py | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/senju/haiku.py b/senju/haiku.py index 6a32071..2cbef17 100644 --- a/senju/haiku.py +++ b/senju/haiku.py @@ -20,24 +20,14 @@ HAIKU DEFINITION: - Must incorporate the subject(s) from user input OUTPUT RULES: -1. ONLY respond with a valid JSON object in this exact format: -{ -"line1": "First line of haiku", -"line2": "Second line of haiku", -"line3": "Third line of haiku" -} +Put every line of the poem on a new line 2. Do NOT include: - Any explanations - Any markdown formatting (like ```json or ```) - Any additional text before or after the JSON - Any line breaks within the JSON structure - -3. Before submitting, verify: -- The JSON uses double quotes (not single quotes) -- All property names are lowercase and exactly as shown above -- There are no trailing commas -- The JSON is properly formatted +- Any special characters IMPORTANT: The output will be consumed by a web application that requires EXACT FORMAT compliance. Any deviation will cause the application to break. @@ -68,12 +58,13 @@ class Haiku: try: r = requests.post(url=AI_BASE_URL + AI_GEN_ENDPOINT, json=ai_gen_request) - ai_response = json.loads(r.json()["response"]) + ai_response = str(r.json()["response"]) + lines = ai_response.split("\n") haiku = Haiku( [ - ai_response["line1"], - ai_response["line2"], - ai_response["line3"] + lines[0], + lines[1], + lines[2] ]) break except json.JSONDecodeError: From 7c304eaa3cfd8a8390a280076bce866e3150c911 Mon Sep 17 00:00:00 2001 From: Alivecow Date: Tue, 4 Mar 2025 17:49:29 +0100 Subject: [PATCH 12/13] feat: Add valdidation for the Haiku format Refs: OPS-12 --- senju/haiku.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/senju/haiku.py b/senju/haiku.py index 2cbef17..4640afb 100644 --- a/senju/haiku.py +++ b/senju/haiku.py @@ -21,6 +21,7 @@ HAIKU DEFINITION: OUTPUT RULES: Put every line of the poem on a new line +Do not referene any of the instructions in the poem 2. Do NOT include: - Any explanations @@ -28,7 +29,7 @@ Put every line of the poem on a new line - Any additional text before or after the JSON - Any line breaks within the JSON structure - Any special characters - +count occurrences of char in string IMPORTANT: The output will be consumed by a web application that requires EXACT FORMAT compliance. Any deviation will cause the application to break. @@ -54,12 +55,37 @@ class Haiku: "stream": False } + syllable_letters: list = ['a', 'e', 'i', 'o', 'u', 'y'] while True: try: r = requests.post(url=AI_BASE_URL + AI_GEN_ENDPOINT, json=ai_gen_request) ai_response = str(r.json()["response"]) + + if ai_response.count("\"") != 0: + continue + lines = ai_response.split("\n") + if len(lines) != 3: + continue + + syllable_count = 0 + prev_was_vowel = False + for line in lines: + for letter in line: + is_vowel = letter in syllable_letters + if is_vowel and not prev_was_vowel: + syllable_count += 1 + prev_was_vowel = is_vowel + + if line.endswith('e'): + syllable_count -= 1 + if syllable_count == 0: + syllable_count = 1 + + if syllable_count != 17: + continue + haiku = Haiku( [ lines[0], From fb5c28c891c5a6cfbea331f8c101da314bba8b0d Mon Sep 17 00:00:00 2001 From: Alivecow Date: Wed, 5 Mar 2025 20:29:47 +0100 Subject: [PATCH 13/13] refactor: Remove unneded line Refs: OPS-12 --- senju/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/senju/main.py b/senju/main.py index c9aa498..bfefb1e 100644 --- a/senju/main.py +++ b/senju/main.py @@ -52,7 +52,6 @@ def prompt_view(): @app.route("/api/v1/haiku", methods=['POST']) def generate_haiku(): - prompt = "a" if request.method == 'POST': json_data = request.get_json() prompt = json_data["prompt"]