Skip to content

albertorsesc/ai-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AI News CLI

An interactive command-line application for fetching and interacting with news headlines, featuring AI-powered Q&A and image generation.

Alt text

Overview

This application provides a real-time, interactive terminal interface to fetch news headlines from a mock source. It allows users to ask questions about specific headlines, leveraging an LLM (like OpenAI's GPT models) to get answers. Additionally, it can generate and display images related to the news content using a local Stable Diffusion model.

Features

  • Interactive Dashboard: A live-updating terminal UI that displays news, status messages, and system resource usage.
  • Real-time Controls: Keyboard shortcuts for fetching news, navigating menus, and scrolling through headlines without interrupting the application flow.
  • AI-Powered Q&A: Ask questions about any news headline and get answers from an integrated LLM.
  • Local Image Generation: Automatically generate and save images based on news headlines using Stable Diffusion.
  • Configuration Validation: A built-in command to check your setup and ensure all necessary configurations (like API keys) are in place.

Getting Started

Follow these steps to get the application up and running.

Installation

  1. Clone the repository:

    git clone https://github.com/albertorsesc/ai-cli.git
    cd ai-cli
  2. Create a virtual environment: I used uv but you can use venv as well.

    uv venv .venv --python=3.12
    source .venv/bin/activate
  3. Install dependencies:

    uv pip install .

    This command reads the pyproject.toml file, installs all required dependencies, and makes the ai-cli command available in your environment.

Configuration

The application uses a .env file in the project root to manage configuration.

  1. Create the .env file:

    cp .env.example .env
  2. Add your configuration: You need to provide an OpenAI API key for the Q&A feature to work.

    # Required for LLM Q&A feature
    OPENAI_API_KEY="sk-..."
    
    # --- Optional Settings ---
    
    # Specify the OpenAI model to use
    # Options: "gpt-3.5-turbo", "gpt-4o"
    # OPENAI_MODEL="gpt-3.5-turbo"

How to Use

Available Commands

The application provides a few commands to get started.

  • ai-cli news: Starts the main interactive news fetching dashboard.
  • ai-cli config: Displays and validates your current configuration.

Interactive Controls

Once you run ai-cli news, you can use the following keys to interact with the dashboard:

Key Action
F Fetch a new batch of news headlines.
SPACEBAR Toggle the actions menu on and off.
/ Scroll up or down through the list of news.
1 (in menu) Enter "Question Mode" to ask about a headline.
2 (in menu) Exit the application.
0 (in menu) Close the menu.
ESC Exit "Question Mode" or cancel an action.
CTRL+C or q Stop the application at any time.

Asking a Question

  1. Press SPACEBAR to open the menu.
  2. Press 1 to enter "Question Mode".
  3. Select a headline by pressing its corresponding number (1-9).
  4. Type your question and press Enter.
  5. The answer from the LLM will be displayed, and an image generation process will be kicked off in the background.

How It Works

The application is built around a central NewsController that manages the state of the CLI.

  • UI: The user interface is a rich.Layout that is updated in a loop to create a live dashboard. Keyboard inputs are handled in a separate thread to ensure the UI remains responsive.
  • News Source: News is fetched from MockMCPNewsServer, which simulates a real news feed. I started the task from the most practical implementation first (which was resolving the multiple processes I needed to have working) and then I was going to move to the MCP integration at the end, since it's not the complex part. Got stuck in some thread bugs which took away time to finish the MCP integration.
  • AI/LLM: When a user asks a question, the NewsController calls an LLMInterface (currently implemented for OpenAI) to get an answer based on the headline's context.
  • Image Generation: Asking a question also triggers a call to an ImageGeneratorInterface, which uses a local Stable Diffusion model (runwayml/stable-diffusion-v1-5) to create an image based on the headline. The model is downloaded and cached locally on its first use.
  • Configuration: All settings are managed by the ConfigManager which loads variables from the .env.

Alt text

Developer Notes

src/ai_cli/core/config.py

This file contains a few classes for configuration management.

The configuration logic should ideally live in its own directory probably inside core as well, and each class should be its own file.

Lack of Git branches

Usually in a project branches are used, in this case I didn't use this flow because I would know before hand what changes I'm going to be making.

Branches are a must in any project that is intended to be deployed.

Project structure

There are definitely a lot of things that can be improved in the project, specifically the news_controller.py which contains more methods that i would like. The reason I didn't refactored it is because I was caught up in the features of the application, and because the main objetive is to have a working application. Refactoring is an ongoing process.

Code Comments

Comments around the application might not reflect the actual conventions to follow on a production application. I'm explaining the reasoning behind certain pieces of code that might be too much information for a single comment, but it is necessary to understand how a came up to "that" conclusion.

In a real project we might leave those comments or reasoning to the commit description or in an ADR (Architectural Decision Record).

Story

I built this application 3 times. The first 3 times I was thinking in how easy it would be to make the integration of LLM for Q&A, Image generation with StableDiffusion, and the MCP integration which are a breeze. The main cause that brought me to redo this app many times is because of the CLI handling of multiple processes, that is why in the first commits you see unrelated code "Counter".

That implementation was done to first figure out how different processes will interact with the CLI, how to handle actions without interruption while processes are running, and other foundational aspects of this app.

I had to dive deep (again) into threads, processes, and other topics I had a while since I implement. Using Async wasn't the actual issue, the problem was processes fighting for control of the CLI UI.

I first tried with asyncio which it worked but there were several race conditions to fix and plenty of work arounds for this behavior. Also many of the actions performed by the application are blocking processes which using asyncio wouldn't completely solved.

This application uses threads and it spawns a process for each action such as the live dashboard and the handling of options, image generation in background, and so on.

By the time I started to figure out several solutions, the current project was so full of experimentation that building a new and clean project was the best course of action.

I wanted to deliver the best experience I could in the amount of time given. I failed to deliver on time, but I'm proud of the usability of the application and the look and feel.

The project structure would be refactored if this were an app intended for production of course, as well as many more guardrails. There are too many methods in the news_controller that I would break down into more digestable code.

And even though I did not deliver on time, it was a great experience, no because of AI-related implementation but because of being able to refresh knowledge I had some time without dealing with, as well as new.

More than AI-related challenge, it was mostly about software architecture, pragmatic approaches and inverse thinking.

I was first focus on building the features, until I realized the main problem is how to put everything together.

Anyways, I appreciate your time looking at this project if you are, and for the opportunity in participating in the process.

Note: The images show a lot of resources being used, in the image case 21.7GB of RAM which is a lot. I implemented a few caching mechanisms, device handling for image generation (cuda vs mps vs cpu), and I'm pretty sure more things could have been done better. For time constraints I made sure the device handling was sufficient for image processing since the image model is quite heavy to manage in terms of resources. I used a MacbookPro M4 Pro with 48GB of RAM.

About

An interactive command-line application for fetching and interacting with news headlines, featuring AI-powered Q&A and image generation.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages