A year ago, AI felt like a separate discipline — something you studied in papers and trained in notebooks, not something you casually shipped into a production app. That changed when I started building with generative AI APIs and realized how small the actual integration surface is.
Most of my early AI experience was academic — training models, reading research papers, implementing architectures from scratch. Then I started building full-stack applications with LLM APIs, and the mental model shifted entirely. You stop thinking about weights, gradients, and activation functions, and you start thinking about prompts, context windows, latency budgets, and output validation.
The chatbot in this portfolio is a simple example of that shift. It is not a fine-tuned model — it is a well-prompted API call with a context window that includes my portfolio data. The AI does not know me by training; it knows me because I told it about me. That distinction matters for how you architect these systems.
AI features behave like any other feature in a real application: they need error handling, fallbacks, rate limit awareness, and enough speed not to frustrate the user. The difference is that they are non-deterministic. The same input can produce meaningfully different outputs. You cannot unit test them the way you would a pure function, and you have to design around that uncertainty from the start.
In practice, this means validating outputs before displaying them, building graceful fallbacks for when the model returns something unexpected, and being honest with users about what they are interacting with.
The tools are good enough now that the integration cost is low and the value ceiling is genuinely high. I do not add AI to things for the sake of it. But when it solves a real problem faster or better than a deterministic approach — a smarter search, a more helpful assistant, a faster first draft of something — I use it. That is just good engineering judgment.