<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexey Tukalo</title>
    <description>The latest articles on DEV Community by Alexey Tukalo (@airtucha).</description>
    <link>https://dev.to/airtucha</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F273840%2F2f05f5aa-6e6e-494c-8516-1f7063eca6f3.jpeg</url>
      <title>DEV Community: Alexey Tukalo</title>
      <link>https://dev.to/airtucha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/airtucha"/>
    <language>en</language>
    <item>
      <title>How I've created my personal AI-astrologist</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Tue, 27 May 2025 16:36:51 +0000</pubDate>
      <link>https://dev.to/airtucha/how-ive-created-my-personal-ai-astrologist-2fha</link>
      <guid>https://dev.to/airtucha/how-ive-created-my-personal-ai-astrologist-2fha</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Alex: I am planning date with my girlfriend. Could you give any advice?&lt;br&gt;
AstroGPT: To sprinkle some starry magic on your plans, I need to know your girlfriend's zodiac sign or birth date. This will help me craft the perfect romantic advice just for you two! ✨&lt;br&gt;
Alex: She is an Aries.&lt;br&gt;
AstroGPT: For your date with your adventurous Aries girlfriend, I suggest planning something that combines excitement and spontaneity! How about a surprise picnic in a scenic spot or an exhilarating outdoor activity? This will definitely spark that fiery Aries enthusiasm! Enjoy the cosmic vibes of your date! 🌟✨&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Telegram bots are among the lowest-friction apps you can build today. Type &lt;code&gt;/start&lt;/code&gt; and the bot is ready - no extra install, no sign-up forms. This zero-friction setup, together with Telegram’s rich features, makes bots handy for both users and developers.&lt;/p&gt;

&lt;p&gt;Bots can handle many tasks: quick support chats for shops and clinics, daily weather or news updates, games, finance trackers. It suits for almost anything you can pack into a chat. Some bots are used as private corporate tools, while others are publicly available serving thousands of users every day.&lt;/p&gt;

&lt;h1&gt;
  
  
  How a bot really works
&lt;/h1&gt;

&lt;p&gt;Put simply, a Telegram bot is a web service that listens to the Bot API. When a user sends a message:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Telegram posts the update to the bot’s server.&lt;/li&gt;
&lt;li&gt;The server processes the input and replies to Telegram.&lt;/li&gt;
&lt;li&gt;Telegram delivers the response to the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this post, I'll walk you through the main parts of a typical Telegram bot backend, using my latest project as a reference, and show how large language models (LLMs) can help build better chatbots.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bot business logic
&lt;/h1&gt;

&lt;p&gt;Classic Telegram bots rely on strict string matching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A predefined list of commands maps to handler functions.&lt;/li&gt;
&lt;li&gt;Regular expressions extract structured data such as dates, names, or email addresses from user input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bots can also add on-screen buttons to simplify input, but users still have to send the exact text, any wrong character can break the logic.&lt;/p&gt;

&lt;p&gt;Large bots are usually split into small, separate “dialog flows” connected to a central router. Each flow is a mini state machine: it knows the user’s current step, what data has been collected, and which messages or commands are valid next. The router inspects every update (text, button press, or command), chooses the right dialog-flow and state, and forwards the update to the correct handler. State data typically lives in a database such as Redis, MongoDB, or SQL.&lt;/p&gt;

&lt;h1&gt;
  
  
  Improve input with LLMs
&lt;/h1&gt;

&lt;p&gt;In the past, you had to train a custom NLP model for intent recognition. Now large language models (LLMs) can infer intent directly from free-form text with a simple prompt. An LLM can parse a message and return structured data in JSON, making it easy to interpret free-form user input.&lt;/p&gt;

&lt;h1&gt;
  
  
  My sandbox project: &lt;strong&gt;AstroGPT&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;While experimenting with LLM-powered apps, I needed a safe way to practise building production-ready Python applications. I decided to build a (pseudo)astrology Telegram bot. It’s simple (and honestly pretty useless) but perfect for testing architecture ideas.&lt;/p&gt;

&lt;p&gt;The bot has only two dialogs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Registration – collects birth date and consent.&lt;/li&gt;
&lt;li&gt;Main chat – lets the user update their data or ask, “What do the stars say today?”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a user finishes registration and subscribes, the bot uses an LLM to generate a short horoscope and sends it automatically.&lt;/p&gt;

&lt;h1&gt;
  
  
  Initial implementation
&lt;/h1&gt;

&lt;p&gt;Because I wanted human-like free-form interactions, the usual telegram libraries mapping input-to-handlers didn’t work. I implemented the flow myself with plain &lt;code&gt;if-else&lt;/code&gt; logic. The diagram below shows the initial dialog flowchart.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fned6s5ivrfo6ixscbr0m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fned6s5ivrfo6ixscbr0m.png" alt="Image description" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Is Birthday Input&lt;/strong&gt; step uses an LLM to extract the user’s birth date from a message. The birthday parser has two parts: a parsing prompt and a schema that describes the output JSON.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BirthdayValidation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;birthday_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The birthday of the user in text format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;extraction_error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Message to display if the birthday could not be extracted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;parse_date_of_birth_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
&amp;lt;instruction&amp;gt;
Please, analyze the following text inside of text_input tag and extract birthday information in text format.

Format output according to instructions in output_formatting_guidelines tag.
&amp;lt;/instruction&amp;gt;

&amp;lt;text_input&amp;gt;
{user_input}
&amp;lt;/text_input&amp;gt;

&amp;lt;output_formatting_guidelines&amp;gt;
Format you reply according to {format_instructions}
If you do not find readable birthday information, please provide a message in extractionError which should aks user to input birthday in readable format.
&amp;lt;/output_formatting_guidelines&amp;gt;
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The schema is defined with LangChain’s Pydantic extension. Each field gets a name, type, and short description. LangChain turns this schema into formatting instructions, injected into the prompt as &lt;code&gt;{format_instructions}&lt;/code&gt;. The raw &lt;code&gt;{user_input}&lt;/code&gt; is added as well. I wrap both parts in simple XML-style tags so my instructions stay clearly separated from the user’s text.&lt;/p&gt;

&lt;p&gt;The next diagram shows logic of the feature-complete application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbxbf7fcp74dr5ky579g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbxbf7fcp74dr5ky579g.png" alt="Image description" width="800" height="736"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  More advanced prompts
&lt;/h1&gt;

&lt;p&gt;While testing parsing prompts, I realised I could merge extraction of several values into one request and cut the total number of LLM calls. In normal conversation, users often provide all the details in a single message anyway. This change both simplifies the code and makes the chatbot feel more natural. &lt;/p&gt;

&lt;p&gt;After some experiments I settled on the following JSON schema and prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CollectDataParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user_birthday_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The birthday of the user in text format, birthday should be in free for format, but it should be reasonable date of birth.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Desired language option of the user. Do not consider language already available in user information. Convert it to single English word like in list of supported languages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;is_data_about_user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Based on input and context of previous conversation, is the data about the user or about someone else?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;parsing_feedback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explanation of data extraction result with clarification of errors is needed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;collect_data_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
&amp;lt;instruction&amp;gt;
You are a part of logic in personal astrologist bot.
Your should collect information from user to provide astrologic forecast.
You have to be completely sure that it is information about the user, since user can also mention other people in the conversation.

You do not support any other actions and do not engage conversation beyond collecting necessary information.
Provide user with kind and clear feedback on any issues with the data provided.
Ask user for input if some information is missing or unclear.
If users asks something beyond the data collection, just ignore it.

previous_conversation tag contains log of previous conversation with user.

user_information tag contains user information. 
Do not extract information if it exactly matches the information already available in user_information.

last_user_input tag contains last user input.

output_formatting_guidelines tag contains instructions on how to format your reply.
&amp;lt;/instruction&amp;gt;

&amp;lt;user_information&amp;gt;
Name: {user_name}
Birthday: {user_birthday}
Subscription: {user_subscription}
Language: {user_language}
&amp;lt;/user_information&amp;gt;

&amp;lt;previous_conversation&amp;gt;
{previous_conversation}
&amp;lt;/previous_conversation&amp;gt;

&amp;lt;last_user_input&amp;gt;
{user_input}
&amp;lt;/last_user_input&amp;gt;

&amp;lt;output_formatting_guidelines&amp;gt;
Please, extract user information from the user_input.
Provide parsing feedback if any issues with the data extraction.
Do not extract information if it exactly matches the information already available in user_information.

Format you reply according to {format_instructions}
&amp;lt;/output_formatting_guidelines&amp;gt;
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Leveraging LLM reasoning
&lt;/h1&gt;

&lt;p&gt;As the number of dialogs grew, the application logic expanded quickly and adding new features became hard. The user experience still felt robotic—more like an upgraded CLI than a chat.&lt;/p&gt;

&lt;p&gt;To cut down the prompt count, I let the LLM handle the reasoning instead of using deep &lt;code&gt;if-else&lt;/code&gt; blocks. The change worked surprisingly well: it simplified the design and made conversations flow more natural. After a few iterations, I settled on the approach below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1
&lt;/h2&gt;

&lt;p&gt;The “menu” prompt receives the latest user message, recent chat history, user data, a list of available actions, and summary of actions already taken for this input. The LLM just has to pick the next action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MenuActions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;update_user_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;update_user_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;subscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subscribe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unsubscribe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;request_input_clarification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request_input_clarification&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;reply_to_user_with_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reply_to_user_with_result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;ask_for_missing_user_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ask_for_missing_user_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;get_situational_advice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_situational_advice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;get_joke_about_astrology&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_joke_about_astrology&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;get_daily_forecast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_daily_forecast&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SelectedAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;selected_action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MenuActions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Decision for future action to take&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;context_for_action_execution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Action will be executed by specialized handler, provide just brief context necessary to execute it properly.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;message_to_user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Only provide message to the user if it is terminal action which imply communication with the user, otherwise leave it empty.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Action: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selected_action&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Description: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context_for_action_execution&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message_to_user&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message_to_user&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="n"&gt;menu_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
&amp;lt;instruction&amp;gt;
You are a part of logic in personal astrologist bot. 
You should handle a user input and make a decision on the next action to take.
You should should not act on the decision, but provide a decision for the next action to take.
You can provide details to help future actions with more context.

You support following actions:

- Update user data, even if it is already provided e.g. name, birthday, language (update_user_data action), keep in mind you should be sure that the data belongs to the user, it should not be data of other people mentioned in the conversation.
- Subscribe to daily forecast, daily forecast is only available by subscription
- Unsubscribe from daily forecast
- Ask user for input if any action failed
- Ask user for input if any request is unclear
- Send message to user if user goal is achieved
- Supply user with an information regarding service you can provide
- You can also provide information about users state if it is requested
- Provide user with a short astrological advice if user ask about things like mood, outfit, love, work, food choices etc. user (get_situational_advice action)
- Give user a short clarification of the latest daily forecast regarding certain situation or particular details (get_situational_advice action) 
- If user specifically ask forecast for today (call get_daily_forecast to leverage specific logic)
- Joke about astrology (finish conversation if joke is already generated)

You do not support any other actions. 
Provide user with kinda and clear feedback on service your can provide.
Clarify if user wants general daily forecast or specific advice on particular aspect of life.

processing_steps tag contains log of actions already taken during handling of current user input.
Information in the steps is not communicated to user, it is internal log of actions taken during handling of user input.
Reply user as soon as you have enough information to fulfill user request or if you need more information from user.
Ask user for input if any step in processing_steps failed.
Finish the conversation immediately if you have enough information to reply to user.
Do not select the same action if it was successfully executed.

previous_conversation tag contains log of previous conversation with user.

user_information tag contains user information. 
One of your goal is to collect missing information in user_information.
Do not ask user for information already available in user_information.

last_user_input tag contains last user input.

output_formatting_guidelines tag contains instructions on how to format your reply.
&amp;lt;/instruction&amp;gt;

&amp;lt;processing_steps&amp;gt;
{processing_steps}
&amp;lt;/processing_steps&amp;gt;

&amp;lt;previous_conversation&amp;gt;
{previous_conversation}
&amp;lt;/previous_conversation&amp;gt;

&amp;lt;user_information&amp;gt;
Name: {user_name}
Birthday: {user_birthday}
Subscription: {user_subscription}
Language: {user_language}
&amp;lt;/user_information&amp;gt;

&amp;lt;last_user_input&amp;gt;
{user_input}
&amp;lt;/last_user_input&amp;gt;

&amp;lt;output_formatting_guidelines&amp;gt;
Please, provide a decision for future action to take and necessary context for future action.
Format you reply according to {format_instructions}
&amp;lt;/output_formatting_guidelines&amp;gt;
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2
&lt;/h2&gt;

&lt;p&gt;The chosen action is executed, it might call another LLM, hit a third-party API, or write to the database. When it finishes, it appends a description of execution result as an entry to the log of executed actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdviceResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;advice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;advice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;clarification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clarification&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdviceParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;advice_result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AdviceResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If you have enough information to provide advice, select advice. If you need more information from the user, select clarification&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result_description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Description of astrological advice or clarification for the user. Do not provide advice if anything is unclear. Do not ask too many questions, you are astrological bot, stars should guid your decisions, so improvise more!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;situation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Description of the situation for which the advice is given&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;advice_parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PydanticOutputParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pydantic_object&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;AdviceParser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;advice_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
&amp;lt;instruction&amp;gt;
You are a personal astrologist bot.
You should an provide user with an astrological advice based on the situation provided or clarify latest daily forecast.
Mention zodiacal signs of other people involved and provide user with a clear recommendation in relation to the situation provided and signs mentioned.
Be more descriptive in your advice, feel free to suggest exact activities or actions to take.
Tell user advice considering the situation provided and zodiacal signs of user and potentially other people involved in the situation.
Do not repeat daily forecast exactly, but provide clarification if needed.

Ask user for more details on situation if it help to provide more accurate advice. 
Ask zodiacs or birth dates of people involved in the situation.

Provide user with kind and clear recommendation.
Ask user for input if some information is missing or unclear.
Keep it short, concise and consistent with context of previous advices, forecast and messages.

previous_conversation tag contains log of previous conversation with user.
user_information tag contains user information.
previous_advice tag contains log of previous advices provided to user.
previous_forecast tag contains log of previous daily forecasts provided to user. 

last_user_input tag contains last user input.

output_formatting_guidelines tag contains instructions on how to format your reply.
&amp;lt;/instruction&amp;gt;

&amp;lt;user_information&amp;gt;
Name: {user_name}
Birthday: {user_birthday}
Subscription: {user_subscription}
Language: {user_language}
&amp;lt;/user_information&amp;gt;

&amp;lt;previous_conversation&amp;gt;
{previous_conversation}
&amp;lt;/previous_conversation&amp;gt;

&amp;lt;last_user_input&amp;gt;
{user_input}
&amp;lt;/last_user_input&amp;gt;

&amp;lt;previous_forecast&amp;gt;
{previous_forecast}
&amp;lt;/previous_forecast&amp;gt;

&amp;lt;previous_advice&amp;gt;
{previous_advice}
&amp;lt;/previous_advice&amp;gt;

&amp;lt;output_formatting_guidelines&amp;gt;
It should be a short and concise advice. Max 2 sentences.
Format you reply according to {format_instructions}
&amp;lt;/output_formatting_guidelines&amp;gt;
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3
&lt;/h2&gt;

&lt;p&gt;Steps 1 and 2 repeat until threshold is reached or the "menu" prompt selected "reply_to_user_with_result". A final prompt then processes the full action log, user data, and the original input to generate the reply, which is sent back to the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reply_user_prompt = """
&amp;lt;instruction&amp;gt;
You are a personal astrologist bot, your name is Zaira and you use cosmic energy to help people with their problems.
You should reply user on his latest message summarizing actions which were taken.
Please, be, playful, witty and charming.
&amp;lt;/instruction&amp;gt;

&amp;lt;user_information&amp;gt;
User name: {user_name}
&amp;lt;/user_information&amp;gt;

&amp;lt;previous_conversation&amp;gt;
{previous_conversation}
&amp;lt;/previous_conversation&amp;gt;

&amp;lt;last_user_input&amp;gt;
{user_input}
&amp;lt;/last_user_input&amp;gt;

&amp;lt;actions_taken&amp;gt;
{actions_taken}
&amp;lt;/actions_taken&amp;gt;

&amp;lt;output_formatting_guidelines&amp;gt;
Reply with a message that summarizes actions taken and results of those actions.
Omit intermediate steps and provide only final results.
Do no explain the actions taken, just provide the feedback in a clear and concise conversation manner.
Do no greet user, since the message is a part of ongoing conversation.
You should not provide user with any additional information or forecast beyond the actions taken.
Please, be brief, friendly, clear, supportive and use chat style language, avoid mentioning details of decision making process.
Never mention anything about Natal Charts, they are not supported by the bot.
Avoid usage of characters and brand names which could be subject to copyright.
Consider messages from previous_conversation tag in your reply, but do not repeat information from them again in your reply.
&amp;lt;/output_formatting_guidelines&amp;gt;
"""
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 0
&lt;/h2&gt;

&lt;p&gt;Before all business-logic steps, I added a safety step that spots abnormal behaviour. A prompt reviews recent messages and returns three fields: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A confidence score&lt;/li&gt;
&lt;li&gt;A warning type&lt;/li&gt;
&lt;li&gt;A warning explanation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The score lets the main logic tune the detector’s sensitivity. Each warning type can trigger different follow-up actions, and repeated warnings can make the bot block certain features to prevent abuse. The explanation text is used when composing a reply to the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnintendedBehaviorDetector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Level of warning to be issued to the user. 0.0 means no warning, 1.0 means clear evil intent. Increase confidence for repeating behavior.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;WarningType&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Type of warning to be issued&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;warning_explanation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explanation of the warning to be issued&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Warning: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;warning&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Confidante: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; Explanation: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;warning_explanation&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;Earlier, when we covered classic Telegram bots, we looked at the MVP flowchart. The diagram below shows the version based on LLM-reasoning, which adds features the MVP lacked. The new bot is more fluent: it answers general questions, cracks jokes, and even offers pseudo-astrological advice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqogrzzszaruesl7hn171.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqogrzzszaruesl7hn171.png" alt="Image description" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Despite these extras, the full flowchart is only about the size of the single “birthday input” branch in the old &lt;code&gt;if-else&lt;/code&gt; design. The LLM-reasoning works surprisingly well—the bot handles complex queries and keeps the dialog human-like. Moreover, adding a feature means just writing one small action and tweaking the main menu prompt.&lt;/p&gt;




&lt;p&gt;🚀 Code: &lt;a href="https://github.com/AIRTucha/astro-bot" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>telegram</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
    <item>
      <title>Developing a CLI Tool to Evaluate Code Cognitive Complexity with LLMs(AI)</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Tue, 15 Apr 2025 05:21:03 +0000</pubDate>
      <link>https://dev.to/airtucha/developing-a-cli-tool-to-evaluate-code-cognitive-complexity-with-llmsai-5gp</link>
      <guid>https://dev.to/airtucha/developing-a-cli-tool-to-evaluate-code-cognitive-complexity-with-llmsai-5gp</guid>
      <description>&lt;p&gt;A while ago, a friend and I were discussing code cognitive complexity and maintainability. A friend of mine wished to have a tool to automatically evaluate whether a piece of code is hard to maintain. I wasn’t sure this was even possible — maintainability is notoriously hard to quantify programmatically.&lt;/p&gt;

&lt;p&gt;But LLMs can understand and generate human-like text or even code, and I wondered if that same capability could be applied to interpreting and evaluating code quality, going beyond what traditional static analysis tools can do.&lt;/p&gt;

&lt;p&gt;That thought led to the tool I eventually built. It’s now available on &lt;a href="https://pypi.org/project/codepass/" rel="noopener noreferrer"&gt;PyPi&lt;/a&gt;, and I believe it could be a valuable addition to any CI pipeline.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/airtucha/simplifying-complex-code-with-advanced-programming-approaches-3eg9"&gt;a previous post&lt;/a&gt;, I shared some early thoughts on maintainability and cognitive complexity of code that emerged while working on this tool. In this post, I’d like to go deeper and walk through the development process, using my CLI tool as a case study for building an LLM-based application.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Leveraging LangChain for LLM-Based Applications
&lt;/h2&gt;

&lt;p&gt;To bring this idea to life, I used LangChain, a Python library for building LLM-powered applications. LangChain abstracts away the APIs of specific language models, so I could focus entirely on building the core functionality without worrying about the details of how to communicate with an LLM.&lt;/p&gt;

&lt;p&gt;One of its most useful features is the seamless integration with Pydantic. The output schemas were defined using Pydantic models, and LangChain automatically generated prompts that guided the LLM to return structured responses, otherwise a lot more time would be spent  on parsing and error handling of LLM output.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Attempt 1: Overall Design and Estimation with a Simple Prompt
&lt;/h2&gt;

&lt;p&gt;With the basic setup ready, I began designing the metric. The idea was straightforward: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Asking the LLM to evaluate each function individually and assign a cognitive complexity score from 1 to 5, where higher scores indicate code that’s harder to understand and maintain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The prompt included both formatting instructions (generated via LangChain) and an explanation of grading criteria. I experimented with different ways of phrasing the grading scale to make the results more stable and meaningful.&lt;/p&gt;

&lt;p&gt;To refine the evaluation, I added a few extra fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;is_setup_or_declaration&lt;/code&gt; flag to identify and skip boilerplate code (like config or constant declarations).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;start_line_number&lt;/code&gt; and &lt;code&gt;end_line_number&lt;/code&gt; to estimate the size of each function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, I tried using a single &lt;code&gt;function_length&lt;/code&gt; field, but estimating start and end lines separately produced more reliable results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CodeComplexityEvaluation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name of the function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;is_setup_or_declaration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The code is part of setup or declaration boilerplate, such as defining constants or configuring a framework.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;start_line_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of the first line of the function, considering existing formatting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;end_line_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of the last line of the function, considering existing formatting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;complexity_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Overall code complexity on a scale from 0 to 5, as discussed in the article &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="s"&gt;Simplifying Complex Code with Advanced Programming Approaches.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Interpretation:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0 - 1: Very low complexity. The code is straightforward, easy to read, and requires minimal domain or technical knowledge.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2 - 3: Moderate complexity. The code may use some advanced techniques or domain knowledge, but remains relatively approachable.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4: High complexity. The code relies on multiple advanced concepts, intricate domain logic, or specialized optimizations.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5: Extremely high complexity. The code likely combines various advanced paradigms, deep domain knowledge, and complex abstractions, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;making it very challenging to understand or maintain.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code was evaluated file by file. For each file, the LLM assessed maintainability of every function individually. Then, the overall file score was calculated as a length-weighted average of the complexity score for each function.&lt;/p&gt;

&lt;p&gt;The same approach was applied at the project level: the total score for the entire codebase was computed as a weighted average across all files, again considering size of each file to better reflect its impact on overall maintainability. &lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Initial Results and Observations
&lt;/h3&gt;

&lt;p&gt;This approach yielded some promising early results. The LLM was able to evaluate functions and assign scores that often aligned with my own assessments.&lt;/p&gt;

&lt;p&gt;However, I noticed the results weren’t fully consistent. Scores varied by 5–15% between runs, likely due to the stochastic nature of LLMs and their sensitivity to slight changes in input or internal randomness.&lt;/p&gt;

&lt;p&gt;In the context of a CI pipeline, this kind of inconsistency is a problem. CI tools need reliable metrics to determine whether code meets quality standards. An unstable score makes it hard to track whether code is actually improve or degrade over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  📖 Attempt 2: Enhancing Accuracy with Explanations
&lt;/h2&gt;

&lt;p&gt;To address the inconsistency, my next step was to enhance the prompt by explicitly asking the LLM to explain &lt;strong&gt;WHY&lt;/strong&gt; it assigned a particular score. &lt;/p&gt;

&lt;p&gt;From previous experiments, I had noticed that when an LLM is prompted to provide reasoning, it tends to produce more thoughtful and consistent responses. I suspect this happens because generating an explanation forces the model to “think through” its decision, leading to better alignment between the score and the reasoning behind it.&lt;/p&gt;

&lt;p&gt;These explanations were also for helping me spot recurring patterns or biases in the model’s behavior. In some cases, I could identify where the prompt needed fine-tuning or where the LLM misunderstood me. This kind of prompt iteration is an essential part of building robust LLM-based applications.&lt;/p&gt;

&lt;p&gt;While this adjustment did lead to slightly more stable scores, the improvement wasn’t enough. Variability was reduced, but not to a level I felt comfortable using in a CI pipeline. I needed a more robust solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  📊 Attempt 3: Incorporating Multiple Metrics for Robustness
&lt;/h2&gt;

&lt;p&gt;I realized that relying on a single score to capture code complexity was too limiting and too fragile. So I shifted toward evaluating multiple metrics, each representing a different aspect of cognitive complexity.&lt;/p&gt;

&lt;p&gt;The idea was simple: by breaking complexity into several dimensions and scoring each separately. I expected to create a more stable composite score. If one metric fluctuated slightly due to randomness, the others could help balance it out, leading to a more reliable overall result.&lt;/p&gt;

&lt;p&gt;Introducing multiple metrics also opened the door to a new approach: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Treating each metric as a probability between 0 and 1. This standard scale made it easier for the LLM to reason about each factor, as it aligned with common patterns found in prompts and training data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It also gave me more flexibility when interpreting the results. Instead of making a strict yes/no decision on whether a factor was present, I could adjust thresholds, playing around with sensitivity and accuracy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CodeComplexityConfidenceEvaluation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name of the function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;is_setup_of_declaration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The code is part of setup or declaration boilerplate, such as defining constants or configuring a framework.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;start_line_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of the first line of the function, considering existing formatting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;end_line_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of the last line of the function, considering existing formatting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;use_of_advanced_algorithms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of advanced algorithms requiring domain-specific knowledge. 0 means no such algorithms, 1 means heavily reliant on them.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;low_level_optimizations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Low-level optimizations that require deep knowledge of hardware or language internals.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complex_third_party_libraries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of complex third-party libraries (e.g., Rx.js, Pandas, TensorFlow).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;business_logic_domain_expertise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Business logic requiring domain-specific expertise.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;advanced_coding_techniques&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of advanced coding techniques (e.g., functional programming).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;excessive_mutable_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Excessive reliance on mutable state. 0 means purely immutable or minimal state, 1 means heavy reliance on mutable data.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;deeply_nested_control_structures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deeply nested control structures (more than 3 levels).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;long_classes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Long classes (over 200 lines). 0 means no long classes, 1 means code is dominated by extremely large classes.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;long_functions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Long functions (over 100 lines). 0 means short functions, 1 means extremely long, monolithic functions.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parallelism_and_concurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Usage of parallelism or concurrency patterns (threads, async, futures, etc.).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;recursion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Usage of recursive functions or algorithms.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;global_variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of global variables.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;magic_numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Magic numbers (unexplained constants) that reduce readability.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;long_lists_of_positional_parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Functions with a large number of positional parameters.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;advanced_language_features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of advanced language features (e.g., metaprogramming, reflection).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;inconsistent_indentation_or_formatting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Poorly formatted code, inconsistent indentation, or misaligned braces.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;long_monolithic_blocks_of_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Large uninterrupted blocks of code lacking clear separation.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;non_descriptive_variable_function_names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Non-descriptive or misleading names for variables, functions, or classes.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;excessive_branching&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Frequent or complicated branching (if/else, switch), making logic harder to follow.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;inconsistent_error_handling&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Multiple, inconsistent ways of handling errors throughout the code.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complex_boolean_logic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Multiple combined boolean expressions making the logic difficult to parse.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;code_duplication&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Repetitive code blocks or functions duplicated across the codebase.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;non_idiomatic_use_of_language_features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Using language features in a way that goes against common idioms or best practices.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this approach came with a trade-off. It was challenging to balance the level of detail in the description of each factor with the overall size of the prompt. The more detailed and explicit the prompt, the better the LLM could identify specific factors, but longer prompts also meant slower response times, higher costs, and a greater chance of hitting token limits.&lt;/p&gt;

&lt;p&gt;On the other hand, shorter prompts were faster and cheaper to run but often resulted in weaker detection accuracy, leading to higher error rates and less reliable evaluations.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 Attempt 4: More factors with Enums
&lt;/h2&gt;

&lt;p&gt;Doubling down on the idea of averaging out inconsistencies, I decided to increase the number of factors even further, while simplifying the prompt by representing each factor as an enum value.&lt;/p&gt;

&lt;p&gt;By scaling up the number of simpler, well-defined factors, I aimed to make the scoring system both more granular and consistent, without overwhelming the model with lengthy descriptions.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;use_advanced_coding_techniques&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of advanced coding techniques, such as functional programming, that are less commonly understood.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;use_advanced_algorithms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of advanced algorithms requiring specialized knowledge, making the code harder to understand.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;use_parallelism_concurrency_patterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of parallelism, concurrency, or recursion, which adds complexity due to the challenges of handling state across multiple threads or processes.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;use_advanced_language_features&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of advanced language features, such as reflection or metaprogramming, which can obscure code readability and require deep understanding.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complicated_arithmetic_expressions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Complex arithmetic expressions that involve multiple operations or formulas, making it harder to reason about.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complicated_boolean_expressions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Complex boolean logic, including multiple conditions that can be difficult to follow and debug.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complicated_string_manipulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Complex string manipulations that involve multiple functions or operations, reducing clarity.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complicated_bitwise_operations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of bitwise operations and manipulation, which are generally low-level and harder to understand.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;use_complex_third_party_libraries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of complex third-party libraries (e.g., Rx.js, Pandas, TensorFlow) that require specialized knowledge to understand and work with.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;business_domain_expertise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Code that requires specific knowledge in the business domain, such as finance or healthcare.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;technical_domain_expertise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Code that requires technical domain knowledge, such as signal processing or computer graphics.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;application_domain_expertise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Code that requires understanding of the business logic unique to the application.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;use_global_variables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of global variables or hidden mutable state, which makes the code harder to reason about and introduces potential side effects.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;non_standard_coding_conventions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of non-standard or inconsistent coding and naming conventions, which can confuse engineers unfamiliar with the code.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;excessive_mutable_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Excessive reliance on mutable state, making the code harder to predict and test.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;magic_numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of magic numbers (unexplained constants) that lack context, reducing clarity.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;long_lists_of_positional_parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Functions with long lists of positional parameters, which can lead to confusion and misuse.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;excessive_boilerplate_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Excessive boilerplate code, which can obscure the core functionality and make the code harder to maintain.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;inconsistent_indentation_or_formatting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Inconsistent indentation or formatting, reducing readability and maintainability.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;long_monolithic_blocks_of_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Long, monolithic blocks of code without clear separation of concerns, making it difficult to follow.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;non_descriptive_variable_function_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Non-descriptive or misleading names for variables or functions, reducing clarity and making it harder to understand the code.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;overly_complex_function_signatures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Overly complex function signatures, making it hard to understand the purpose and use of the function.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;deeply_nested_control_flow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deeply nested branching in control flow (e.g., if/else, switch), making it hard to follow the execution logic.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complicated_control_flow_branching&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Complicated branching in control flow, adding difficulty in understanding the code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s decision-making.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;deeply_nested_loops&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deeply nested loops (e.g., for, while), which can reduce code readability and increase cognitive load.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complicated_loop_structure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Complicated loop structures that involve multiple conditions, breaking out of loops, or complex logic.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;hidden_side_effects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hidden side effects that are not immediately obvious from the function signature, making debugging and reasoning more difficult.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;code_duplication&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Code duplication across functions or classes, which increases maintenance complexity.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;non_idiomatic_use_of_language_features&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Non-idiomatic use of language features, which may be unfamiliar or unintuitive for engineers working in the language.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complex_math_concepts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of advanced mathematical concepts or models, which require specialized knowledge to understand.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;functional_programming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of functional programming paradigms, which require a different way of thinking and may not be familiar to all engineers.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complex_inheritance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Complex inheritance hierarchies, which can be hard to trace and understand.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complex_polymorphism&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Complex use of polymorphism, which may introduce unexpected behavior and harder-to-understand relationships between classes.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complex_data_structures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of complex data structures (e.g., graphs, trees) that require specialized knowledge to work with.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;bitwise_operations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of bitwise operations, which are generally low-level and harder to understand.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;concurrency_mechanisms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of complex concurrency mechanisms, which add complexity in terms of state management and performance.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;complex_regular_expressions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of complex regular expressions, which are often hard to read and understand at a glance.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;reflection_and_metaprogramming&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of reflection, metaprogramming, or other runtime code manipulation that reduces readability and increases cognitive load.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;high_performance_computations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;High-performance computations or low-level system optimizations, requiring specialized knowledge and potentially obscuring clarity.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;low_level_networking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Low-level networking or socket programming, which requires specialized technical knowledge.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;use_of_category_theory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of category theory concepts, which are very abstract and require a deep understanding to work with.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;domain_specific_languages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use of domain-specific languages (DSLs), which introduce custom syntax or rules that may be unfamiliar.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make the scoring more meaningful, I also introduced a custom weight to each enum value. By asking the LLM to identify which factors were present in the code and then applying the corresponding weights, I could compute a weighted sum that reflected the impact of the estimated complexity. This gave me a more flexible way to evaluate code, where each factor contributed proportionally based on how much it affects readability, maintainability, or onboarding effort.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;code_complexity_factors_weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use_advanced_coding_techniques&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use_advanced_algorithms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complicated_control_structures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use_parallelism_concurrency_patterns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use_advanced_language_features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complicated_arithmetic_expressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complicated_boolean_expressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complicated_string_manipulation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complicated_bitwise_operations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use_complex_third_party_libraries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;business_domain_expertise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;technical_domain_expertise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;application_domain_expertise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use_global_variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;non_standard_coding_conventions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;excessive_mutable_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;magic_numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;long_lists_of_positional_parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;excessive_boilerplate_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inconsistent_indentation_or_formatting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;long_monolithic_blocks_of_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;non_descriptive_variable_function_names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;overly_complex_function_signatures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deeply_nested_control_flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complicated_control_flow_branching&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deeply_nested_loops&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complicated_loop_structure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hidden_side_effects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code_duplication&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;non_idiomatic_use_of_language_features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complex_math_concepts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;functional_programming&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complex_inheritance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complex_polymorphism&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complex_data_structures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bitwise_operations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;concurrency_mechanisms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complex_regular_expressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reflection_and_metaprogramming&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;high_performance_computations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;low_level_networking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;use_of_category_theory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CodeComplexityFactors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;domain_specific_languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My prompt was generating output in JSON format, one of the fields had to contain the array of enum values. During experimentation, I started noticing an increase in poorly formatted JSON outputs from the LLM. It turned out that LangChain was including the enum descriptions directly in the prompt and expecting output to contain array of string exactly matching my enum descriptions. LLM response was very long and verbose, that led to inconsistent representations and parsing errors. To fix this, I revised the enums to use concise, clear values that reduced ambiguity and minimized the chance of misinterpretation. This helped with formatting, but didn’t fully solve the problem.&lt;/p&gt;

&lt;p&gt;Despite these improvements, the approach still had reliability issues. The LLM would sometimes miss key factors or falsely detect ones that weren’t present. This was especially problematic for high-weight factors, since errors in those would heavily skew the final score.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚖️ Attempt 5: Grouping Factors into Key Categories
&lt;/h2&gt;

&lt;p&gt;After playing with the trade-offs of fine-grained metrics, I realized I needed a better balance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too many individual factors overwhelmed the LLM and made the scoring process fragile. &lt;/li&gt;
&lt;li&gt;A single metric was too simplistic and lacked the nuance needed for meaningful evaluation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But by spending time refining the individual factors, I started to see patterns, groups of related traits that could be consolidated into broader categories. This led me to define five key dimensions of complexity:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Readability Issues&lt;/strong&gt; – Problems related to naming, formatting, or clarity that reduce how easily code can be understood.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control Flow Complexity&lt;/strong&gt; – Use of deeply nested logic, recursion, or heavy branching that increases cognitive load.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Project-Specific Knowledge&lt;/strong&gt; – Dependencies on internal business logic, frameworks, or custom libraries that are hard to understand without context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Domain-Specific Knowledge&lt;/strong&gt; – Use of specialized concepts (e.g., from machine learning, graphics, physics, or signal processing) that require prior expertise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Advanced Coding Techniques&lt;/strong&gt; – Patterns like metaprogramming, functional programming or other techniques that are powerful but mostly used due to personal preference.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Grouping the factors this way allowed me to keep the prompt concise while still capturing the most important sources of complexity. It also made it easier to assign meaningful weights to each category based on how difficult they are to understand, refactor, or onboard new developers into.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FunctionComplexityEvaluation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name of the function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;is_setup_of_declaration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The code is part of setup or declaration boilerplate, such as defining constants or configuring a framework.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;start_line_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of the first line of the function, considering existing formatting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;end_line_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of the last line of the function, considering existing formatting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;readability_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate how readable the code is based on factors like naming conventions, formatting, and non-runtime characteristics.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;cognitive_complexity_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate the cognitive complexity of control structures and expressions. Higher scores result from deeply nested control flow, complex expressions, and multiple branching levels.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;project_specific_knowledge_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate how much project-specific knowledge is required, such as the use of third-party libraries or specific business rules.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;technical_domain_knowledge_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate the level of deep technical domain knowledge required, such as advanced algorithms, parallel programming, signal processing, or low-level optimizations.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;advanced_code_techniques_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate the use of advanced coding techniques (like functional programming paradigms) that are not essential for solving the task but reflect the developer’s preference.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By focusing on five broad categories, I could include clear definitions and concrete examples for each, which helped the model make more consistent and accurate evaluations. It also made the weighting process much simpler. Instead of juggling dozens of individual factors, I could assign meaningful weights to just five core categories, each representing a different dimension of complexity.&lt;/p&gt;

&lt;p&gt;After some refinement, I realized that adding more detailed grading guidelines for each category directly into the prompt would further improve consistency. Clear score ranges gave the LLM a more structured way to estimate maintainability and helped align its output with my expectations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FunctionComplexityEvaluation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name of the function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;is_setup_of_declaration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The code is part of setup or declaration boilerplate, such as defining constants or configuring a framework.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;start_line_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of the first line of the function, considering existing formatting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;end_line_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of the last line of the function, considering existing formatting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;readability_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate how readable the code is based on factors like naming conventions, formatting, and non-runtime characteristics.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        Score ranges:&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0 - 0.3: The code follows standard naming conventions, is well-formatted, and lacks clutter (e.g., no magic numbers or excessive boilerplate).&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.3 - 0.7: Minor readability issues, inconsistent formatting, occasional use of non-descriptive names, or slight violations of coding standards.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.7 - 1: Significant readability problems, non-standard conventions, poor naming, inconsistent formatting, or extensive use of boilerplate code.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;cognitive_complexity_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate the cognitive complexity of control structures and expressions.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        Score ranges:&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0 - 0.3: Simple control structures (minimal nesting, straightforward logic, few operators).&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.3 - 0.7: Moderate complexity, involving some nesting (2–3 levels), more complex boolean/arithmetic expressions, or multiple operators.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.7 - 1: Highly complex control structures, deeply nested (3+ levels), intricate logic with many operators, or multiple conditional/loop combinations.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;project_specific_knowledge_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate how much project-specific knowledge is required, such as the use of third-party libraries or specific business rules.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        Score ranges:&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0 - 0.3: Little to no project-specific knowledge required, uses common third-party libraries or standard business rules.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.3 - 0.7: Some project-specific knowledge is needed, involving custom libraries or moderately complex business rules.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.7 - 1: Extensive project-specific knowledge required, highly customized third-party libraries or intricate, specific business logic.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;technical_domain_knowledge_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate the level of deep technical domain knowledge required, such as advanced algorithms, parallel programming, signal processing, or low-level optimizations.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        Score ranges:&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0 - 0.3: Minimal technical domain knowledge required, standard algorithms and techniques used.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.3 - 0.7: Moderate technical domain knowledge, involving specialized algorithms, parallel programming, or some scientific/engineering calculations.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.7 - 1: High level of technical domain knowledge required, including advanced algorithms, low-level optimizations, or complex scientific/mathematical concepts.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;advanced_code_techniques_score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimate the use of advanced coding techniques (like functional programming paradigms) that are not essential for solving the task but reflect the developer’s preference.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        Score ranges:&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0 - 0.3: No or minimal use of advanced techniques, the code is straightforward and easy to follow.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.3 - 0.7: Some use of advanced techniques (e.g., functional programming, metaprogramming) that increase complexity but do not dominate the code.&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s"&gt;        0.7 - 1: Heavy use of advanced techniques that significantly add complexity without being essential for solving the problem (e.g., monads, currying, complex metaprogramming).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I assigned weights to each category based on how difficult it is to address that type of complexity in real-world scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Readability Issues&lt;/strong&gt; &lt;em&gt;(Weight: 1)&lt;/em&gt; – These are usually easy to fix. Renaming variables, cleaning up formatting, or adding comments, minimal effort or low risk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control Flow Complexity&lt;/strong&gt; &lt;em&gt;(Weight: 2)&lt;/em&gt; – Refactoring deeply nested logic or simplifying branching structures is harder and can introduce bugs if not done carefully.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Project-Specific Knowledge&lt;/strong&gt; &lt;em&gt;(Weight: 3)&lt;/em&gt; – This often requires onboarding or checking internal documentation. It makes harder to onboard new team members and it is hard for engineers to keep their knowledge up to date.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Domain-Specific Knowledge&lt;/strong&gt; &lt;em&gt;(Weight: 4)&lt;/em&gt; – Understanding concepts from fields like machine learning or graphics can take significant time and isn’t always easily accessible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Advanced Coding Techniques&lt;/strong&gt; &lt;em&gt;(Weight: 5)&lt;/em&gt; – Unnecessary complexity, often reflecting personal preferences rather than project needs, and understanding them may require deep technical knowledge and hands-on experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📏 Function length component
&lt;/h3&gt;

&lt;p&gt;In addition to the cognitive complexity estimated by the language model, I decided to also consider function length as part of the final score. Long functions often require developers to hold more context in their minds, which becomes especially difficult when the logic is hard.&lt;/p&gt;

&lt;p&gt;A short function that handles something complex can still be understandable. But even simple logic, when stretched over dozens of lines, becomes difficult to follow. That’s why keeping functions small is a well-known best practice, something I wanted the tool to encourage.&lt;/p&gt;

&lt;p&gt;To capture this, I introduced a function size factor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;desired_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;  &lt;span class="c1"&gt;# lines of code
&lt;/span&gt;&lt;span class="n"&gt;function_size_factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function_length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;desired_length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A 10-line function is treated as the baseline. Shorter functions are typically simpler and easier to reason about, while longer ones get penalized. The function size factor growth is limited by sq. root, to prevent excessively long functions from dominating entire score.&lt;/p&gt;

&lt;h3&gt;
  
  
  📈 Computing the Final Score
&lt;/h3&gt;

&lt;p&gt;To keep the final score more human friendly, I wanted to keep it in range from 1 to 5 like typical &lt;code&gt;star&lt;/code&gt; rating. I applied a hyperbolic tangent (tanh) function to the adjusted composite score:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MIN_VALUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;MAX_VALUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;VALUE_RANGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MAX_VALUE&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;MIN_VALUE&lt;/span&gt; &lt;span class="c1"&gt;# 4
&lt;/span&gt;&lt;span class="n"&gt;final_score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MIN_VALUE&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;VALUE_RANGE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;tanh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;composite_score&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;function_size_factor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hyperbolic tangent function brings several useful properties to the scoring formula:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Across zero it grows steadily, capturing the initial linear increase in perceived complexity.&lt;/li&gt;
&lt;li&gt;As the input gets larger, the output asymptotically approaches 1, ensuring the score stays bounded and doesn’t spike uncontrollably.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By applying this function, I ensured the final score stays within desired range, while also modeling the non-linear nature of how developers experience complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚢 Finalizing the Tool and Additional Features
&lt;/h2&gt;

&lt;p&gt;As the tool evolved, I added a few more features to improve its performance and usability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Progressive Evaluation&lt;/strong&gt; – To save time and compute, the tool caches previous results and skips files that haven’t changed since the last run. This makes it much faster to use in CI pipelines or large projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improvement Suggestions&lt;/strong&gt; – When a file exceeds the target complexity score, the tool generates helpful, actionable feedback on what could be improved, highlighting specific areas that contribute most to the score.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration Options&lt;/strong&gt; – The tool behaviour can be customized through a config file or CLI flags. This allows teams to adapt it to fit their needs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  🤩 Wrapping Up
&lt;/h1&gt;

&lt;p&gt;I hope this tool will be useful to other engineers and companies looking to bring code complexity evaluation into their CI workflows. While it’s still early, I see this as one of the first practical steps toward automating parts of the code review process using LLMs.&lt;/p&gt;

&lt;p&gt;With this post, I didn’t just want to showcase the tool, I wanted to share the journey of building it. From experimenting with prompts to balance reliability, performance, and cost. This project taught me a lot about working with LLMs in real-world scenarios.&lt;/p&gt;

&lt;p&gt;It also gave me a deeper understanding of what actually makes code complex, readable, or maintainable. Now I approach code quality with a more structured mindset, and I hope these insights help others do the same.&lt;/p&gt;




&lt;p&gt;🧪 Try it out: &lt;a href="https://pypi.org/project/codepass/" rel="noopener noreferrer"&gt;codepass on PyPI&lt;/a&gt;&lt;br&gt;
🚀 Code: &lt;a href="https://github.com/airtucha/codepass" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;&lt;br&gt;
💬 Got feedback or ideas? Drop a comment below!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>ci</category>
      <category>llm</category>
      <category>rag</category>
    </item>
    <item>
      <title>Simplifying Complex Code with Advanced Programming Approaches</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Wed, 16 Oct 2024 06:45:23 +0000</pubDate>
      <link>https://dev.to/airtucha/simplifying-complex-code-with-advanced-programming-approaches-3eg9</link>
      <guid>https://dev.to/airtucha/simplifying-complex-code-with-advanced-programming-approaches-3eg9</guid>
      <description>&lt;p&gt;Recent I've spent quite some time working on a &lt;a href="https://pypi.org/project/codepass/" rel="noopener noreferrer"&gt;CLI tool designed to evaluate code complexity&lt;/a&gt;. This project made me think about factors which impact the overall cognitive load required to understand and maintain a codebase. I've realized that complexity largely comes from two key areas: &lt;em&gt;how we organize our code&lt;/em&gt; and &lt;em&gt;the amount of knowledge required to understand it&lt;/em&gt;. This knowledge could involve domain expertise needed to grasp the science or business rules behind the code, or it could be the technical know-how related to the tools and techniques used in implementation.&lt;/p&gt;

&lt;p&gt;A lot is said on structuring code effectively, while I believe the "knowledge factor" is often overlooked. This is critical because, although messy code can be untangled with time and effort, no amount of refactoring will help if the underlying code is built on complex scientific concepts or advanced coding techniques that you do not understand. Mastering such knowledge can take years, making it far more challenging to deal with.&lt;/p&gt;

&lt;p&gt;Considering the knowledge requirements associated with a codebase, I divide them into two categories: natural complexity and artificial complexity introduced by engineering decisions. Natural complexity is unavoidable, such as domain-specific knowledge necessary to solve the problem. However, the more dangerous form of complexity arises from optional engineering choices—like unnecessary third-party libraries or hard-to-master coding techniques. These choices can impose a steep learning curve on the team, resulting in long-term costs and complexity that can drain businesses significantly.&lt;/p&gt;

&lt;h1&gt;
  
  
  Code Complexity Grades
&lt;/h1&gt;

&lt;p&gt;Let me explain my thoughts abstractly. Imagine we have a gradation of code based on complexity levels:&lt;/p&gt;

&lt;p&gt;1) Code that is instantly clear to anybody.&lt;br&gt;
2) Code that requires closer inspection but is still accessible to most developers.&lt;br&gt;
3) Code with complex logic or requiring specialized domain knowledge that is commonly available within the organization.&lt;br&gt;
4) Code with highly intricate logic or demanding advanced, specialized domain expertise.&lt;br&gt;
5) Code so complex that it is comprehensible only to a select few.&lt;/p&gt;

&lt;p&gt;A healthy software project should have the majority of the code at level 2, with a small portion at level 3, and only a minimal amount at level 4. This balance ensures that most of the codebase remains accessible and maintainable, while only a small part requires specialized knowledge or extra attention.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fru0f094cec2fgps4a5qr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fru0f094cec2fgps4a5qr.png" alt="Image description" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Advanced Coding Techniques
&lt;/h1&gt;

&lt;p&gt;In my view, one of the selling points for many advanced coding techniques like functional programming (FP) is that by applying the techniques developers intend to "simplify" the code.&lt;/p&gt;

&lt;p&gt;For example functional programming offers powerful abstractions that can encapsulate complex logic in a more declarative and concise manner. This can lead to cleaner, more maintainable code that reduces the cognitive load required to understand intricate systems. &lt;/p&gt;

&lt;p&gt;However, there is a caveat: according to the complexity scale, any FP code inherently falls into level 3-4. It requires specialized knowledge and skills, which are not as widespread as one might hope. Therefore, when building a team for a project that heavily relies on functional programming, it's not enough to simply find smart and capable engineers — they also need to be proficient in the advanced coding techniques that the project demands.&lt;/p&gt;

&lt;p&gt;Using advanced approaches, the project gets higher amount of level 3-4 code. Such a code requires more cognitive load for those, who is not too experienced with a selected paradigm, and not every programmer can understand it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9sh3eoqlb36tso0mm4ll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9sh3eoqlb36tso0mm4ll.png" alt="Image description" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Third-Party Libraries
&lt;/h1&gt;

&lt;p&gt;Third-party libraries are often introduced with the goal of speeding up development and reducing the need to reinvent the wheel. By leveraging pre-built solutions, developers can focus on higher-level tasks, potentially simplifying certain aspects of the project.&lt;/p&gt;

&lt;p&gt;However, these libraries come with their own complexity. Each one introduces new abstractions, APIs, and sometimes even entire ecosystems that developers need to understand and manage. According to the complexity scale, integrating third-party libraries inherently pushes parts of the codebase up by expanding amount of knowledge necessary to understand system. It requires understanding how these libraries work, their limitations, and how they interact with other components in the application.&lt;/p&gt;

&lt;p&gt;While third-party libraries are generally easier to pick up compared to advanced coding techniques. However, even with good documentation and community support, developers must invest time to learn the library’s nuances and ensure it fits the project's needs. Over-reliance on these libraries can still increase the cognitive load, especially for team members unfamiliar with them, adding complexity that comes not from the problem domain itself but from managing external tools.&lt;/p&gt;

&lt;p&gt;Usage of a library can be justified when it helps to reduce complexity, especially by covering areas that would otherwise require specialized domain knowledge. For example, Three.js is a popular JavaScript library that simplifies working with 3D graphics. Creating 3D scenes, animations, and effects from scratch would typically require deep knowledge of computer graphics, rendering pipelines, and low-level WebGL programming. However, Three.js abstracts much of this complexity, offering a more accessible API that lets developers create sophisticated 3D visualizations without needing to master computer graphics. This allows teams to focus on business logic and the creative aspects of the project rather than the technical challenges of rendering graphics.&lt;/p&gt;

&lt;h1&gt;
  
  
  Embracing Simplicity
&lt;/h1&gt;

&lt;p&gt;Over the years, I have come to appreciate the value of simplicity in software design. This doesn't mean avoiding advanced techniques altogether, but rather using them judiciously and ensuring that the overall system remains understandable and maintainable. &lt;/p&gt;

&lt;p&gt;I think the knowledge requirements we casually introduce by using unnecessary third-party libraries or advanced coding techniques is the worst, since nothing requires it to be there, it is not essential to solve the business problem. The balance lies in knowing when to apply these techniques and ensuring that the overall design remains accessible to the entire development team.&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>functionalreactiveprogramming</category>
      <category>cleancode</category>
      <category>programming</category>
    </item>
    <item>
      <title>Book: Interactive Data Visualization for the Web by Scott Murray</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Fri, 11 Oct 2024 04:53:33 +0000</pubDate>
      <link>https://dev.to/airtucha/book-interactive-data-visualization-for-the-web-by-scott-murray-1gge</link>
      <guid>https://dev.to/airtucha/book-interactive-data-visualization-for-the-web-by-scott-murray-1gge</guid>
      <description>&lt;p&gt;Written by the creator of D3.js, the most popular JavaScript library for custom data visualization, this book serves as a comprehensive tutorial for the tool. While centered on D3.js, the workflows presented are applicable beyond the library and even beyond JavaScript itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Beginners:
&lt;/h2&gt;

&lt;p&gt;An excellent introduction to 2D data visualization, it also introduces the concept of Data-Driven Design, which has applications outside the field of visualization.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Experienced Readers:
&lt;/h2&gt;

&lt;p&gt;Rather than focusing on specific techniques, this book emphasizes the process of transforming data into meaningful visuals, a skill valuable across many disciplines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.oreilly.com/library/view/interactive-data-visualization/9781449340223/" rel="noopener noreferrer"&gt;Interactive Data Visualization for the Web by Scott Murray&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>data</category>
      <category>webdev</category>
      <category>d3</category>
    </item>
    <item>
      <title>Book: A Philosophy of Software Design</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Sun, 29 Sep 2024 05:59:09 +0000</pubDate>
      <link>https://dev.to/airtucha/book-a-philosophy-of-software-design-2je1</link>
      <guid>https://dev.to/airtucha/book-a-philosophy-of-software-design-2je1</guid>
      <description>&lt;p&gt;This book offers insights and wisdom from a seasoned software engineer, with detailed breakdowns of software design problems and in-depth analyses. While some discussions dive too deeply into specific examples, occasionally straying into irrelevant details, the author’s perspective is often conservative, and at times, even radical.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Beginners:
&lt;/h2&gt;

&lt;p&gt;I wish this had been my first programming book. It provides a glimpse into the mindset of those who are likely to be your first managers and mentors. While the proposed solutions may not always be the best, they are practical and have guided generations of software engineers. More importantly, the book introduces readers to critical design challenges and familiarizes them with the broader discussions in the field.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Experienced Readers:
&lt;/h2&gt;

&lt;p&gt;The book excels in explaining viewpoints and reasoning behind software practices that you might have encountered but struggled to fully understand or agree with. By presenting problems and solutions from multiple perspectives, it helps deepen your understanding of your colleagues and fellow software engineers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/39996759-a-philosophy-of-software-design" rel="noopener noreferrer"&gt;A Philosophy of Software Design by John Ousterhout&lt;/a&gt;&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>softwaredesign</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Book: The C Programming Language</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Mon, 23 Sep 2024 19:04:24 +0000</pubDate>
      <link>https://dev.to/airtucha/book-the-c-programming-language-5383</link>
      <guid>https://dev.to/airtucha/book-the-c-programming-language-5383</guid>
      <description>&lt;p&gt;This book is often regarded as a classic, sometimes even called the "bible of programming." It provides an in-depth education in the C programming language. While it may not be the best resource for those focused on modern general-purpose programming due to C's lack of some widely used features, it compels programmers to engage with many often-overlooked details and limits the use of contemporary approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Beginners:
&lt;/h2&gt;

&lt;p&gt;An excellent resource for learning the fundamentals of low-level programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Experienced Readers:
&lt;/h2&gt;

&lt;p&gt;A great tutorial for mastering the C language when needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.goodreads.com/book/show/515601.The_C_Programming_Language" rel="noopener noreferrer"&gt;The C Programming Language by Brian Kernighan and Dennis Ritchie&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

</description>
      <category>c</category>
      <category>books</category>
      <category>programming</category>
    </item>
    <item>
      <title>Udemy: Learning Path: Haskell: Functional Programming and Haskell</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Sun, 08 Sep 2024 14:22:16 +0000</pubDate>
      <link>https://dev.to/airtucha/udemy-learning-path-haskell-functional-programming-and-haskell-2nco</link>
      <guid>https://dev.to/airtucha/udemy-learning-path-haskell-functional-programming-and-haskell-2nco</guid>
      <description>&lt;p&gt;Udemy: Learning Path: Haskell: Functional Programming and Haskell&lt;/p&gt;

&lt;p&gt;This learning path comprises three separate courses. The first two courses overlap significantly; the first introduces fundamental Haskell semantics, while the second covers more advanced language elements. The third course stands apart, focusing on sophisticated applications of Haskell tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Beginners:
&lt;/h2&gt;

&lt;p&gt;The first two courses provide a solid foundation in purely functional programming and Haskell basics, although the third part may be too advanced.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Experienced Readers:
&lt;/h2&gt;

&lt;p&gt;The courses offer clear explanations of Haskell-specific semantics, such as do-notation and Type Classes. The advanced examples in the last section may prove useful for specific applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.udemy.com/course/learning-path-haskell-functional-programming-and-haskell/?utm_source=adwords&amp;amp;utm_medium=udemyads&amp;amp;utm_campaign=Search_DSA_GammaCatchall_NonP_la.EN_cc.ROW-English&amp;amp;campaigntype=Search&amp;amp;portfolio=ROW-English&amp;amp;language=EN&amp;amp;product=Course&amp;amp;test=&amp;amp;audience=DSA&amp;amp;topic=&amp;amp;priority=Gamma&amp;amp;utm_content=deal4584&amp;amp;utm_term=_._ag_169801645584_._ad_700876640599_._kw__._de_c_._dm__._pl__._ti_dsa-1456167871416_._li_9042514_._pd__._&amp;amp;matchtype=&amp;amp;gad_source=1&amp;amp;gbraid=0AAAAADROdO16iQl56KQKG3r7EvrOEZfWP&amp;amp;gclid=CjwKCAjwxNW2BhAkEiwA24Cm9O8cY8HhwqvBspE79ItVW3-WpdyXudGeWUbudANmQ7kkawPfaCkrLBoCbZQQAvD_BwE&amp;amp;couponCode=2021PM20" rel="noopener noreferrer"&gt;Learning Path: Haskell: Functional Programming and Haskell&lt;/a&gt;&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>programming</category>
      <category>functional</category>
    </item>
    <item>
      <title>Book: Learning JavaScript Design Patterns</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Tue, 03 Sep 2024 18:18:17 +0000</pubDate>
      <link>https://dev.to/airtucha/book-learning-javascript-design-patterns-36p1</link>
      <guid>https://dev.to/airtucha/book-learning-javascript-design-patterns-36p1</guid>
      <description>&lt;p&gt;This book explores the implementation and use of common software design patterns in JavaScript. While some examples may be slightly outdated according to the latest best practices, they remain valuable for those maintaining legacy systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Beginners:
&lt;/h2&gt;

&lt;p&gt;It serves as an excellent introduction to software design patterns. However, the problems these patterns address may be less familiar to those with limited programming experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Experienced Readers:
&lt;/h2&gt;

&lt;p&gt;The specific applications of software design patterns can provide inspiration for creative solutions to future challenges.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.oreilly.com/library/view/learning-javascript-design/9781449334840/" rel="noopener noreferrer"&gt;Learning JavaScript Design Patterns: A JavaScript and jQuery Developer's Guide by Addy Osmani&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>designpatterns</category>
      <category>books</category>
    </item>
    <item>
      <title>Book: Think Complexity by Allen Downey</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Mon, 02 Sep 2024 15:11:38 +0000</pubDate>
      <link>https://dev.to/airtucha/book-think-complexity-by-allen-downey-2mch</link>
      <guid>https://dev.to/airtucha/book-think-complexity-by-allen-downey-2mch</guid>
      <description>&lt;p&gt;Think Complexity introduces readers to the field of Complexity Science, exploring its implications for programming. The book showcases unique algorithms typical of the discipline and delves into intriguing concepts like Cellular Automata and the Game of Life, using Python for demonstrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Beginners:
&lt;/h2&gt;

&lt;p&gt;This book provides excellent examples of rare algorithms, particularly those involving graph-based problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Experienced Readers:
&lt;/h2&gt;

&lt;p&gt;You'll find value in the case studies and the application of programming techniques within Complexity Science.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.oreilly.com/library/view/think-complexity-2nd/9781492040194/" rel="noopener noreferrer"&gt;Think Complexity&lt;/a&gt;&lt;/p&gt;

</description>
      <category>books</category>
      <category>complexity</category>
    </item>
    <item>
      <title>9 months of Machine Learning and beyond: Machine Learning A-Z</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Fri, 26 Jul 2024 06:56:41 +0000</pubDate>
      <link>https://dev.to/airtucha/9-months-of-machine-learning-and-beyond-machine-learning-a-z-3jfj</link>
      <guid>https://dev.to/airtucha/9-months-of-machine-learning-and-beyond-machine-learning-a-z-3jfj</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Before I even started properly studying machine learning last summer, I've already had several machine learning courses purchased on Udemy. The most basic among that courses was &lt;a href="https://www.udemy.com/course/machinelearning/" rel="noopener noreferrer"&gt;Machine Learning A-Z: AI, Python &amp;amp; R&lt;/a&gt;, so, it became my starting point. This course served as a perfect introduction to the field, covering a wide range of classical machine learning techniques and some deep learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Course Impression
&lt;/h2&gt;

&lt;p&gt;Typically, as programmers, we work with structured data. However, the world is inherently messy. Machine learning proves to be an invaluable tool for dealing with unstructured information. I was very impressed by the course because it introduced a whole new world of approaches that felt like gaining a superpower.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Course Content
&lt;/h2&gt;

&lt;p&gt;The course explains the machine learning process step by step. The initial, crucial stage of the process is data preprocessing, which happens even before any algorithms can be applied. &lt;/p&gt;

&lt;h3&gt;
  
  
  Preprocessing of data
&lt;/h3&gt;

&lt;p&gt;Very beginning of preprocessing is &lt;strong&gt;data splitting&lt;/strong&gt;. It is common to divide dataset into three parts: &lt;strong&gt;training&lt;/strong&gt;, &lt;strong&gt;validation&lt;/strong&gt;, and &lt;strong&gt;test&lt;/strong&gt; sets. &lt;strong&gt;A training set&lt;/strong&gt; is used for training of a model, &lt;strong&gt;a validation set&lt;/strong&gt; helps assessing overfitting during training, and &lt;strong&gt;a test set&lt;/strong&gt; is used to evaluate the model’s performance after training. &lt;/p&gt;

&lt;p&gt;Handling missing data is another critical aspect. Depending on the situation and the amount of data missing, there are two primary options: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Imputing missing values based on other data points&lt;/li&gt;
&lt;li&gt;Removing rows with missing data entirely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Moreover, often it is important to perform &lt;strong&gt;feature scaling&lt;/strong&gt;, because some machine learning algorithms are sensitive to the scale of the input data. For instance, algorithms that compute distances between data points, like K-Nearest Neighbors (K-NN), will be biased towards variables with a larger scale if the data is not adjusted to compensate this. Feature scaling helps to make sure that the range of independent variables equally contributes to the analysis. This can be done through methods like normalization or standardization. Normalization rescales features to a fixed range, usually from 0 to 1. Standardization adjusts all features to have 0 mean and standard deviation of 1.&lt;/p&gt;

&lt;p&gt;These preprocessing steps are necessary to create a robust machine learning models that perform well in real-world scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classic Machine Learning Models
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Regression
&lt;/h3&gt;

&lt;p&gt;Regression models are a type of statistical tool used for predicting a continuous outcome based on one or more input variables. They are fundamental for forecasting and determining the strength of relationships between variables. These models work by creating an equation that best fits the observed data. I already had some experiences with regression models especially with &lt;strong&gt;Linear Regression&lt;/strong&gt; from &lt;a href="https://dev.to/airtucha/9-months-of-machine-learning-and-beyond-before-ive-started-bk5"&gt;the stat courses I took years ago&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Polynomial Regression&lt;/strong&gt; extends linear regression by adding terms with powers greater than one. This allows the model to fit a wider range of data shapes, capturing more complex relationships between variables. However, higher-degree polynomials can lead to overfitting, where the model fits the training data too closely and performs poorly on unseen data. This occurs because the model learns noise from the training data, mistaking it for actual relationships.&lt;/p&gt;

&lt;p&gt;Next, the course introduces &lt;strong&gt;Support Vector Regression (SVR)&lt;/strong&gt;, a powerful model that can encapsulate non-linear relationships with a lower risk of overfitting and can model exponential relationships. The main goal of &lt;strong&gt;SVR&lt;/strong&gt; is to create a prediction line that fits most of the data points as closely as possible while also trying to keep the line as smooth and flat as possible. In other words, &lt;strong&gt;SVR&lt;/strong&gt; tries to strike a balance between closely following the training data and avoiding overly complex models that might not work well on new, unseen data. It does this by allowing for a small margin of error, within which deviations are acceptable. This makes &lt;strong&gt;SVR&lt;/strong&gt; a robust choice for predicting continuous values, especially when the data is complex or has a lot of variability.&lt;/p&gt;

&lt;p&gt;After that &lt;strong&gt;Decision Trees&lt;/strong&gt; and &lt;strong&gt;Random Forests&lt;/strong&gt; are introduced. Typically known for classification, these techniques are also applicable in regression settings. The course explains how these models can predict an output based on decision rules inferred from the data features. &lt;strong&gt;Decision Trees&lt;/strong&gt; and &lt;strong&gt;Random Forests&lt;/strong&gt; create models based on a series of binary decisions from the features within the dataset. This approach can lead to models that fit well on training data but fail to generalize to new data because the decision-making process is arbitrary and doesn’t necessarily capture underlying mathematical relationships between variables.&lt;/p&gt;

&lt;p&gt;On the other hand, methods like &lt;strong&gt;SVR&lt;/strong&gt; and &lt;strong&gt;Polynomial Regression&lt;/strong&gt; aim to identify the mathematical relationships inherent in the data. For example, &lt;strong&gt;SVR&lt;/strong&gt; tries to fit the best possible curve within a certain margin of error, and polynomial regression can model relationships that follow a polynomial equation. If the true relationship between the variables is mathematical, these methods are likely to perform better with less risk of overfitting. This ability to uncover and leverage mathematical relationships makes &lt;strong&gt;SVR&lt;/strong&gt;, &lt;strong&gt;Linear&lt;/strong&gt;, and &lt;strong&gt;Polynomial Regression&lt;/strong&gt; more robust for predicting outcomes where the underlying data relationships are strong and clear.&lt;/p&gt;

&lt;h4&gt;
  
  
  Model Selection in Regression
&lt;/h4&gt;

&lt;p&gt;The section on regression wraps up with strategies for choosing the best model. Experimentation with different approaches and evaluation of their performance on test data is still recommended, since an experiment is still the only way to select a truly optimal model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classification
&lt;/h3&gt;

&lt;p&gt;Classification involves predicting a categorical response based on input variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logistic Regression&lt;/strong&gt;, despite its name, is a basic classification technique, ideal for binary classification problems. It is used for prediction of outcomes that have two possible states e.g., yes/no, true/false. It works by modelling the probability of the default class, usually labeled &lt;code&gt;1&lt;/code&gt;, as a function of the input features. &lt;strong&gt;Logistic regression&lt;/strong&gt; applies the logistic function to the output of a linear equation, producing a probability score between 0 and 1. This model is robust, straightforward, and efficient for binary classification problems.&lt;/p&gt;

&lt;p&gt;The next model in the course is &lt;strong&gt;K-Nearest Neighbors (K-NN)&lt;/strong&gt;. It classifies a data point based on how its neighbors are classified, capable of handling multi-class problems and more complex decision boundaries.&lt;/p&gt;

&lt;p&gt;The course also covers &lt;strong&gt;Support Vector Machines (SVM)&lt;/strong&gt; for classification, explaining the use of different kernels to handle linear and non-linear classification. &lt;strong&gt;Support Vector Machine&lt;/strong&gt; constructs a hyperplane in a multidimensional space to separate different classes. &lt;strong&gt;SVM&lt;/strong&gt; performs well in high-dimensional spaces. It is versatile due to its ability to use different kernel functions to make the hyperplane more adaptable to the data. For example, linear kernels are great for linearly separable data, while radial basis function (RBF) kernels can map non-linear relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clustering
&lt;/h3&gt;

&lt;p&gt;Classification and clustering are both methods of organizing data but serve different purposes. Classification is a &lt;strong&gt;supervised learning&lt;/strong&gt; approach where the model is trained on labeled data. This means the model learns from examples that already have an assigned category or class. Its task is to predict the category for new data based on what it has learned. For example, a classification model might determine whether emails are spam or not spam based on training with a dataset of emails labeled accordingly.&lt;/p&gt;

&lt;p&gt;Clustering, on the other hand, is an &lt;strong&gt;unsupervised learning&lt;/strong&gt; technique that involves grouping a set of objects in such a way that objects in the same group are more similar to each other than to those in other groups. It’s used when we don’t have predefined labels for data. The model itself discovers the inherent groupings in the data. An example of clustering might be segmenting customers into groups based on purchasing behavior without prior knowledge of the different customer types.&lt;/p&gt;

&lt;p&gt;Both methods are fundamental in data analysis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classification uses labeled data for predictive modeling.&lt;/li&gt;
&lt;li&gt;Clustering helps to discover hidden patterns in data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Clustering Techniques
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;K-Means&lt;/strong&gt; is a popular clustering technique that partitions data into K distinct, non-overlapping clusters based on their features. The process involves randomly initializing K points as cluster centers and assigning each data point to the nearest cluster based on Euclidean distance. The cluster centers are then recalculated as the mean of the assigned points, and this process repeats until the centroids stabilize and no longer move significantly. This method is particularly effective for large datasets and is widely used due to its simplicity and efficiency. &lt;strong&gt;K-Means&lt;/strong&gt; works best with data where the clusters are spherical and evenly sized, making it less effective with complex cluster shapes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hierarchical Clustering&lt;/strong&gt;, unlike &lt;strong&gt;K-Means&lt;/strong&gt;, does not require the number of clusters to be specified in advance. It builds a hierarchy of clusters either by a divisive method or an agglomerative method. &lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;the agglomerative approach&lt;/strong&gt;, each data point starts as its own cluster, and pairs of clusters are merged as one moves up the hierarchy. The process continues until all points are merged into a single cluster at the top of the hierarchy. This method is beneficial for identifying the level of similarity between data points and is visually represented using a dendrogram, which can help determine the number of clusters by cutting the dendrogram at a suitable level. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The divisive method&lt;/strong&gt; of hierarchical clustering, also known as top-down clustering, starts with all observations in a single cluster and progressively splits the cluster into smaller ones. This approach begins at the top of the hierarchy and works its way down, making it conceptually straightforward: every split is designed to create the most distinct and coherent clusters possible at each level of division.&lt;/p&gt;

&lt;p&gt;In practice, &lt;strong&gt;the divisive method&lt;/strong&gt; involves examining the cluster at each step and choosing the best point to split it. This involves measuring the distance between observations within the cluster and identifying the largest distance as the point to divide. The process continues recursively, splitting each subsequent cluster until each observation is its own cluster or until a specified number of clusters is reached. It is generally more computationally intensive than the agglomerative approach, as it requires a global view of the data at each split, making it less commonly used in very large datasets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hierarchical clustering&lt;/strong&gt; is particularly useful for smaller datasets or when the relationships between data points need to be closely examined, such as in biological sciences or when clustering historical data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Learning Models
&lt;/h2&gt;

&lt;p&gt;Deep learning is a subset of machine learning that employs neural networks with many layers. It is a significantly different from classical machine learning techniques. While classical machine learning focuses on features that are often manually selected and engineered, deep learning aims to train neural networks to learn features. The models automate feature extraction by building complex patterns from simpler ones. This makes deep learning exceptionally powerful for tasks such as image and speech recognition, where the input data is highly dimensional and the relationships within the data are complex. However, it requires vast amounts of information to train deep learning models.&lt;/p&gt;

&lt;h3&gt;
  
  
  Artificial Neural Network
&lt;/h3&gt;

&lt;p&gt;A fundamental element of deep learning is the forward densely connected neural network, or &lt;strong&gt;Artificial Neural Network (ANN)&lt;/strong&gt;. In these networks, neurons are arranged in layers, with the first layer taking the input data and the last layer producing output. Each neuron in one layer connects to every neuron in the next layer, making the network "densely connected." These neurons have weights and biases that adjust as the network learns from data during the training process. The output of each neuron is calculated by a nonlinear activation function, which introduces the ability to capture nonlinear relationships in the data.&lt;/p&gt;

&lt;p&gt;Layers of neurons, in &lt;strong&gt;ANNs&lt;/strong&gt;, can be represented by vectors consisting of the weights and biases. Data is propagated forward through these layers using matrix multiplication. An output of each layer is calculated by multiplying the input data by the weight matrix and then adding a bias term. This output then passes through an activation function before it is sent to the next layer. &lt;/p&gt;

&lt;p&gt;The activation function is crucial because it introduces non-linearity into the model, allowing the network to learn and model complex, non-linear relationships in the data. Without non-linear activation functions, the network, regardless of its depth, would still behave just like a single-layer perceptron, which can only learn linear boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Convolutional Neural Network
&lt;/h3&gt;

&lt;p&gt;An alternative to basic &lt;strong&gt;ANNs&lt;/strong&gt; is &lt;strong&gt;the Convolutional Neural Network (CNN)&lt;/strong&gt;. Unlike densely connected networks where every input is connected to each neuron, &lt;strong&gt;CNNs&lt;/strong&gt; operate over volumes of pixels and use filters to create feature maps that summarize the presence of detected features in the input, such as edges in images. This makes &lt;strong&gt;CNNs&lt;/strong&gt; highly efficient for tasks that involve spatial hierarchies, as they reduce the number of parameters needed, reducing the computational burden.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Convolutional Neural Networks&lt;/strong&gt; are specialized kinds of neural networks for processing data that has a grid-like topology, such as images. &lt;strong&gt;CNNs&lt;/strong&gt; use filters that perform convolution operations as the filter slides over the input to create a feature map that summarizes the presence of detected features in the input. This makes them exceptionally efficient for image related tasks. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CNNs&lt;/strong&gt; leverage the mathematical operation of convolution, a fundamental technique in digital signal processing. In the context of DSP, convolution is used to alter a signal by a filter, extracting important features. Similarly, in &lt;strong&gt;CNNs&lt;/strong&gt;, convolution involves applying a filter over an image to produce a feature map. This process effectively allows the network to detect similarities or specific features in the image that correspond to the filter. For example, a filter might be learn to detect edges or specific shapes.&lt;/p&gt;

&lt;p&gt;As the input image is processed through successive convolutional layers, the &lt;strong&gt;CNN&lt;/strong&gt; uses multiple filters at each layer to search for increasingly complex patterns. The first layer may detect simple edges or textures, while deeper layers can recognize more complex features like parts of objects or entire objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gradient Descent and Training Neural Networks
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Gradient descent&lt;/strong&gt; is a fundamental optimization algorithm used in training neural networks and other machine learning models. It works by iteratively adjusting the model's parameters to minimize &lt;strong&gt;the loss function&lt;/strong&gt;, which measures how well the model's predictions match the actual data. In each step, the algorithm computes the gradient of &lt;strong&gt;the loss function&lt;/strong&gt; with respect to the model parameters, and moves the parameters in the direction that reduces the loss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backpropagation&lt;/strong&gt; is the technique used to compute these gradients efficiently in neural networks. It involves two phases: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A forward pass, where input data is passed through the network to generate predictions. &lt;/li&gt;
&lt;li&gt;A backward pass, where the gradient of &lt;strong&gt;the loss function&lt;/strong&gt; is computed based on the prediction. It is later propagated back through the network to update the weights. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This process leverages the chain rule of calculus to estimate gradients, ensuring that each weight is adjusted in proportion to its contribution to the overall error. Together, &lt;strong&gt;Gradient Descent&lt;/strong&gt; and &lt;strong&gt;Backpropagation&lt;/strong&gt; enable neural networks to learn from data by iteratively improving their accuracy.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Loss Functions
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Loss functions&lt;/strong&gt; play a critical role in guiding the training process. It is also known as a cost function or error function. It quantifies the difference between the predicted outputs of the network and the actual target values. This metric provides a concrete measure of how well the network is performing. The goal of training is to minimize this loss, thereby optimizing the model's parameters.&lt;/p&gt;

&lt;p&gt;Commonly used loss functions in &lt;strong&gt;ANNs&lt;/strong&gt; vary depending on the specific type of task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For regression tasks, where the goal is to predict continuous values, &lt;strong&gt;the Mean Squared Error (MSE)&lt;/strong&gt; loss is frequently used. &lt;strong&gt;MSE&lt;/strong&gt; calculates the average of the squares of the differences between the predicted and actual values, penalizing larger errors more severely. &lt;/li&gt;
&lt;li&gt;For classification tasks, where the output is a class label, &lt;strong&gt;Cross-Entropy Loss&lt;/strong&gt; is commonly employed. This loss function measures the dissimilarity between the true label distribution and the predictions provided by the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  The Vanishing Gradient Problem and ReLu
&lt;/h4&gt;

&lt;p&gt;One significant challenge when building deep neural networks is &lt;strong&gt;the vanishing gradient problem&lt;/strong&gt;. The gradients used in the training process can become too small, preventing weights from changing their values, which stops the network from sufficiently updating parameters. &lt;/p&gt;

&lt;p&gt;This issue is particularly prominent with sigmoid or tanh activation functions. To mitigate this, deep learning has adopted &lt;strong&gt;the Rectified Linear Unit (ReLu)&lt;/strong&gt; activation function. &lt;strong&gt;ReLu&lt;/strong&gt; is defined as &lt;code&gt;ReLU(x)=max(0,x)&lt;/code&gt;, where &lt;code&gt;x&lt;/code&gt; represents the input to a neuron. This function helps maintain a stronger gradient during training, allowing deeper networks to learn effectively without the gradients vanishing. This simplicity and efficiency in promoting nonlinearity without affecting the scale of the gradient make &lt;strong&gt;ReLu&lt;/strong&gt; a popular choice in deep learning architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specialized Machine Learning Techniques
&lt;/h2&gt;

&lt;p&gt;The course progressed into a variety of more specialized machine learning techniques, each tailored to specific applications and domains. &lt;/p&gt;

&lt;h3&gt;
  
  
  Natural Language Processing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Natural Language Processing (NLP)&lt;/strong&gt; involves the application of computational techniques to the analysis and synthesis of natural language and speech. One of the main challenges in using machine learning for &lt;strong&gt;NLP&lt;/strong&gt; is that text data is inherently unstructured and high-dimensional. Text must be converted into a numerical format that machine learning algorithms can process, a task complicated by the nuances of language such as syntax, semantics, and context. &lt;/p&gt;

&lt;h4&gt;
  
  
  The Bag of Words
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;The Bag of Words (BoW)&lt;/strong&gt; model addresses this by transforming text into fixed-length vectors by counting how frequently each word appears in a document, ignoring the order and context of words. This method simplifies text data, making it manageable for basic machine learning models and serving as a foundational technique for text classification tasks, such as spam detection or sentiment analysis. However, simplicity of &lt;strong&gt;the BoW&lt;/strong&gt; model, its disregard for word order and semantic context limit its effectiveness for more complex language tasks. &lt;/p&gt;

&lt;h3&gt;
  
  
  Reinforcement Learning with UCB and Thompson Sampling
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Reinforcement Learning (RL)&lt;/strong&gt; is a type of machine learning where an agent learns to make decisions by interacting with an environment. It differs from &lt;strong&gt;supervised learning&lt;/strong&gt;, since correct input/output pairs are never presented, nor sub-optimal actions explicitly corrected. This strategies evolves by balancing the exploration, trying new things, and exploitation, using known information, in decision-making processes.&lt;/p&gt;

&lt;p&gt;The agent takes actions based on a policy, receives feedback through rewards or punishments, and updates its policy to maximize long-term rewards. Two notable strategies in &lt;strong&gt;RL&lt;/strong&gt; that help manage the exploration-exploitation dilemma are the &lt;strong&gt;Upper Confidence Bound (UCB)&lt;/strong&gt; and &lt;strong&gt;Thompson Sampling&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UCB&lt;/strong&gt; is an algorithm that prioritizes exploration by selecting actions that have either high rewards or have not been tried often. The idea is to balance the known rewards with the potential of finding higher rewards in lesser-tried actions. &lt;strong&gt;UCB&lt;/strong&gt; does this by constructing confidence bounds around the estimates of action rewards and choosing the action with the highest upper confidence bound. This approach systematically reduces uncertainty and improves decision-making over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thompson Sampling&lt;/strong&gt; takes a Bayesian approach to the exploration-exploitation problem. It involves sampling from the posterior distributions of the rewards for each action and selecting the action with the highest sample. This method allows for a more probabilistic exploration based on the known performance of actions, dynamically balancing between exploring new actions and exploiting the known ones based on their reward probability distributions.&lt;/p&gt;

&lt;p&gt;Both &lt;strong&gt;UCB&lt;/strong&gt; and &lt;strong&gt;Thompson Sampling&lt;/strong&gt; are powerful techniques in situations where the learning environment is initially unknown to the agent, allowing for systematic exploration and optimized learning based on the feedback received from the environment. These methods are particularly useful in real-time decision-making scenarios like A/B testing or network routing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dimensionality Reduction Techniques
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;PCA&lt;/strong&gt; is a statistical technique used for dimensionality reduction while preserving as much variance as possible. It works by identifying so called principal components - the directions along which the variance of the data is maximized. It reduces the dimension of the data by transforming the original variables into a new set of orthogonal variables. Orthogonality allows this new variable to be as non-correlated as possible, and account for the maximum variance in the data. This is particularly useful in reducing the number of variables in data while maintaining the relationships that contribute most to its variance. By transforming the data into a new set of dimensions with reduced complexity, &lt;strong&gt;PCA&lt;/strong&gt; helps in visualizing high-dimensional data, speeding up learning algorithms, and removing noise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LDA&lt;/strong&gt;, on the other hand, is also a dimensionality reduction technique but focuses more on maximizing the separability among known categories. It tries to model the difference between the classes of data. &lt;strong&gt;LDA&lt;/strong&gt; achieves this by finding a linear combination of features that separates classes. The resulting combination can be used as a linear classifier or for dimensionality reduction before later classification.&lt;/p&gt;

&lt;p&gt;Both &lt;strong&gt;PCA&lt;/strong&gt; and &lt;strong&gt;LDA&lt;/strong&gt; serve slightly different purposes: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PCA&lt;/strong&gt; is unsupervised, focusing on variance in the data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LDA&lt;/strong&gt; is supervised, focusing on maximizing class separability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Modern Model Selection and Boosting Techniques
&lt;/h2&gt;

&lt;p&gt;The latter part of the course explores advanced model selection strategies and introduces &lt;strong&gt;boosting&lt;/strong&gt;. &lt;strong&gt;Boosting&lt;/strong&gt; works by combining multiple weak learners into a stronger model in a sequential manner. Each learner in the sequence focuses on the errors made by the previous one, gradually improving the model's accuracy. The learners are usually simple models like decision trees, and each one contributes incrementally to the final decision, making the ensemble stronger than any individual model alone.&lt;/p&gt;

&lt;h4&gt;
  
  
  Extreme Gradient Boosting
&lt;/h4&gt;

&lt;p&gt;One of the most popular implementations of this technique is &lt;strong&gt;Extreme Gradient Boosting (XGBoost)&lt;/strong&gt;, which stands out due to its efficiency and effectiveness across a wide range of predictive modeling tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The "Machine Learning A-Z: AI, Python &amp;amp; R" course is a great starting point for anyone interested in machine learning. It covers a lot of important topics and gives a broad overview, but it’s just the beginning. &lt;/p&gt;

&lt;p&gt;Finishing this course won’t make you an expert ready for a specialized machine learning job right away. Instead, think of it as a first step. It helps you understand the basics and shows you what parts of machine learning might be most interesting to you.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>deeplearning</category>
      <category>python</category>
      <category>ai</category>
    </item>
    <item>
      <title>9 months of Machine Learning and beyond: before I've started</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Mon, 06 May 2024 22:00:00 +0000</pubDate>
      <link>https://dev.to/airtucha/9-months-of-machine-learning-and-beyond-before-ive-started-bk5</link>
      <guid>https://dev.to/airtucha/9-months-of-machine-learning-and-beyond-before-ive-started-bk5</guid>
      <description>&lt;p&gt;For this post, I want to look back at my earlier attempts to learn machine learning and data science, and discuss my current learning strategy.&lt;/p&gt;

&lt;p&gt;After university, I worked as a graphics programmer, developing tools for data visualization. However, I was also curious about data analysis. I admired people who could tell stories with data and wanted to acquire that skill. I eventually decided to pursue the &lt;a href="https://www.coursera.org/specializations/statistics" rel="noopener noreferrer"&gt;Data Analysis with R Specialization on Coursera&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I considered many options to learn data analysis. Most courses on the topic focused on people without much computer science background, covering basics of Python and R, data visualization, RDBMS, and SQL databases, with a bit of data analysis using statistics at the end. Given my background, I didn't need to cover these basics, so I looked for a program focused on foundational knowledge, especially statistics.&lt;/p&gt;

&lt;p&gt;The Data Analysis Specialization fit my needs perfectly. In hindsight, my only regret is not choosing a course that covered a similar curriculum in Python, which I find to be a more versatile language. Originally, the specialization consisted of five courses but has since been shortened to three.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://www.coursera.org/specializations/statistics" rel="noopener noreferrer"&gt;Data Analysis with R Specialization on Coursera&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;The program included 4 theory oriented courses. They had theoretical videos, interviews with industry experts, quizzes, and peer-reviewed data analysis tasks. The tasks involved writing reports in R Markdown, similar to Jupyter Notebooks but for R, and submitting them for peer review. Reviewing other students' reports was a crucial part of the learning process, as it offered different perspectives on the same dataset and introduced useful R tricks.&lt;/p&gt;

&lt;p&gt;The specialization aslo concluded a practical course with a large data analysis project, similar to the peer-reviewed reports but on a larger scale. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.coursera.org/learn/probability-intro" rel="noopener noreferrer"&gt;Introduction to Probability and Data with R&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The first course goal was understanding the fundamentals of probability and data analysis. This course covered key concepts such as the difference between observational studies and experiments, which is crucial for designing studies and interpreting data accurately. It emphasized the importance of eliminating bias, an essential skill for anyone working with data, as bias can skew results and lead to incorrect conclusions.&lt;/p&gt;

&lt;p&gt;The course also provided an introduction to probability theory, helping students understand the likelihood of various events occurring. It explored different types of probability distributions, such as Normal and Binomial, which are fundamental to many statistical analyses and real-world phenomena. The course taught how to quantitatively describe a dataset using measures like mean, median, and standard deviation, essential for summarizing data. Additionally, it introduced the concept of robust statistics, which offer metrics that are more tolerant to outliers in the data, ensuring that analyses are not unduly influenced by anomalies.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.coursera.org/learn/inferential-statistics-intro" rel="noopener noreferrer"&gt;Inferential Statistics&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The second course taught how to make informed decisions based on data. This course introduced tools for estimating the probability of a given dataset occurring by chance, which is vital for making evidence-based decisions in various fields, from business to scientific research. The course covered hypothesis testing, a key technique for determining whether a result is statistically significant, and introduced the concepts of false positive and false negative errors. Understanding these errors is crucial, as they can affect decision-making. For example, in medical testing, a false negative could miss a diagnosis, while a false positive could lead to unnecessary treatment. This course highlighted the importance of balancing the risk of each error type based on the specific context of a problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.coursera.org/learn/linear-regression-model" rel="noopener noreferrer"&gt;Linear Regression and Modeling&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The third course delved into linear regression, one of the most fundamental and widely used statistical and machine learning models. The main goal of linear regression is to fit a linear function to a set of data points, establishing a relationship between a dependent variable and one or more independent variables. This method is used extensively to predict outcomes based on input variables and has applications across numerous industries, from predicting sales to understanding the relationship between factors. The course provided an in-depth introduction to linear regression, including techniques for managing outliers to improve model accuracy, methods for evaluating model performance, and strategies for selecting optimal parameters in multi-linear regression. This knowledge is invaluable for anyone looking to develop predictive models or understand the relationships between different variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.coursera.org/learn/bayesian" rel="noopener noreferrer"&gt;Bayesian Statistics&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The last theoretical course introduced a different approach to probability. It explained the difference between the Frequentist and Bayesian approaches, with the Bayesian interpretation offering a flexible framework for applying statistical methods in a wide range of applications. The Bayesian approach treats probability as a degree of belief rather than a fixed frequency, allowing for continuous updating of beliefs based on new evidence according to Bayes’ Rule. This flexibility makes Bayesian statistics useful in dynamic environments where conditions change, such as finance or real-time decision-making. The course demonstrated how this approach can lead to more nuanced and adaptable models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outcome of the study
&lt;/h2&gt;

&lt;p&gt;While the knowledge wasn't directly applicable to my day-to-day tasks, it enhanced my decision-making, helping me understand research papers and news. However, since it was not immediately useful for me at work I was demotivated from diving deeper into the topic, focusing instead on other skills like databases, cloud computing, algorithms, and web development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to ML
&lt;/h2&gt;

&lt;p&gt;As I mentioned in my previous post, I was impressed by ChatGPT and Midjourney, which reignited my interest in machine learning. I had basic ideas about artificial neural networks, but struggled to understand modern models. Having experience with Udemy and Coursera, I found Coursera too intense for my needs, as I wasn’t planning to switch to a machine learning job but simply wanted to understand the field. I didn’t want to spend time on quizzes and programming tasks typical of Coursera's computer science courses, and considered Coursera a bit pricey.&lt;/p&gt;

&lt;p&gt;In contrast, I already purchased several machine learning courses on Udemy. The platform also offers a wide variety of courses from different instructors. With my self-study experience, I've always been concerned with long-term retention of knowledge, particularly when it's not in active use. I find interval-based training helpful for retention.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Learning Approach
&lt;/h2&gt;

&lt;p&gt;In interval-based training, I buy several courses on the same topic by different instructors, mixing courses on different computer science areas to space out similar topics. This approach has two benefits: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, the initial exposure to a new topic serves as an introduction, forming a "skeleton" of knowledge. After a break, I revisit the topic through another course. Repetition over time enhances long-term retention, supported by research on memory mechanics. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secondly, different instructors provide different perspectives often from a different angle, enabling a more comprehensive understanding of a topic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Starting with the next post, I'll review the courses I've taken, beginning with foundational machine learning courses I completed early on.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>beginners</category>
      <category>ai</category>
    </item>
    <item>
      <title>9 months of Machine Learning and beyond</title>
      <dc:creator>Alexey Tukalo</dc:creator>
      <pubDate>Mon, 29 Apr 2024 18:56:32 +0000</pubDate>
      <link>https://dev.to/airtucha/9-months-of-machine-learning-and-beyond-3c48</link>
      <guid>https://dev.to/airtucha/9-months-of-machine-learning-and-beyond-3c48</guid>
      <description>&lt;p&gt;Hi, my name is Alex, and I'm a full-stack software engineer. Nine months ago, I decided to take a couple of machine learning courses to better understand the ongoing AI revolution, and I've become increasingly fascinated by this topic. &lt;/p&gt;

&lt;p&gt;I'm excited to share my journey into the world of machine learning with you. This isn't going to be a short story. I intend to write a series of posts starting with my background, explaining my learning strategy, and later reviewing the courses I've taken and will take. My reviews will briefly discuss the topics covered by the courses.&lt;/p&gt;

&lt;p&gt;Why am I doing this? First and foremost, I do it for myself. I hope this series will document and solidify my learning path in machine learning. It will help me to better understand and remember what I've learned. Additionally, I hope it can serve as a resource for others interested in making their first steps in machine learning and AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Early Years in Tech
&lt;/h3&gt;

&lt;p&gt;My university program focused mostly on C and programming micro-controllers. However, what truly captivated me were data visualization and computer graphics. Blending my childhood passion for visual art with computer science seemed like a natural progression.&lt;/p&gt;

&lt;p&gt;That kick-started my career in graphics programming, where I developed both 2D and 3D rendering algorithms and even wrote my Bachelor thesis on Volume Rendering. Despite enjoying this field, I noticed the limited market demand for graphics programmers, especially for those not versed in C++. My tools of choice were C# with DirectX and later JavaScript with WebGL, which somewhat limited my opportunities in the more traditional C++ dominated areas.&lt;/p&gt;

&lt;p&gt;Simultaneously, I developed a curiosity for Machine Learning and Data Science. However, observing the rapidly growing interest in this area, I decided to proceed cautiously, building my knowledge gradually while focusing on other professional avenues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Becoming a Full-Stack Engineer
&lt;/h3&gt;

&lt;p&gt;The more robust job market compared to the niche field of computer graphics, along with the valuable opportunity to learn how to build large systems from scratch, prompted my move from graphics programming to frontend and eventually full-stack web development. This shift steered my career towards developing complex, client-facing platforms. Additionally, this change seamlessly aligned with my lifelong interest in startups.&lt;/p&gt;

&lt;p&gt;In an effort to strengthen my computer science fundamentals, I enrolled in the &lt;a href="https://www.coursera.org/specializations/scala" rel="noopener noreferrer"&gt;Functional Programming in Scala Specialization&lt;/a&gt;. While this program was not directly related to data analysis, it provided insights into big data processing with Spark. Over time, however, as I moved away from programming in a functional style and as Scala was increasingly overshadowed by advancements in Java and Kotlin, I found fewer opportunities to apply this knowledge in production.&lt;/p&gt;

&lt;p&gt;Understanding the crucial role of statistics in Machine Learning, I also pursued a &lt;a href="https://www.coursera.org/specializations/statistics" rel="noopener noreferrer"&gt;Data Analysis with R Specialization&lt;/a&gt;. This program was practical in nature, focusing less on theoretical mathematical concepts and more on the hands-on application of statistical methods to analyze real-world datasets. The curriculum covered foundational statistical techniques progressing to more complex topics like inferential statistics, linear regression models, and an introduction to Bayesian statistics. This approach helped me grasp how to effectively use statistical tools to extract insights and make data-driven decisions.&lt;/p&gt;

&lt;p&gt;Although, as a full-stack web developer, I quickly realized that to truly thrive, I needed to deepen my understanding of the entire software engineering tech stack. This led me to delve into algorithms, infrastructure, cloud technologies, databases, as well as UX/UI design and software architecture. As a result, these areas became the primary focus of my self-development for many years.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Industrial Revolution
&lt;/h3&gt;

&lt;p&gt;I still have much to learn regarding general software engineering, especially in such wide areas as DevOps or database engineering, but recent developments in LLMs and diffusion models made me realize that I have to learn machine learning to understand what is going on in the world.&lt;/p&gt;

&lt;p&gt;While I may not fully transition into a machine learning career, the knowledge I gain could prove invaluable, especially in a startup environment where versatility is crucial. Additionally, our software systems often interact with a messy world of fuzzy and noisy data. Understanding how to effectively manage and utilize this data is essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Next?
&lt;/h3&gt;

&lt;p&gt;The next article will feature a detailed review of the &lt;a href="https://www.coursera.org/specializations/statistics" rel="noopener noreferrer"&gt;Data Analysis with R Specialization&lt;/a&gt;, marking my initial foray into the realm of data processing. I’ll also share insights into my learning approach. &lt;/p&gt;

&lt;p&gt;Subsequent posts will focus on reviews of additional courses I’ve taken or I will take, exploring how my understanding of machine learning continues to evolve with new information.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
