Skip to content
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

cache ask results in db #337

Merged
merged 1 commit into from
Jan 11, 2025
Merged

cache ask results in db #337

merged 1 commit into from
Jan 11, 2025

Conversation

Southclaws
Copy link
Owner

  • key based on question, slugified
  • future work: vector lookup with tight threshold

Copy link

vercel bot commented Dec 30, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
storyden ⬜️ Ignored (Inspect) Visit Preview Jan 11, 2025 4:41pm
storyden-homepage ⬜️ Ignored (Inspect) Visit Preview Jan 11, 2025 4:41pm

Copy link

coderabbitai bot commented Dec 30, 2024

📝 Walkthrough

Walkthrough

The pull request introduces a comprehensive implementation of a new Question entity across the application. This addition enables storing and managing user-generated questions with associated metadata, including a relationship to user accounts. The changes span multiple packages, adding database schema, ORM capabilities, repository methods, and integration with existing services like the semantic indexing system. The implementation provides a robust framework for tracking, storing, and retrieving questions within the application.

Changes

File Change Summary
app/resources/datagraph/content.go Added NewRichTextFromMarkdown function to convert Markdown to rich text content
app/resources/datagraph/content_test.go Added test for Markdown to rich text conversion
app/resources/question/question.go Introduced Question struct and Map function for converting database entities
app/resources/question/repo.go Created repository for managing question entities with methods for storing, retrieving, and querying questions
app/services/semdex/asker/asker.go Enhanced asker service with caching and result management for questions
internal/ent/schema/question.go Defined database schema for the Question entity
Multiple internal/ent/* files Generated ORM-related files for Question entity management

Sequence Diagram

sequenceDiagram
    participant User
    participant Asker
    participant QuestionRepo
    participant Database

    User->>Asker: Ask a question
    Asker->>QuestionRepo: Check for cached result
    alt Cached result exists
        QuestionRepo-->>Asker: Return cached result
    else No cached result
        Asker->>Asker: Generate live prompt
        Asker->>QuestionRepo: Store new question
        QuestionRepo->>Database: Save question
        Asker-->>User: Stream response
    end
Loading

Possibly related PRs

  • add perplexity prompter #327: The changes in this PR involve the addition of a new function newPerplexity and modifications to the PromptStream method, which may relate to the handling of content, similar to how NewRichTextFromMarkdown processes Markdown into a Content object.

Poem

🐰 A Rabbit's Ode to Questions

In databases deep and queries bright,
A new entity hops into sight
Questions bloom like carrots in spring
With metadata and stories they'll bring
Knowledge grows, one query at a time! 🥕

Finishing Touches

  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (19)
app/services/semdex/asker/asker.go (3)

27-42: Initialize Asker fields with parameter validation
It's good to see the Asker struct being constructed with all relevant dependencies. However, consider validating that questions and logger are non-nil to avoid potential nil-pointer dereferences in subsequent methods.


79-101: Prevent potential race condition in cachedResult
Because this function streams chunks with a sleep, if the same question is processed simultaneously in different goroutines, concurrency issues could arise if q.Result.HTMLTree() is updated or replaced. Ensure the underlying data is immutable or guarded with locks if shared by multiple goroutines.


179-192: Validate maximum length constraints before caching
cacheResult stores the entire result in the database. If the result is excessively large, it could cause performance bottlenecks or exceed DB column size limits, depending on the schema. Adding an upper limit check, perhaps configured in cfg, can help maintain reliability.

internal/ent/question_create.go (4)

74-79: Metadata type consistency
The SetMetadata method relies on map[string]interface{}. Ensure that callers maintain consistent typing within this map, or consider a typed struct if usage patterns are known. This helps avoid runtime errors when encoding/decoding the JSON field.


156-182: Field validation in check()
The validations for required fields (slug, query, result, etc.) are clear. However, consider adding context about what caused the failure in error messages, e.g., including the faulty value or more details on constraints. This can ease debugging in large systems.


190-194: Handle MySQL constraint errors with more detail
When sqlgraph.CreateNode fails due to constraint violations, you wrap it in ConstraintError. Providing more detail (e.g., which field caused the violation) could make troubleshooting easier.


581-643: Bulk creation approach
The bulk creation logic carefully sets defaults for each builder. If partial failures occur within the batch, the entire batch might fail. Consider whether a partial success strategy is needed or if an all-or-nothing design is acceptable.

app/resources/question/question.go (1)

34-41: Potential Null Reference in in.Result

While this code checks for errors during the conversion, consider verifying that in.Result is never empty or null. This could avoid potential edge cases for partially saved data.

app/resources/question/repo.go (1)

57-71: Fetching by ID with Author and Role Relationship

This ensures you return a fully hydrated Question object. Any usage of partial or subset queries could speed up performance if the entire dataset isn’t always needed, but that’s optional.

internal/ent/question.go (2)

129-136: Consider advanced error logging for JSON unmarshalling.
When decoding Metadata in lines 129–136, any JSON unmarshal error is reported. For better debugging, you might consider including more context (like which record ID was being processed) so troubleshooting becomes easier.


178-207: Potential performance enhancement in building string representations.
When creating large strings in performance-critical scenarios, consider using a pre-allocated buffer or advanced string concatenation methods if performance becomes a bottleneck. Currently, the builder usage is fine for most cases.

internal/ent/question_update.go (3)

48-52: Be aware of potential null impact on indexing logic.

Clearing the "indexed_at" field removes existing indexing timestamps from the record. If other systems rely on a non-null timestamp, this may cause confusion. Ensure downstream consumers handle null indexed_at properly.


218-230: Clarify author edge clearance behavior.

Clearing the required unique edge "author" raises an error if it’s immediately re-set in the same mutation. If the design intent is to optionally remove the author link, validate both the business logic and user flows to avoid accidental “author” loss.


249-255: Enhance constraint error messaging.

When a constraint error occurs, consider appending more context (like the specific field or edge) to facilitate faster debugging, rather than returning only the generic “constraint failed” message.

internal/ent/question/where.go (1)

169-172: Use caution with nil checks on "indexed_at".

While IndexedAtIsNil() is useful for discovering unindexed questions, confirm that the caching mechanism correctly interprets unindexed questions and reindexes them when appropriate.

internal/ent/account.go (2)

70-71: Consider lazy loading or pagination for Questions.

If the number of linked questions grows significantly, returning them all at once could impact performance. Evaluate if lazy loading or pagination might be beneficial.


96-96: Incrementing loadedTypes size.

Remember to update any logic that relies on loadedTypes array indexing if additional edges are added in the future. Off-by-one errors are easy to miss in array expansions.

internal/ent/question_query.go (1)

410-419: Consider Bulk Loading Optimizations

The loadAuthor method individually aggregates questions by account_id. If large volumes of data are expected, ensure that the current approach scales and consider potential optimizations (e.g., batching or more specialized queries) if performance becomes an issue.

internal/ent/account/where.go (1)

794-805: Conditional Filtering with Predicates

HasQuestionsWith allows additional conditions on the joined table, enabling richer queries. Useful for scoping queries by question properties.

Consider adding unit tests or integration tests that illustrate advanced usage combining multiple predicate.Question conditions.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d5faf0 and 1b4e04b.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (32)
  • app/resources/datagraph/content.go (2 hunks)
  • app/resources/datagraph/content_test.go (1 hunks)
  • app/resources/question/question.go (1 hunks)
  • app/resources/question/repo.go (1 hunks)
  • app/resources/resources.go (2 hunks)
  • app/services/semdex/asker/asker.go (3 hunks)
  • app/services/semdex/semdex.go (1 hunks)
  • app/transports/http/bindings/datagraph.go (2 hunks)
  • internal/ent/account.go (14 hunks)
  • internal/ent/account/account.go (4 hunks)
  • internal/ent/account/where.go (1 hunks)
  • internal/ent/account_create.go (3 hunks)
  • internal/ent/account_query.go (9 hunks)
  • internal/ent/account_update.go (7 hunks)
  • internal/ent/client.go (11 hunks)
  • internal/ent/ent.go (2 hunks)
  • internal/ent/er.html (2 hunks)
  • internal/ent/hook/hook.go (1 hunks)
  • internal/ent/migrate/schema.go (3 hunks)
  • internal/ent/mutation.go (15 hunks)
  • internal/ent/predicate/predicate.go (1 hunks)
  • internal/ent/question.go (1 hunks)
  • internal/ent/question/question.go (1 hunks)
  • internal/ent/question/where.go (1 hunks)
  • internal/ent/question_create.go (1 hunks)
  • internal/ent/question_delete.go (1 hunks)
  • internal/ent/question_query.go (1 hunks)
  • internal/ent/question_update.go (1 hunks)
  • internal/ent/runtime.go (2 hunks)
  • internal/ent/schema/account.go (1 hunks)
  • internal/ent/schema/question.go (1 hunks)
  • internal/ent/tx.go (2 hunks)
🔇 Additional comments (121)
app/services/semdex/asker/asker.go (2)

70-77: Verify presence of questions repository
When err == nil, the flow assumes cached is not nil, but if questions or the cached entity unexpectedly is nil, it could lead to a panic later. Consider adding a quick nil check on cached.


103-151: 🛠️ Refactor suggestion

Clean resource usage on stream termination
The livePrompt method uses two channels for streaming data and errors. The cleanup logic is invoked when the chunk channel is closed or if yield returns false, which is good. However, consider handling the scenario where ech immediately returns an error but chch doesn’t close. You might need an extra wait or channel drain to prevent potential goroutine leaks.

app/transports/http/bindings/datagraph.go (2)

62-65: Return immediate error on Ask failure
The direct check for err after d.asker.Ask(ctx, query) is appropriate. This ensures that downstream logic is not executed if the Asker initialization fails. The error wrapping is also good here.


79-89: Graceful partial response handling
When streaming the chunks with the new iterator approach, returning err immediately ends the response. If you want partial results to be kept, consider buffering them until the stream completes or fails. Currently, partial data is written, but subsequent logic stops if an error is encountered. This behavior might be acceptable but is worth confirming against product requirements.

internal/ent/question_create.go (1)

20-30: Ensure concurrency safety when reusing QuestionCreate
QuestionCreate holds a mutation struct that might still have state if reused concurrently. If multiple goroutines call SetCreatedAt and others, it may cause undefined behavior. Typically, builders like QuestionCreate are used once per entity creation.

internal/ent/mutation.go (15)

34-34: Import for Question entity looks good.
No issues found with the added import; it aligns with the new Question references in the code.


71-71: New TypeQuestion constant is consistent.
The newly introduced TypeQuestion = "Question" matches the naming convention for other entity types.


119-121: New fields for questions in AccountMutation are consistent.
These fields (questions, removedquestions, clearedquestions) match the existing pattern for other edges like posts and reacts.


1159-1212: Edge methods for "questions" are well-structured.
All methods (Add, Remove, Clear, Reset, etc.) follow the same design used for other edges, ensuring consistent behavior.
[approve]
Consider adding tests or verifying usage to confirm these methods correctly integrate with the rest of the codebase.


2149-2149: Maintainable fixed-capacity slice initialization.
Using make([]string, 0, 20) is fine and follows the existing approach.


2174-2176: AddedEdges logic for questions is appropriate.
Including account.EdgeQuestions in added edges ensures the correct handling of newly set relationships.


2263-2268: Retrieving IDs for added questions is consistent.
Collecting IDs from m.questions matches the established approach for other edges.


2341-2341: RemovedEdges slice initialization is consistent.
Same approach as for added edges; no issues found.


2363-2365: RemovedEdges logic for questions is correct.
Appending account.EdgeQuestions when m.removedquestions is not nil is consistent with other edges.


2448-2453: RemovedIDs method for questions is well-implemented.
Gathering IDs from m.removedquestions aligns with the ent mutation pattern.


2526-2526: ClearedEdges uses a fixed-cap slice.
Continuing the existing pattern for edges capacity is acceptable.


2551-2553: ClearedEdges logic for "questions" is solid.
Conditionally adding account.EdgeQuestions allows consistent clearing detection.


2610-2611: EdgeCleared method extended for questions.
Returning m.clearedquestions ensures consistent reporting for the "questions" edge.


2677-2679: Edge reset for questions is consistent.
Invoking m.ResetQuestions() properly reverts changes to the "questions" edge.


20320-21083: Comprehensive QuestionMutation logic is well-aligned with Ent conventions.
This large block defines a thorough set of mutation methods for the new Question entity—covering fields, relationships, and old-value lookups. The approach is consistent with Ent’s design, and no critical issues stand out.

internal/ent/schema/question.go (4)

1-2: File Header Looks Good

This file header and package declaration follow common Go conventions for ent schema files.


14-16: Mixins Properly Declared

Using Identifier, CreatedAt, and IndexedAt mixins keeps the schema DRY and consistent with any existing patterns or shared fields.


18-28: Ensure metadata Field Handles Valid JSON

The optional JSON field for metadata is useful for arbitrary data. Ensure that there's validation logic (or usage guidelines) to prevent malformed JSON data.

Would you like a script to scan usage of metadata, ensuring correct JSON usage or any validation presence in the codebase?


30-38: Edges Configuration Aligns with account_id

The edge from author verifies the relationship to Account, marking it as unique and required. This should keep the schema consistent, though confirm that this edge is never left unset during entity creation.

app/resources/question/question.go (5)

1-2: Package Declaration and Imports

All required imports for the question package seem properly declared, aligning with the new Question structure and mapping logic.


10-16: Struct Fields Are Comprehensive

The Question struct includes Slug, Query, Result, Author and an ID field. This matches the ent schema, ensuring data consistency across layers.


18-22: Edge Retrieval Error Handling

Error checking on Edges.AuthorOrErr() is a good practice to avoid nil references. Ensuring that the author is present in the DB is crucial.


24-27: Result Field Conversion

Wrapping datagraph.NewRichText(in.Result) with error handling is valuable to ensure no invalid or malformed content breaks the application.


29-32: Author Mapping Logic

Mapping the linked author entity ensures that the returned author object is the same structure used elsewhere, maintaining consistency.

app/resources/question/repo.go (5)

24-27: Constructing and Mutating the Question

Good approach in combining create.Mutation() on the same chain. This ensures code readability and future maintainability.


28-29: Slug Generation from Query

slug.Make(query) is appropriate for generating a consistent slug; ensure edge cases like empty or extremely long queries are handled gracefully.


35-35: Conflict Resolution Strategy - “slug”

OnConflictColumns("slug").UpdateNewValues() indicates upsert logic. Confirm that overwriting is the intended behavior to avoid unintentionally overwriting existing data.


42-55: Retrieving and Mapping the Saved Entity

Fetching the newly saved question and mapping is a good pattern to return a complete object. Confirm that all edges are loaded if there's the possibility of more linked data in future expansions.


73-89: Slug-based Retrieval Method

GetByQuerySlug is consistent with how Store derives a slug. Keep an eye on collisions if users submit identical queries.

internal/ent/predicate/predicate.go (1)

66-68: New Question Predicate

Having type Question func(*sql.Selector) aligns with ent’s approach to filtering. This is a straightforward addition to support question-specific queries.

internal/ent/schema/account.go (1)

66-66: Good job adding the questions edge to the Account entity.

This new relationship expands the data model to link an account with multiple questions. Ensure that your client code handles any potential cascading operations (e.g., whether to automatically delete questions when an account is deleted) in a way that aligns with your business requirements.

internal/ent/question_delete.go (9)

15-20: The QuestionDelete struct correctly follows Ent patterns.

It encapsulates the configuration, hooks, and mutation needed to manage deletions. This approach provides a clear structure to build on for future custom logic.


23-26: The Where method is properly appending predicates.

This ensures flexible filtering of Question entities during deletion. Nicely done following Ent’s builder pattern.


28-31: Appropriate hooking of the deletion execution.

Wrapping the execution with hooks allows customized pre- or post-deletion behavior. This pattern is consistent with Ent best practices.


33-40: The ExecX method’s panic-on-error approach is used appropriately.

It offers a concise way to handle failures by deferring error handling to caller functions or higher-level panic recoveries.


42-57: sqlExec is well-structured for the low-level deletion logic.

Careful handling of constraints by wrapping them into ConstraintError ensures maintainable error handling. Marking mutation.done = true is important to ensure the builder can’t be reused.


60-62: The QuestionDeleteOne struct nicely embeds QuestionDelete.

This design reuses the existing deletion logic for single-entity deletes, avoiding duplicate code.


65-68: Where method on QuestionDeleteOne consistently re-applies the shared mutation logic.

This adds a straightforward predicate layering for single-entity deletion.


70-81: The Exec method elegantly handles the “no row found” scenario.

Returning a NotFoundError provides a clear contract for callers, ensuring robust error handling when no entity matches the criteria.


83-88: The ExecX method’s panic-on-error usage is consistent.

As with the multi-entity deletion, this design is suitable when the caller is prepared to handle panics.

app/resources/resources.go (2)

46-46: Importing the question package extends resource loading.

This import ensures the new Question resource is available within the application’s dependency injection framework.


98-98: Registering the question.New constructor is consistent with the pattern used for other resources.

It fully integrates the Question resource into the FX lifecycle. Good job maintaining uniformity across resource registrations.

internal/ent/question/question.go (14)

1-2: Auto-generated Ent file successfully created for the question package.

These headers signify that changes will be overwritten when regenerating code from the schema. Maintain any custom changes in separate extension files or custom hooks, if necessary.


3-12: Package structure correctly imports necessary modules for question.

Time, SQL, and sqlgraph are essential for definitions, while github.com/rs/xid is used for ID generation. Everything looks consistent with Ent patterns.


13-43: Constants defining the question schema are well organized.

They cover field names, edge names, and table names. This ensures consistent references across your codebase.


45-65: Columns and ValidColumn elegantly manage valid fields.

Mapping the schema fields into a slice and verifying against it adds safety for dynamic queries. Good job ensuring robust field validation.


67-74: Default field functions and validators are well structured.

They allow custom initialization logic (e.g., generating xid.ID) and validation prior to saving the entity.


76-78: OrderOption type definition is standard for Ent ordering.

This approach offers a flexible way to chain ordering logic without duplicating code throughout your queries.


79-82: ByID ordering function is properly implemented.

It uses sql.OrderByField to produce an OrderOption—a typical Ent pattern for custom or field-based ordering.


84-87: ByCreatedAt ordering function follows the same structure.

The approach ensures consistent ordering capabilities across various data fields.


89-92: ByIndexedAt extends the same ordering logic.

It’s clear this method remains consistent with the rest.


94-97: BySlug ordering function is straightforward.

Follows the established pattern for ordering queries on the slug field.


99-102: ByQuery ordering function ensures sorting by the question text.

Maintaining uniform naming conventions for clarity is good practice.


104-107: ByResult ordering function for sorting on result content.

This helps when retrieving questions sorted by processed output or appended content.


109-112: ByAccountID ordering provides easy grouping by account associations.

This is consistent with the new edge linking accounts to questions.


114-126: ByAuthorField leverages sqlgraph.OrderByNeighborTerms for M2O relationship ordering.

The separate newAuthorStep function keeps the logic clean and helps avoid duplication. Good job structuring neighbor-based ordering carefully.

internal/ent/question.go (1)

18-50: The generated code approach looks solid.
This entire entity file is automatically generated by Ent. Typically, we avoid manually editing these files to prevent losing changes on the next code generation. The new fields (Slug, Query, etc.) and the edges (author) appear consistent with the standard Ent patterns.

internal/ent/tx.go (1)

55-56: Integration of QuestionClient is correct and consistent.
The new Question *QuestionClient field is initialized in init(). This ensures the transactional context is extended to the new entity. It aligns with standard Ent patterns, so it looks good.

Also applies to: 215-215

internal/ent/hook/hook.go (1)

240-250: Proper handling of QuestionMutation in hooks.
The new QuestionFunc and its Mutate method correctly follow the established pattern of type checking mutation objects. This ensures that mutation logic applies specifically to the Question entity.

app/resources/datagraph/content_test.go (1)

129-159: Test coverage for Markdown-based content creation is solid.
The new TestNewRichTextFromMarkdown properly verifies generating short text, references, and rendered HTML. This helps ensure the content transformation logic behaves as expected.

internal/ent/question_update.go (2)

20-32: Consider further validation for predicates when chaining multiple updates.

Although the Where function is flexible, ensure that complex filtering logic does not accidentally exclude rows meant to be updated or vice versa. You may want to add additional validation or logging for scenarios where unintuitive predicates are combined.


108-112: Validate the presence of an account before assigning account ID.

When setting account_id, confirm the ID actually references a valid account. This preemptive check helps prevent potential foreign key constraint errors.

internal/ent/ent.go (2)

34-34: Ensure consistent grouping of imports.

The addition of "github.com/Southclaws/storyden/internal/ent/question" is appropriate for referencing the question entity. Validate your import ordering guidelines to keep imports organized and consistent across the project.


118-118: Verify the correctness of added table validation.

Adding question.Table: question.ValidColumn is a good measure to ensure column checks for the new entity. Confirm that all question columns are properly recognized by ValidColumn.

internal/ent/question/where.go (2)

14-17: Check ID filter usage for partial updates and caching.

IDs of type xid.ID may have unique behaviors (e.g., collisions, case differences). Make sure the filter conditions align with the caching strategy, especially if the ID generation scheme interacts with question slug creation.


454-463: Review the correctness of HasAuthor in M2O relations.

The HasAuthor() predicate works as intended for one-to-many relationships, but if usage patterns expect more complex logic (e.g., user roles or multiple associations), validate that the logic still fits.

internal/ent/account.go (2)

173-180: Ensure eager loading of questions for subsequent logic.

If subsequent logic depends on Questions, ensure the edge is loaded before using QuestionsOrErr(), or handle the NotLoadedError gracefully. This particularly matters in scenarios where caching is involved.


445-448: Maintain consistent naming convention for query methods.

QueryQuestions() follows established naming patterns. Confirm that external references to this method (if any) align with the same naming approach for clarity across the codebase.

internal/ent/question_query.go (4)

20-32: Robust Query Builder Implementation

The struct and field definitions, along with the initial setup of the query builder, are well-structured and align with Ent’s best practices. The approach of storing predicates, ordering conditions, and context in the QuestionQuery fields provides clean extensibility.


87-98: Graceful Handling of First Query

Using Limit(1) followed by handling an empty result set with a NotFoundError is a standard pattern for retrieving a single entity safely. This approach is commendable.


178-185: Cautious Use of Panics in X-Suffix Methods

The FirstIDX and similar X-suffix methods (like OnlyX, etc.) panic if an unexpected error occurs. While this is part of Ent’s generated code, confirm that the calling code handles these panics appropriately or that these methods are used sparsely in production to avoid unintended disruptions.


495-528: Modifiers and Custom Selectors

The support for adding query modifiers and custom logic via Modify is a flexible extension point. Ensure consistent usage across the codebase so that logic is centrally maintained and discoverable.

internal/ent/account/account.go (5)

56-57: Clarity in Naming the "questions" Edge

Defining EdgeQuestions for the new questions relationship is consistent with existing naming conventions. This edge name is clear and self-explanatory.


138-144: Snapping to Existing Pattern

Introducing the QuestionsTable, QuestionsInverseTable, and QuestionsColumn for the new relation aligns with existing ent naming conventions, reducing confusion for other maintainers.


432-437: Order By Questions Count

ByQuestionsCount is a neat addition that leverages sqlgraph.OrderByNeighborsCount. Confirm thorough testing in real scenarios to ensure correct ordering when multiple edges exist.


439-444: Ordering by Questions Terms

ByQuestions appropriately delegates neighbor-based ordering to sqlgraph.OrderByNeighborTerms. This provides more granular ordering for advanced queries.


655-661: New Step for Questions Edge

newQuestionsStep() is consistent with other edge step builders. The O2M edge definition correctly matches the intended one-to-many relationship between accounts and questions.

internal/ent/account/where.go (1)

783-792: Simple Existence Check for Questions

HasQuestions effectively checks for at least one related question. Ensure calling code interprets this correctly, especially in multi-filter logic.

internal/ent/migrate/schema.go (4)

694-704: New Columns for “questions” Table

Defining id, created_at, indexed_at, slug, etc., provides a rich schema. The uniqueness constraint on slug ensures queries can quickly find questions by a canonical string.


705-718: Maintaining Relational Integrity

OnDelete: schema.NoAction for the account_id foreign key signals a strict requirement that an account must exist before referencing it in questions. This can be ideal if desired, but double-check if a cascade or set-null policy might be more user-friendly for record cleanup.


1015-1015: Inclusion in Global Tables Slice

Adding QuestionsTable to the global Tables array ensures the table is generated and managed by migrations. This is a pivotal step to fully integrate the new entity.


1069-1069: Foreign Key Reference

QuestionsTable.ForeignKeys[0].RefTable = AccountsTable properly links the question entity to its parent account. Verify the correct usage of schema.NoAction on delete to avoid orphan references if accounts are removed.

internal/ent/runtime.go (2)

27-27: Import for question package is correct.
The introduced import aligns with the new Question entity.


801-831: Properly initializing the Question mixin.
The code follows the established pattern of reading mixin fields, setting defaults, and defining validators. This addition appears consistent with existing entities.

internal/ent/account_create.go (3)

29-29: Import statement for question package confirmed.
Bringing in the question package is necessary for referencing Question entities.


291-305: New methods for adding Question entities.
The methods AddQuestionIDs and AddQuestions provide a straightforward way to associate Question entities with an Account. This is consistent with existing naming patterns.


761-776: Edge specification for questions during account creation.
The O2M relationship logic is consistent with the approach used for similar edges like posts or emails.

internal/ent/account_query.go (8)

30-30: Import statement for question aligned with the new edge.
This is needed to support the QueryQuestions method.


52-52: New field withQuestions in AccountQuery.
Enabling the eager-loading of Question entities is consistent with other “with” patterns.


277-298: QueryQuestions method to traverse the questions edge.
Implements a typical O2M query flow. The step logic is correct for bridging from account to question.


741-741: Clone logic for withQuestions.
Retaining the cloned withQuestions query ensures consistency in repeated query usage.


848-858: Eager load approach via WithQuestions.
Mirrors other With* methods. Adhering to established design patterns in the codebase.


Line range hint 1058-1067: Expanding loaded types array to 20.
Reflects adding a new “questions” relationship. This is important to track loaded edges.


1159-1165: Loading logic for queried questions.
The check ensures an empty slice is pre-initialized and appended when the withQuestions sub-query is active.


1495-1524: loadQuestions for the O2M edge.
The usage of the foreign key AccountID is consistent with other edge-loading patterns.

internal/ent/account_update.go (7)

30-30: Import for question package.
Required for referencing the new Question entity and its schema definitions.


320-334: Introducing AddQuestionIDs & AddQuestions in AccountUpdate.
The logic parallels similar methods for other edges. Implementation is clean and consistent.


658-678: Removal methods for the questions edge.
Provides necessary operations to clear and remove Question entities, mirroring standard design.


1370-1414: Edge handling in sqlSave for question fields.
The O2M setup for questions is cohesive and well-aligned with the rest of the codebase.


2221-2235: Methods for associating questions in AccountUpdateOne.
Allows adding multiple Question entities to a single Account, matching the multi-add pattern used elsewhere.


2559-2579: Removal methods for questions in AccountUpdateOne.
The approach to clearing and removing questions is suitably consistent with other edges.


3301-3345: O2M edge handling in sqlSave for AccountUpdateOne.
Covers add, remove, and clear operations for questions. No issues noted.

internal/ent/client.go (9)

38-38: Add Question import.
Adding the question import helps integrate the new Question entity into the Ent client.


90-91: Introduce QuestionClient field.
Declaring Question *QuestionClient extends the top-level Ent client to support operations on the Question entity.


130-130: Initialize QuestionClient in init().
Ensures the Question client is properly set up with the correct configuration.


246-246: Add QuestionClient to transactional client.
Including Question: NewQuestionClient(cfg) in the Tx creation ensures that Question operations can be performed in a transaction.


289-289: Support QuestionClient in BeginTx.
Same rationale as above, allowing transactional operations on Questions.


326-326: Enabling mutation hooks for Question.
Enables consistent application of hooks (logging, validation, etc.) across all entity operations, including Question.


339-339: Enabling interceptors for Question.
Allows interceptors to be inherited for the Question entity, ensuring consistent query transformations or validations.


386-387: Handle QuestionMutation in Mutate method.
Ensures the client dispatches Question mutations to the specialized Question.mutate function.


637-651: Add QueryQuestions for Account.
A new edge method to query the questions relationship from an Account, contributing to a more complete data model.

app/services/semdex/semdex.go (1)

46-46: Switched from channels to a callback-based Ask.
This refactor replaces channels with a callback mechanism, offering a potentially more streamlined flow for yielding ask results. Confirm that upstream callers are updated accordingly.

internal/ent/er.html (2)

209-218: Introduce “Question” entity.
Adding a new entity with fields like slug, query, and result clarifies how questions are stored. The indexed_at column can facilitate or track search indexing.


252-252: Define relationship from Account to Question.
Enabling an account to reference multiple questions establishes a clear authoring relationship. This helps when linking user accounts to their questions.

app/resources/datagraph/content.go (2)

17-17: Import blackfriday for Markdown support.
The new import is necessary for parsing Markdown content in newly introduced methods.


150-157: Generate rich text from Markdown.
The new NewRichTextFromMarkdown function provides a convenient way to convert Markdown into the existing Content structure, preserving links, media, and references.

internal/ent/question/where.go Show resolved Hide resolved
- key based on question, slugified
- future work: vector lookup with tight threshold
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
internal/ent/question/where.go (1)

424-452: ⚠️ Potential issue

Prevent partial matches on AccountID string operations.

Using string-based predicates (Contains, HasPrefix, HasSuffix) on xid.ID fields can lead to incorrect matches. These operations should be removed or replaced with exact matching.

-// AccountIDContains applies the Contains predicate on the "account_id" field.
-func AccountIDContains(v xid.ID) predicate.Question {
-	vc := v.String()
-	return predicate.Question(sql.FieldContains(FieldAccountID, vc))
-}
-
-// AccountIDHasPrefix applies the HasPrefix predicate on the "account_id" field.
-func AccountIDHasPrefix(v xid.ID) predicate.Question {
-	vc := v.String()
-	return predicate.Question(sql.FieldHasPrefix(FieldAccountID, vc))
-}
-
-// AccountIDHasSuffix applies the HasSuffix predicate on the "account_id" field.
-func AccountIDHasSuffix(v xid.ID) predicate.Question {
-	vc := v.String()
-	return predicate.Question(sql.FieldHasSuffix(FieldAccountID, vc))
-}
🧹 Nitpick comments (6)
app/transports/http/bindings/datagraph.go (1)

62-65: Add input validation for the query parameter.

Consider validating the query parameter before passing it to asker.Ask(). Empty or malformed queries should be caught early to avoid unnecessary processing.

+ if strings.TrimSpace(query) == "" {
+   return echo.NewHTTPError(http.StatusBadRequest, "Query parameter cannot be empty")
+ }
+ 
  iter, err := d.asker.Ask(ctx, query)
internal/ent/question_create.go (1)

268-269: Fix grammatical error in comments.

In the comments, "the was proposed for insertion" should be corrected to "that were proposed for insertion" for clarity.

Apply this diff to fix the grammatical errors:

 //			// Update the row with the new values
-//			// the was proposed for insertion.
+//			// that were proposed for insertion.

Also applies to: 399-400, 674-675

app/services/semdex/asker/cached.go (1)

53-67: Optimize chunking of markdown content in cachedResult

The current implementation splits the markdown content into chunks using strings.SplitAfter(string(md), " "), which splits after every space. This can result in very small chunks and may affect performance or user experience due to excessive processing and network overhead.

Consider splitting the content into larger chunks, such as by sentences or paragraphs, to improve efficiency:

-    chunks := strings.SplitAfter(string(md), " ")
+    chunks := strings.SplitAfter(string(md), "\n\n")

Alternatively, implement a more sophisticated chunking mechanism that balances chunk size and readability.

app/services/semdex/asker/perplexity.go (1)

114-115: Use structured logging instead of fmt.Println

Logging with fmt.Println is not ideal for production code as it writes directly to standard output and lacks log levels and structured context. In line 114, replace fmt.Println with your structured logger to provide better logging practices:

-    fmt.Println(string(event.Data))
+    a.logger.Error("no citations in response", zap.String("response_data", string(event.Data)))
app/services/semdex/asker/asker.go (1)

Line range hint 40-57: Consider enhancing the answer prompt template.

The template provides clear instructions but could be improved to handle edge cases:

  1. Add guidance for when no relevant sources are found
  2. Specify how to handle conflicting information from multiple sources
 var AnswerPrompt = template.Must(template.New("").Parse(`
 You are an expert assistant. Answer the user's question accurately and concisely using the provided sources. Cite the sources in a separate list at the end of your answer. 
 Ensure that the source URLs (in "sdr" format) are kept exactly as they appear, without modification or breaking them across lines.
+If no relevant information is found in the provided sources, clearly state this limitation.
+If sources contain conflicting information, acknowledge the discrepancy and explain your reasoning for the chosen answer.
 You MUST include references to the sources below in your answer in addition to other sources you may have.
 
 Sources:
app/resources/datagraph/content_test.go (1)

129-159: Add more test cases for edge cases.

While the current test covers basic functionality, consider adding tests for:

  1. Empty content
  2. Malformed references
  3. Special characters in the content
  4. Very long content
t.Run("empty_content", func(t *testing.T) { ... })
t.Run("malformed_references", func(t *testing.T) { ... })
t.Run("special_characters", func(t *testing.T) { ... })
t.Run("very_long_content", func(t *testing.T) { ... })
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b4e04b and f69c1f8.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (38)
  • app/resources/datagraph/content.go (2 hunks)
  • app/resources/datagraph/content_test.go (1 hunks)
  • app/resources/question/question.go (1 hunks)
  • app/resources/question/repo.go (1 hunks)
  • app/resources/resources.go (2 hunks)
  • app/services/semdex/asker/asker.go (1 hunks)
  • app/services/semdex/asker/cached.go (1 hunks)
  • app/services/semdex/asker/default.go (1 hunks)
  • app/services/semdex/asker/perplexity.go (4 hunks)
  • app/services/semdex/semdex.go (1 hunks)
  • app/transports/http/bindings/datagraph.go (2 hunks)
  • internal/ent/account.go (14 hunks)
  • internal/ent/account/account.go (4 hunks)
  • internal/ent/account/where.go (1 hunks)
  • internal/ent/account_create.go (3 hunks)
  • internal/ent/account_query.go (9 hunks)
  • internal/ent/account_update.go (7 hunks)
  • internal/ent/client.go (11 hunks)
  • internal/ent/ent.go (2 hunks)
  • internal/ent/er.html (2 hunks)
  • internal/ent/hook/hook.go (1 hunks)
  • internal/ent/migrate/schema.go (3 hunks)
  • internal/ent/mutation.go (15 hunks)
  • internal/ent/predicate/predicate.go (1 hunks)
  • internal/ent/question.go (1 hunks)
  • internal/ent/question/question.go (1 hunks)
  • internal/ent/question/where.go (1 hunks)
  • internal/ent/question_create.go (1 hunks)
  • internal/ent/question_delete.go (1 hunks)
  • internal/ent/question_query.go (1 hunks)
  • internal/ent/question_update.go (1 hunks)
  • internal/ent/runtime.go (2 hunks)
  • internal/ent/schema/account.go (1 hunks)
  • internal/ent/schema/question.go (1 hunks)
  • internal/ent/tx.go (2 hunks)
  • internal/infrastructure/ai/ai.go (2 hunks)
  • internal/infrastructure/ai/mock.go (1 hunks)
  • internal/infrastructure/ai/openai.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (14)
  • internal/ent/predicate/predicate.go
  • internal/ent/schema/account.go
  • app/services/semdex/semdex.go
  • app/resources/resources.go
  • internal/ent/hook/hook.go
  • internal/ent/ent.go
  • internal/ent/er.html
  • app/resources/datagraph/content.go
  • internal/ent/account.go
  • app/resources/question/question.go
  • internal/ent/schema/question.go
  • internal/ent/question.go
  • app/resources/question/repo.go
  • internal/ent/question_delete.go
🔇 Additional comments (53)
internal/ent/tx.go (2)

55-56: LGTM: Question client field added to Tx struct

The Question client field is properly added to the Tx struct following the same pattern as other entities.


215-215: LGTM: Question client initialization added

The Question client is properly initialized in the init method using the standard NewQuestionClient constructor.

internal/ent/client.go (7)

38-38: LGTM: Question schema import added

The question schema package is properly imported.


90-91: LGTM: Question client field added to Client struct

The Question client field is properly added to the Client struct following the same pattern as other entities.


130-130: LGTM: Question client initialization added

The Question client is properly initialized in the init method using the standard NewQuestionClient constructor.


326-326: LGTM: Question added to Use and Intercept methods

The Question client is properly added to both Use and Intercept methods to support hooks and interceptors.

Also applies to: 339-339


386-387: LGTM: Question added to Mutate method

The Question mutation case is properly added to the Mutate method.


4254-4401: LGTM: QuestionClient implementation

The QuestionClient implementation is complete and follows the standard ent patterns with all necessary CRUD operations and edge handling.


5052-5053: LGTM: Question added to hooks and interceptors structs

Question is properly added to both hooks and interceptors structs.

Also applies to: 5058-5059

internal/ent/question/question.go (1)

1-2: Generated code by Ent framework

This file is auto-generated by the Ent framework. Direct modifications are not recommended as they may be overwritten. Ensure that any changes are made through the Ent schema definitions to maintain consistency.

internal/ent/question_update.go (1)

1-526: The code changes in this file are auto-generated and comply with Ent framework conventions.

The methods and structures for updating Question entities are correctly implemented. No issues are identified in the code.

internal/ent/question_query.go (1)

1-630: The query builder for Question entities is correctly implemented.

The code provides comprehensive querying capabilities, including predicates, ordering, eager-loading of related entities, and aggregation functions. No issues are found.

internal/ent/question_create.go (1)

1-880: The rest of the code appears correct and follows Ent framework standards.

All required fields and relationships are properly handled, and the upsert functionality is correctly implemented. No issues are detected.

internal/ent/account_update.go (4)

672-675: Same potential nil pointer dereference in RemoveQuestions method

The RemoveQuestions method also accesses q[i].ID without checking if q[i] is nil, which may cause a panic if a nil *Question is passed. Please add a nil check similar to the one suggested for AddQuestions.


2230-2233: Add nil check in AddQuestions method of AccountUpdateOne

In the AddQuestions method of AccountUpdateOne, accessing q[i].ID without checking for nil may lead to a panic if a nil *Question is passed. Adding a nil check will prevent this issue.


2573-2576: Potential nil pointer dereference in RemoveQuestions method of AccountUpdateOne

Similar to the previous methods, the RemoveQuestions method in AccountUpdateOne may panic when q[i] is nil. Please add a nil check.


1370-1414: Edge handling for questions in sqlSave methods is correctly implemented

The addition of edge handling for questions in the sqlSave methods of AccountUpdate and AccountUpdateOne appears to be correctly implemented and aligns with the existing patterns for other entities.

Also applies to: 3301-3345

internal/ent/mutation.go (15)

34-34: Import of 'question' package is appropriate

The import statement for the question package correctly includes the new 'Question' entity.


71-71: Addition of 'TypeQuestion' constant is appropriate

The TypeQuestion constant is added to define the type name for the 'Question' entity, aligning with existing type definitions.


119-121: Addition of 'questions' edge fields in 'AccountMutation'

The fields questions, removedquestions, and clearedquestions are correctly added to the AccountMutation struct to manage the 'questions' edge, following established patterns.


1159-1212: Methods for managing 'questions' edge are correctly implemented

The methods AddQuestionIDs, RemoveQuestionIDs, ClearQuestions, QuestionsCleared, QuestionsIDs, RemovedQuestionsIDs, and ResetQuestions are correctly added to manage the 'questions' edge in AccountMutation, consistent with existing edge management methods.


2149-2149: Initialization of 'edges' slice in 'AddedEdges' method

The 'edges' slice is initialized with a capacity of 20 in the AddedEdges method, which is appropriate considering the number of potential edges.


2174-2176: Include 'questions' edge in 'AddedEdges' method

The 'questions' edge is correctly included in the AddedEdges method to ensure it's tracked when edges are added.


2263-2268: Properly retrieve added 'questions' edge IDs in 'AddedIDs' method

The implementation correctly retrieves the IDs of the added 'questions' edges in the AddedIDs method, ensuring they are processed appropriately.


2341-2341: Initialization of 'edges' slice in 'RemovedEdges' method

The 'edges' slice is initialized with a capacity of 20 in the RemovedEdges method, consistent with the AddedEdges method.


2363-2365: Include 'questions' edge in 'RemovedEdges' method

The 'questions' edge is correctly included in the RemovedEdges method to track edges that have been removed.


2448-2453: Properly retrieve removed 'questions' edge IDs in 'RemovedIDs' method

The implementation correctly retrieves the IDs of the removed 'questions' edges in the RemovedIDs method.


2526-2526: Initialization of 'edges' slice in 'ClearedEdges' method

The 'edges' slice is initialized with a capacity of 20 in the ClearedEdges method, aligning with other edge methods.


2551-2553: Include 'questions' edge in 'ClearedEdges' method

The 'questions' edge is correctly included in the ClearedEdges method to track edges that have been cleared.


2610-2611: Edge clearance check for 'questions' edge in 'EdgeCleared' method

The method correctly checks if the 'questions' edge has been cleared.


2677-2679: Resetting 'questions' edge in 'ResetEdge' method

The ResetQuestions method is correctly called to reset changes to the 'questions' edge.


20374-21136: Comprehensive implementation of 'QuestionMutation' struct and methods

The QuestionMutation struct and all its associated methods are thoroughly implemented, enabling complete management of 'Question' entity mutations. The methods follow established patterns used in other entity mutations, ensuring consistency across the codebase.

internal/ent/account_create.go (2)

291-304: LGTM!

The methods for adding questions follow the established pattern for edge management in the codebase.


761-776: LGTM!

The edge specification is correctly implemented in createSpec, following the same pattern as other edges.

internal/ent/account_query.go (5)

52-52: LGTM!

The field declaration follows the established pattern for edge query fields.


277-297: LGTM!

The query method correctly sets up the graph traversal for the questions edge.


848-857: LGTM!

The eager loading configuration is properly implemented.


1494-1523: LGTM!

The loading function correctly handles the loading of questions, including proper error handling and foreign key validation.


Line range hint 1058-1067: LGTM!

The loadedTypes array is correctly updated to include the questions edge.

internal/ent/migrate/schema.go (3)

694-704: LGTM!

The column definitions are comprehensive and include all necessary fields with appropriate types and constraints.


1015-1015: LGTM!

The table is correctly registered in the Tables slice and properly initialized.

Also applies to: 1069-1069


705-718: Verify the OnDelete behavior for the account foreign key.

The foreign key is set to NoAction which might prevent account deletion if there are associated questions. Consider whether Cascade would be more appropriate to automatically clean up questions when an account is deleted.

✅ Verification successful

The NoAction behavior for questions-accounts relationship is correct

The current behavior aligns with the codebase's pattern of preserving user-generated content. This is evidenced by similar NoAction treatment of posts-accounts relationships, suggesting a deliberate design choice to prevent content loss when accounts are deleted.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if other similar edges use Cascade for cleanup
rg --type go "OnDelete:\s+schema\.Cascade" internal/ent/migrate/

Length of output: 2586


Script:

#!/bin/bash
# Get context of foreign key definitions including table names
rg --type go -B 2 "OnDelete:\s+schema\.(NoAction|Cascade)" internal/ent/migrate/schema.go

# Also search for any comments about deletion behavior
rg --type go "(?i)delete|cascade|foreign key" internal/ent/migrate/schema.go

Length of output: 8603

internal/ent/account/where.go (1)

783-804: LGTM!

The predicate functions are correctly implemented, following the established pattern for edge predicates.

app/services/semdex/asker/default.go (1)

19-30: Refactored Ask method improves control flow and error handling

The updated Ask method transitions from a channel-based approach to a function-based iterator. This refactoring simplifies the control flow, enhances error handling, and improves the overall readability and maintainability of the code.

internal/infrastructure/ai/openai.go (1)

Line range hint 46-81: Proper handling of the yield function in streaming responses

The updated PromptStream method correctly utilizes the yield function to send streaming responses and checks its return value to allow the caller to terminate the stream early. Error handling is appropriately managed by yielding errors when they occur, enhancing the robustness of the streaming logic.

app/services/semdex/asker/perplexity.go (1)

108-115: Verify if absence of citations should trigger an error

The code returns an error when there are no citations in the response:

if len(cr.Citations) == 0 {
    // ...
    yield("", fmt.Errorf("no citations in response"))
    return
}

Ensure that the API is expected to always return citations. If the absence of citations is acceptable in certain cases, consider handling this scenario without returning an error to prevent unnecessary failures.

✅ Verification successful

Citations are required in Perplexity API responses

The code's behavior is correct. Citations appear to be a core part of the Perplexity API response structure, as evidenced by:

  • Citations field is part of the CompletionResponse struct
  • Response processing includes citation marker handling
  • No configuration options exist to make citations optional
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for Perplexity-related files
fd perplexity

# Search for citation-related code
rg -i "citations?" -A 5 -B 5

# Look for documentation about Perplexity integration
fd "README|docs" --extension md | xargs rg -i "perplexity|citation"

# Search for any configuration related to citations
rg -i "citation.*required" -A 5 -B 5

Length of output: 70867


Script:

#!/bin/bash
# Search for perplexity test files
fd perplexity.*test

# Search for configuration files
fd "config|settings" --type f

# Search for citation-related code in test files
rg -i "citation" --type test

# Look for perplexity configuration
rg -i "perplexity.*config" -A 5 -B 5

Length of output: 3249

internal/infrastructure/ai/ai.go (1)

17-17: Ensure all implementations of Prompter interface are updated

The PromptStream method signature in the Prompter interface has been changed. Verify that all implementations of this interface, as well as any consumers, are updated accordingly to comply with the new method signature and to prevent runtime errors.

app/services/semdex/asker/asker.go (1)

21-38: LGTM! Clean separation of concerns.

The refactoring improves modularity by:

  • Separating asker creation logic into a helper function
  • Adding caching capability through composition
internal/ent/runtime.go (1)

801-831: LGTM! Standard entity initialization.

The question entity initialization follows the established pattern with proper setup of:

  • Field descriptors
  • Default values
  • ID validation
internal/ent/account/account.go (4)

56-57: LGTM! Edge constant follows the established pattern.

The new EdgeQuestions constant follows the consistent naming pattern and is properly documented.


138-144: LGTM! Table constants are well-defined.

The table constants for the questions edge are properly defined with clear documentation of their purpose and relationships.


432-444: LGTM! Ordering functions are correctly implemented.

The ByQuestionsCount and ByQuestions functions follow the established pattern for edge ordering, properly handling both count-based and term-based ordering scenarios.


655-661: LGTM! Graph step function is properly implemented.

The newQuestionsStep function correctly sets up the One-to-Many relationship between accounts and questions, following the consistent pattern used throughout the codebase.

Comment on lines +79 to 90
for chunk, err := range iter {
if err != nil {
return err
}

if flusher != nil {
flusher.Flush()
}
if _, err := w.Write([]byte(chunk)); err != nil {
return err
}

case err := <-errSignal:
if err != nil {
return err
}
if flusher != nil {
flusher.Flush()
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance context cancellation handling.

The iterator loop should respect context cancellation to handle client disconnections gracefully. Consider adding context checks within the loop.

  for chunk, err := range iter {
+   select {
+   case <-ctx.Done():
+     return ctx.Err()
+   default:
      if err != nil {
        return err
      }

      if _, err := w.Write([]byte(chunk)); err != nil {
        return err
      }

      if flusher != nil {
        flusher.Flush()
      }
+   }
  }

Committable suggestion skipped: line range outside the PR's diff.

internal/ent/account_update.go Show resolved Hide resolved
internal/infrastructure/ai/mock.go Show resolved Hide resolved
Comment on lines +77 to +102
iter, err := a.asker.Ask(ctx, q)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return func(yield func(string, error) bool) {
acc := []string{}

defer func() {
err := a.cacheResult(ctx, accountID, q, acc)
if err != nil {
a.logger.Error("failed to cache result", zap.Error(err))
}
}()

for chunk, err := range iter {
if err != nil {
yield("", err)
return
}

acc = append(acc, chunk)
if !yield(chunk, nil) {
return
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Correct the usage of the iter function in livePrompt method

In the livePrompt method, the iter variable is a function returned by a.asker.Ask(ctx, q) with the signature func(yield func(string, error) bool). However, it is incorrectly used as an iterator in a for loop:

for chunk, err := range iter {
    if err != nil {
        yield("", err)
        return
    }

    acc = append(acc, chunk)
    if !yield(chunk, nil) {
        return
    }
}

This usage is invalid because iter is not an iterator. Instead, you should call iter and pass a yield function to handle the chunks and errors.

Apply this diff to fix the issue:

 func (a *cachedAsker) livePrompt(ctx context.Context, q string) (func(yield func(string, error) bool), error) {
     accountID, err := session.GetAccountID(ctx)
     if err != nil {
         return nil, fault.Wrap(err, fctx.With(ctx))
     }

     iter, err := a.asker.Ask(ctx, q)
     if err != nil {
         return nil, fault.Wrap(err, fctx.With(ctx))
     }

     return func(yield func(string, error) bool) {
         acc := []string{}

         defer func() {
             err := a.cacheResult(ctx, accountID, q, acc)
             if err != nil {
                 a.logger.Error("failed to cache result", zap.Error(err))
             }
         }()

-        for chunk, err := range iter {
-            if err != nil {
-                yield("", err)
-                return
-            }
-
-            acc = append(acc, chunk)
-            if !yield(chunk, nil) {
-                return
-            }
-        }
+        err := iter(func(chunk string, err error) bool {
+            if err != nil {
+                yield("", err)
+                return false
+            }
+            acc = append(acc, chunk)
+            return yield(chunk, nil)
+        })
+        if err != nil {
+            yield("", err)
+            return
+        }
     }, nil
 }

@Southclaws Southclaws merged commit 508d616 into main Jan 11, 2025
4 checks passed
@Southclaws Southclaws deleted the cache-ask-results branch January 11, 2025 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant