Skip to content
This repository was archived by the owner on Jul 27, 2025. It is now read-only.

Comments

Personal Finance AI#1985

Closed
Shpigford wants to merge 25 commits intomainfrom
ai
Closed

Personal Finance AI#1985
Shpigford wants to merge 25 commits intomainfrom
ai

Conversation

@Shpigford
Copy link
Member

No description provided.

- Add chat and messages controllers
- Create chat and message views
- Implement chat-related routes
- Add message broadcasting and user interactions
- Update application layout to support chat sidebar
- Enhance user model with initials method
- Update sidebar layout with dynamic width and improved responsiveness
- Add new chat menu Stimulus controller for toggling between chat and chat list views
- Improve chat list display with recent chats and empty state
- Extract AI avatar to a partial for reusability
- Enhance message display and interaction styling
- Add more contextual buttons and interaction hints
- Refactor chat scroll functionality with Stimulus controller
- Optimize message scrolling in chat views
- Update message styling for better visual hierarchy
- Enhance chat container layout with flex and auto-scroll
- Simplify message rendering across different chat views
- Refactor AI avatar rendering across chat views
- Replace hardcoded avatar markup with a reusable partial
- Simplify avatar display in chats and messages views
- Add conditional width class for right sidebar panel
- Ensure consistent sidebar toggle behavior for both left and right panels
- Use specific width class for right panel (w-[375px])
- Extract message form to a reusable partial with dynamic context support
- Create flexible AI greeting partial for consistent welcome messages
- Simplify chat and sidebar views by leveraging new partials
- Add support for different form scenarios (chat, new chat, sidebar)
- Improve code modularity and reduce duplication
- Implement clear chat action in ChatsController
- Add clear chat route to support clearing messages
- Update AI sidebar with dropdown menu for chat actions
- Preserve system message when clearing chat
- Enhance chat interaction with new menu options
- Create initial frontmatter for structure.mdc file
- Include description and configuration options
- Prepare for potential dynamic documentation rendering
- Add rule for using `Current.family` instead of `current_family`
- Include new guidelines for testing, API routes, and solution approach
- Expand project-specific rules for more consistent development practices
- Add `ruby-openai` gem for AI integration
- Implement `to_ai_readable_hash` methods in BalanceSheet and IncomeStatement
- Include Promptable module in both models
- Add savings rate calculation method in IncomeStatement
- Prepare financial models for AI-powered insights and interactions
…apabilities

- Implement comprehensive AI financial query system with function-based interactions
- Add detailed debug logging for AI responses and function calls
- Extend BalanceSheet and IncomeStatement models with AI-friendly methods
- Create robust error handling and fallback mechanisms for AI queries
- Update chat and message views to support debug mode and enhanced rendering
- Add AI query routes and initial test coverage for financial assistant
- Remove inline AI chat from application layout
- Enhance AI sidebar with more semantic HTML structure
- Add descriptive comments to clarify different sections of chat view
- Improve flex layout and scrolling behavior in chat messages container
- Optimize message rendering with more explicit class names and structure
- Implement `markdown` helper method in ApplicationHelper using Redcarpet
- Update message view to render AI messages with Markdown formatting
- Add comprehensive Markdown rendering options (tables, code blocks, links)
- Enhance AI Financial Assistant prompt to encourage Markdown usage
- Remove commented Markdown CSS in Tailwind application stylesheet
@Shpigford Shpigford requested a review from zachgoll March 11, 2025 16:51
- Update @biomejs/biome to latest version with caret (^) notation
- Refactor AI query and chat controllers to use template literals
- Standardize npm scripts formatting in package.json
- Add family association to chat fixtures and tests
- Set consistent password digest for test users
- Enable AI for test users
- Add OpenAI access token for test environment
- Update chat and user model tests to include family context
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we drop this route / controller / view for the moment?

I ran into several issues here and I'm not sure how critical it is to have. Seems like we could simplify the overall feature by removing this and sticking with the sidebar chat only.

Copy link
Contributor

@zachgoll zachgoll Mar 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After spending some more time understanding the overall flow, I think this may be one of the bigger areas with an opportunity to simplify and make the overall view organization a bit clearer with Turbo frames.

Right now, we're putting a ton of view logic in the layout, which I think we should consolidate into the app/views/chats directory and leverage Turbo frames. My main concern is that we're loading the chat on every request, and for longer chats, this will incur a performance hit on every page.

I'm imagining the layout could just be consolidated in application.html.erb to:

<%= tag.div class: class_names("py-4 shrink-0 h-full overflow-y-auto transition-all duration-300", right_sidebar_open ? "w-[375px]" : "w-0"), data: { sidebar_target: "rightPanel" } do %>
  <%= render "chats/chat_nav" %>
  
  <%= turbo_frame_tag "chats", src: chats_controller, loading: "lazy" do %>
    <p>Loading chats...</p>
  <% end %>
<% end %>

Then all of the AI related stuff would go in views/chats, and index.html.erb effectively becomes what is the _ai_sidebar.html.erb right now. This will have several benefits:

  • Makes each chat request async
    • When chat is collapsed, request won't be made at all (that way users with this feature hidden won't incur any performance hit from it)
  • Consolidates the index view into one and aligns better with the domain by putting all the view logic in views/chats/
  • Keeps our layouts generic and easier to reason about

So in summary, here's the view organization that I'm imagining for the entire feature:

  • views/layouts/application.html.erb
    • Loads chats/chat_nav
    • Loads turbo_frame_tag "chats", src: chats_path
  • views/chats/
    • _chat_nav.html.erb - a shared partial, rendered at top of index and show for navigation of chats
    • _chat.html.erb - for list view
    • _chat_consent.html.erb
    • _chat_greeting.html.erb
    • _chat_form.html.erb - better aligns with an entire "chat"
    • index.html.erb
      • Renders _chat_consent
      • Renders a list of _chat.html.erb partials for user
    • show.html.erb
      • Renders _chat_greeting
      • Renders array of messages/_message.html.erb partials
        • Updated by streams
      • Renders _chat_form
  • views/messages
    • _message.html.erb

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and mocked this up to see how it would look. Here's the branch and demo:

main...zachgoll/ai-skeleton

  • AI sidebar uses data-turbo-permanent so it doesn't reload the frames on each navigation
  • We keep track of the "last viewed chat" for each user
    • Load last viewed chat by default
    • If user clicks "all chats", it sets the last viewed chat to nil and the next page load will show "all chats" again
    • Layout encapsulates the logic that determines whether to show the "current chat" or "all chats"
CleanShot.2025-03-12.at.12.37.45.mp4

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this over to tailwind/application.css and delete this file entirely? (after v4 upgrade I don't think we need this at all)

else
"#{format_date(period.start_date)} to #{format_date(period.end_date)}"
end
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using the chat, I ran into an application error pretty much any time I asked about IncomeStatement items that had a period:

[ActiveJob] [ProcessAiResponseJob] [2909c435-6d15-40fe-b895-1519239cfd38] Error generating AI response: undefined method 'previous_month' for class Period
16:28:49 web.1    | [ActiveJob] [ProcessAiResponseJob] [2909c435-6d15-40fe-b895-1519239cfd38] /Users/zachgoll/Documents/apps/maybe/app/models/ai/financial_assistant.rb:520:in 'Ai::FinancialAssistant#get_period_from_param'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this controller used at all? I think we can delete it?

Copy link
Contributor

@zachgoll zachgoll Mar 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After spending some more time understanding the overall flow, I think this may be one of the bigger areas with an opportunity to simplify and make the overall view organization a bit clearer with Turbo frames.

Right now, we're putting a ton of view logic in the layout, which I think we should consolidate into the app/views/chats directory and leverage Turbo frames. My main concern is that we're loading the chat on every request, and for longer chats, this will incur a performance hit on every page.

I'm imagining the layout could just be consolidated in application.html.erb to:

<%= tag.div class: class_names("py-4 shrink-0 h-full overflow-y-auto transition-all duration-300", right_sidebar_open ? "w-[375px]" : "w-0"), data: { sidebar_target: "rightPanel" } do %>
  <%= render "chats/chat_nav" %>
  
  <%= turbo_frame_tag "chats", src: chats_controller, loading: "lazy" do %>
    <p>Loading chats...</p>
  <% end %>
<% end %>

Then all of the AI related stuff would go in views/chats, and index.html.erb effectively becomes what is the _ai_sidebar.html.erb right now. This will have several benefits:

  • Makes each chat request async
    • When chat is collapsed, request won't be made at all (that way users with this feature hidden won't incur any performance hit from it)
  • Consolidates the index view into one and aligns better with the domain by putting all the view logic in views/chats/
  • Keeps our layouts generic and easier to reason about

So in summary, here's the view organization that I'm imagining for the entire feature:

  • views/layouts/application.html.erb
    • Loads chats/chat_nav
    • Loads turbo_frame_tag "chats", src: chats_path
  • views/chats/
    • _chat_nav.html.erb - a shared partial, rendered at top of index and show for navigation of chats
    • _chat.html.erb - for list view
    • _chat_consent.html.erb
    • _chat_greeting.html.erb
    • _chat_form.html.erb - better aligns with an entire "chat"
    • index.html.erb
      • Renders _chat_consent
      • Renders a list of _chat.html.erb partials for user
    • show.html.erb
      • Renders _chat_greeting
      • Renders array of messages/_message.html.erb partials
        • Updated by streams
      • Renders _chat_form
  • views/messages
    • _message.html.erb

@zachgoll
Copy link
Contributor

#2022 is a direct checkout of this branch with some additional documentation added, so closing this one out and will use #2022 for final merge.

@zachgoll zachgoll closed this Mar 24, 2025
@Shpigford Shpigford deleted the ai branch May 2, 2025 00:59
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants