-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/ai rag tool #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis update introduces a specialized AI tool for Yu-Gi-Oh! Goat Format rulings, integrates dynamic model selection via an environment variable, and expands environment configuration accordingly. It adds new utility modules for AI context retrieval, introduces new UI components and refactors input/message handling for chat components, and updates global and theme CSS. Several type aliases are converted to interfaces. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ChatUI
participant API (route.ts)
participant AI Model
participant AI Tool (getRelevantRulings)
participant Pinecone (getRelevantContext)
User->>ChatUI: Enters ruling question
ChatUI->>API (route.ts): Sends POST with user message
API (route.ts)->>AI Model: Streams text with system prompt and tool definition
AI Model->>AI Tool (getRelevantRulings): Calls tool with question
AI Tool->>Pinecone (getRelevantContext): Retrieves relevant rulings
Pinecone-->>AI Tool: Returns ruling context
AI Tool-->>AI Model: Returns relevant rulings (title, url)
AI Model-->>API (route.ts): Generates answer with sources
API (route.ts)-->>ChatUI: Streams response
ChatUI-->>User: Displays AI-generated ruling with sources
Possibly related PRs
Note ⚡️ AI Code Reviews for VS Code, Cursor, WindsurfCodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback. Note ⚡️ Faster reviews with cachingCodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (11)
apps/web/components/navbar.tsx (1)
2-2: Improve accessibility with the new BotIconThe icon has been added without any accessibility text. Consider adding an aria-label to the BotIcon or wrapping it with a span that includes a visually hidden text to ensure screen readers can properly identify the brand.
- <BotIcon /> + <BotIcon aria-label="Yu-Gi-Oh! Ruling Bot" />Or alternatively:
- <BotIcon /> + <span className="flex items-center"> + <BotIcon /> + <span className="sr-only">Yu-Gi-Oh! Ruling Bot</span> + </span>Also applies to: 9-9
apps/web/lib/ai-tools.ts (1)
1-8: Clean implementation of the RAG functionality.This new module implements the Retrieval-Augmented Generation feature for fetching relevant Yu-Gi-Oh! rulings. The code is concise and follows the single responsibility principle.
However, consider adding error handling to manage potential failures when generating embeddings or querying the Pinecone database.
export async function getRelevantRulings(text: string): Promise<ContextType[]> { - const embeddings = await generateEmbedding(text); - const rulingsMetadata = await getRelevantContext(embeddings); - return rulingsMetadata; + try { + const embeddings = await generateEmbedding(text); + const rulingsMetadata = await getRelevantContext(embeddings); + return rulingsMetadata; + } catch (error) { + console.error("Error fetching relevant rulings:", error); + return []; + } }apps/web/components/footnote.tsx (1)
1-27: Well-structured informational component with proper accessibility attributes.The Footnote component is cleanly implemented with appropriate styling and semantic markup. The use of proper accessibility attributes (
target="_blank"withrel="noreferrer") for external links is excellent.Consider extracting the link URLs to constants at the top of the file for easier maintenance:
+const RAG_URL = "https://www.pinecone.io/learn/retrieval-augmented-generation/"; +const GOAT_FORMAT_URL = "https://www.goatformat.com/whatisgoat.html"; + const Footnote = () => { return ( <div className="text-muted-foreground text-xs mt-2"> This is an AI chatbot using{" "} <a className="underline text-primary" - href="https://www.pinecone.io/learn/retrieval-augmented-generation/" + href={RAG_URL} target="_blank" rel="noreferrer" > RAG </a> . It is trained on{" "} <a className="underline text-primary" - href="https://www.goatformat.com/whatisgoat.html" + href={GOAT_FORMAT_URL} target="_blank" rel="noreferrer" > GOAT Format Yu-Gi-Oh! </a>{" "} rulings only. </div> ); };apps/web/components/chat.tsx (1)
14-14: Consider documenting the maxSteps limitation.Setting maxSteps to 3 limits the number of sequential tool calls. This is a reasonable approach to prevent excessive API usage, but should be documented with a brief comment explaining the rationale.
- maxSteps: 3, + // Limit tool calls to 3 steps to control API usage and response time + maxSteps: 3,apps/web/app/globals.css (1)
44-50: Universal* { @apply border-border outline-ring/50; }may hurt perfApplying border & outline utilities to all elements inflates the final CSS and forces every node to paint an outline even when not needed. Consider scoping to interactive elements (
button,a,input, etc.) or using a class-based approach to avoid layout thrashing.apps/web/app/api/chat/route.ts (2)
17-35: Tool is “mandatory” but not enforcedThe system prompt states that
getInformationmust be called, yet nothing checks the model’s tool-invocation result. Consider post-processing the streamed answer to ensure at least one tool call occurred, otherwise fall back to"Sorry, I don't know."to prevent hallucinated answers.
40-47: Lost error contextThe catch block logs the error but returns a generic message. Including a sanitized error code (e.g.,
"vector-db-timeout") in the JSON helps client-side handling while avoiding sensitive details.- return new Response( - JSON.stringify({ error: "Failed to process chat request" }), + return new Response( + JSON.stringify({ error: "chat_api_failure" }),apps/web/components/start-messages.tsx (2)
19-27: Consider disabling UI when a response is being generated.You're correctly tracking the generation state with
isGeneratingResponse, but this state isn't used to disable the prompt cards. This could allow users to click multiple prompts while waiting for a response.Update the
onClickhandler in the Card components to prevent multiple clicks during response generation:<Card key={index} className="p-4 cursor-pointer hover:bg-muted/50 transition-colors" - onClick={() => handleSendMessage(question)} + onClick={() => !isGeneratingResponse && handleSendMessage(question)} + aria-disabled={isGeneratingResponse} + style={{ opacity: isGeneratingResponse ? 0.6 : 1 }} >
29-49: Consider extracting strings for localization.The welcome message and subtitle are hardcoded strings. For better internationalization support, consider extracting these to constants or using a localization library.
Also, add a visual indicator to make the cards more explicitly look clickable:
<Card key={index} className="p-4 cursor-pointer hover:bg-muted/50 transition-colors" + role="button" onClick={() => handleSendMessage(question)} > - <p className="text-foreground">{question}</p> + <p className="text-foreground flex items-center"> + <span>{question}</span> + <span className="ml-auto text-muted-foreground text-sm">↗</span> + </p> </Card>packages/ui/src/components/ui/card.tsx (1)
84-92: Consider adding size variants to the card system.The card system is well-structured but lacks size variants, which would increase flexibility for different use cases.
Consider implementing a size prop with predefined padding and spacing values:
type CardSize = 'sm' | 'md' | 'lg'; interface CardProps extends React.ComponentProps<"div"> { size?: CardSize; } function Card({ className, size = 'md', ...props }: CardProps) { return ( <div data-slot="card" className={cn( "bg-card text-card-foreground flex flex-col rounded-xl border shadow-sm", { 'gap-3 p-3': size === 'sm', 'gap-6 p-6': size === 'md', 'gap-8 p-8': size === 'lg', }, className )} {...props} /> ); }packages/pinecone/src/query.ts (1)
4-11: Consider more type-safety for the Metadata interface.While the index signature
[key: string]: anyprovides flexibility, it reduces type safety. If possible, consider using a more specific type or a separate interface for optional fields.export interface Metadata { card: string; ruling: string; title: string; url: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any - [key: string]: any; + // Consider using a more specific type if you know which additional fields might exist + // For example: + source?: string; + date?: string; + // Or create a separate interface for optional fields: + // optionalFields?: Record<string, string | number | boolean>; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/web/public/favicon.icois excluded by!**/*.ico
📒 Files selected for processing (22)
apps/web/app/api/chat/route.ts(3 hunks)apps/web/app/env.ts(2 hunks)apps/web/app/globals.css(1 hunks)apps/web/app/layout.tsx(1 hunks)apps/web/components/chat-input-area.tsx(1 hunks)apps/web/components/chat-input-controls.tsx(1 hunks)apps/web/components/chat-input.tsx(2 hunks)apps/web/components/chat-messages.tsx(2 hunks)apps/web/components/chat.tsx(1 hunks)apps/web/components/footnote.tsx(1 hunks)apps/web/components/navbar.tsx(1 hunks)apps/web/components/start-messages.tsx(1 hunks)apps/web/hooks/use-send-message.ts(1 hunks)apps/web/lib/ai-tools.ts(1 hunks)packages/pinecone/package.json(1 hunks)packages/pinecone/src/query.ts(1 hunks)packages/pinecone/src/types.ts(2 hunks)packages/seeder/src/types.ts(1 hunks)packages/tailwind-config/shared-styles.css(0 hunks)packages/ui/src/components/ui/card.tsx(1 hunks)packages/ui/src/styles.css(0 hunks)turbo.json(1 hunks)
💤 Files with no reviewable changes (2)
- packages/tailwind-config/shared-styles.css
- packages/ui/src/styles.css
🧰 Additional context used
🧬 Code Graph Analysis (3)
apps/web/components/chat-messages.tsx (1)
packages/ui/src/lib/utils.ts (1)
cn(4-6)
packages/pinecone/src/query.ts (1)
packages/pinecone/src/pinecone.ts (1)
getPineconeIndex(11-44)
packages/ui/src/components/ui/card.tsx (1)
packages/ui/src/lib/utils.ts (1)
cn(4-6)
🔇 Additional comments (28)
packages/seeder/src/types.ts (1)
1-8: LGTM! Good conversion from type alias to interfaceConverting the
CardRulingtype alias to an interface maintains the same structure while providing better consistency with other interface-based declarations in the codebase. This change supports the new RAG functionality and aligns with TypeScript best practices for object type definitions.apps/web/components/chat-input-controls.tsx (1)
22-26: LGTM! Improved input handling patternThe explicit passing of the input value to
handleSendMessageimproves code clarity and maintains consistency with the refactored pattern used throughout the chat components. This approach better supports controlled component management in React and creates a clearer data flow.Also applies to: 33-33
packages/pinecone/package.json (1)
24-28: LGTM! Good addition of the query module exportThe new export for the query module properly exposes the
getRelevantContextfunction and its related types, which are critical for the RAG functionality. The export follows the package's established pattern for module exports.packages/pinecone/src/types.ts (1)
1-10: Good migration from type alias to interface structure.Converting
PineconeVectorfrom a type alias to an interface is a positive change that follows TypeScript best practices. Interfaces are more extensible and better suited for object shapes that might be extended or implemented in the future.turbo.json (1)
8-13: Good formatting improvement and addition of OPENAI_MODEL environment variable.The change from a single-line array to a multi-line array improves readability. The addition of the
OPENAI_MODELenvironment variable is necessary to support the dynamic model selection feature mentioned in the PR description.apps/web/components/chat.tsx (3)
7-7: Good import addition for state management.Adding the useState import is necessary for the new internal input state management.
10-11: Good refactoring to manage input state internally.Moving the input state management into the Chat component provides better control over the input value across components.
22-23: Properly propagating state and helpers to child components.Good approach to pass the chatHelpers object and input state to child components. This ensures that all components have access to the necessary state and functions.
apps/web/components/chat-input-area.tsx (2)
31-31: Improved message handling with explicit input parameter.The change to explicitly pass the
inputvalue tohandleSendMessagealigns with the refactored hook implementation that now expects an input argument rather than accessing it from closure scope.
39-39: Enhanced textarea styling for better user experience.The styling changes from
py-3top-5provide more consistent padding on all sides and add explicit min/max height constraints, which prevents excessive expansion or contraction of the input area during typing.apps/web/app/env.ts (1)
11-11: Good addition of configurable OpenAI model with sensible default.Adding the
OPENAI_MODELenvironment variable with a default value enables dynamic model selection without hardcoding. This improves flexibility for switching between different OpenAI models as needs evolve.apps/web/components/chat-input.tsx (4)
6-6: Good component composition with Footnote.Replaced the
useStateimport with theFootnotecomponent import, which aligns with the refactoring to use controlled components and provides better separation of concerns.
10-11: Improved props interface for controlled component pattern.Added
inputandsetInputprops to enable the controlled component pattern, which lifts state management to the parent component. This is a cleaner architecture that makes state management more centralized and predictable.
14-14: Updated component signature to use controlled component pattern.The component now correctly destructures the
inputandsetInputprops from its props object, supporting the state lifting refactoring.
30-30: Enhanced UX with contextual footnote.Replaced static text with a dedicated
Footnotecomponent, which provides better contextual information about the AI chatbot's capabilities and limitations.apps/web/components/chat-messages.tsx (6)
5-6: Good component composition and type safety.Added imports for the
StartMessagescomponent andUseChatHelperstype, which improve component composition and type safety respectively.
9-10: Improved props interface for better component integration.Updated
ChatMessagesPropsto includechatHelpersandsetInput, which enables access to chat state and functionality from the parent component and supports the state lifting refactoring.
13-15: Refactored to access messages through chatHelpers.The component now correctly destructures
chatHelpersandsetInputfrom props, and accesses messages throughchatHelpers. This aligns with the architecture where chat state is managed through thechatHelpersobject.
30-30: Enhanced UX with starter messages for new conversations.Added the
StartMessagescomponent to provide a better onboarding experience when no messages exist, giving users suggested prompts or a welcome message.
38-38: Improved message alignment conditional.The conditional for message alignment now uses a more direct comparison with the message role, which improves code readability and makes the intent clearer.
46-46: Enhanced system message styling.Added the
system-message-stylesclass to system messages, which provides specific styling for system-generated messages to distinguish them visually from user messages.apps/web/app/layout.tsx (1)
10-13: 👍 Clearer branding & SEO – looks goodThe updated title and description more accurately reflect the product and improve search-engine relevance. No issues spotted.
apps/web/hooks/use-send-message.ts (2)
18-28: Redundant empty-input checks & missed whitespace-only scenario
!inputshort-circuits on an empty string, so the secondarytrim()+""guard is only useful for the whitespace-only case.
If that distinction is intentional, consider documenting it. Otherwise you can simplify and avoid two guards:- const handleSendMessage = (input?: string) => { + const handleSendMessage = (raw?: string) => { // Cancel message generation … - if (!input) { - return; - } - - const message = input.trim(); + const message = raw?.trim() ?? ""; + if (message === "") { + return; + }[ suggest_optional_refactor ]
36-45: Async error handling forappendis missing
append(...)returns a promise from@ai-sdk/react; unhandled rejections could surface in the console and break UX (e.g., network failure).
Wrap in try/catch or attach.catch()so the UI can surface an error toast and re-enable the input.- append({ + await append({ role: "user", content: message, createdAt: new Date(), }).catch(console.error);[ suggest_essential_refactor ]
apps/web/app/globals.css (1)
5-42: Verify plugin support for@theme inline
@theme inlineis not part of core Tailwind; ensure thetailwind-themeable(or equivalent) plugin is installed and configured, otherwise these rules will be stripped at build time.apps/web/app/api/chat/route.ts (1)
14-16: Graceful fallback whenOPENAI_MODELis undefinedIf the env var is missing,
openai.responses(undefined)may throw. Provide a default (e.g.,"gpt-4o-mini"), or return a 500 with a descriptive error.- model: openai.responses(env.OPENAI_MODEL), + model: openai.responses(env.OPENAI_MODEL ?? "gpt-4o-mini"),[ suggest_essential_refactor ]
apps/web/components/start-messages.tsx (1)
7-12: Good choice on prompt examples, consider future organization.The
STARTER_PROMPTSarray with Yu-Gi-Oh! Goat Format ruling questions is well-defined outside the component to avoid recreating it on each render. If this list grows significantly in the future, consider extracting it to a separate module for better maintainability.packages/ui/src/components/ui/card.tsx (1)
18-62: 🛠️ Refactor suggestionAdd keyboard focus states for better accessibility.
The card components handle layout well with a sophisticated grid approach, but lack focus states for keyboard navigation. This is important for accessibility.
For interactive card components, add focus states:
function Card({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="card" className={cn( - "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", + "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", className )} {...props} /> ); }Consider also providing a variant prop to create different card styles (primary, secondary, etc.).
Likely an incorrect or invalid review comment.
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores