Skip to content

Conversation

@jjmata
Copy link
Collaborator

@jjmata jjmata commented Oct 1, 2025

Summary

  • propagate chat session identifiers and anonymized user hashes into Langfuse logging for OpenAI calls
  • derive session and user metadata from chat messages when requesting LLM responses
  • extend assistant tests to assert the new metadata is passed through

Testing

  • bin/rails test test/models/assistant_test.rb
  • bin/rails test test/models/provider/openai_test.rb

https://chatgpt.com/codex/tasks/task_e_68daafd5d41c83328af563e99a785fd4

Summary by CodeRabbit

  • Chores

    • Adds per-session and anonymized user identifiers to chat interactions and associated logging.
    • Extends provider integration to include these identifiers across streaming and non-streaming responses.
  • Tests

    • Adds coverage to verify session and user identifiers are correctly propagated through the chat response flow.
  • Refactor

    • Updates internal interfaces to accept optional session and user identifiers without altering existing behavior or public usage.

@jjmata jjmata added the codex Touched by OpenAI Codex somehow label Oct 1, 2025 — with ChatGPT Codex Connector
@coderabbitai
Copy link

coderabbitai bot commented Oct 1, 2025

Walkthrough

Introduces per-chat/session identifiers in LLM calls. Assistant::Responder now derives session_id and user_identifier from chat context and passes them to provider.chat_response. Provider::LlmConcept and Provider::OpenAI method signatures are extended to accept these. OpenAI implementation forwards identifiers to payloads and Langfuse logging. Tests assert propagation.

Changes

Cohort / File(s) Summary
Assistant responder: session/user derivation
app/models/assistant/responder.rb
Add private helpers to compute chat_session_id and chat_user_identifier; pass session_id and user_identifier to provider.chat_response.
Provider interface: signature update
app/models/provider/llm_concept.rb
Extend chat_response with session_id and user_identifier keyword params (default nil); no behavior change.
OpenAI provider: propagation and logging
app/models/provider/openai.rb
Update chat_response and log_langfuse_generation signatures; include session_id and user_identifier in input/log payloads and Langfuse trace metadata for streaming and non-streaming paths.
Tests: assertion of propagation
test/models/assistant_test.rb
Add expectations for session_id (chat id as string) and user_identifier (SHA256 of user_id) in provider.chat_response calls across scenarios.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Responder as Assistant::Responder
  participant Provider as Provider::OpenAI
  participant Lfuse as Langfuse

  User->>Responder: handle_message(message)
  Responder->>Responder: chat_session_id(), chat_user_identifier()
  Responder->>Provider: chat_response(..., session_id, user_identifier)

  alt Streaming
    Provider->>Lfuse: start generation (session_id, user_id)
    Provider-->>Responder: stream tokens
    Provider->>Lfuse: end generation (usage, session_id, user_id)
  else Non-streaming
    Provider->>Lfuse: log generation (input/output, usage, session_id, user_id)
    Provider-->>Responder: full response
  end

  Responder-->>User: deliver response
  note over Responder,Provider: session_id = chat.id (string)<br/>user_identifier = SHA256(user_id)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I bounced through chats with carrot-bright cheer,
Tagging each session, who’s nibbling here.
A hash for the user, a string for the thread,
Logs leave a trail where the tokens tread.
Now every reply knows where it’s been—
Hippity-hop, traceable within! 🥕🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “Add Langfuse session and user metadata to OpenAI traces” accurately and concisely summarizes the primary change of this pull request, which is to propagate session identifiers and anonymized user hashes into Langfuse logging for OpenAI interactions.
✨ Finishing touches
  • 📝 Docstrings were successfully generated. (🔄 Check again to generate docstrings again)
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/add-session-and-user-tracking-to-traces

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jjmata jjmata marked this pull request as ready for review October 1, 2025 17:06
@jjmata
Copy link
Collaborator Author

jjmata commented Oct 1, 2025

Working well it seems:
Screenshot 2025-10-01 at 7 06 58 PM

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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/models/provider/openai.rb (1)

96-103: Include user for abuse/safety tracking; session_id isn’t supported
Add user: user_identifier to the client.responses.create call to leverage OpenAI’s built-in safety monitoring. Continue handling session_id in your own layer or via the Conversations/Assistants APIs.

🧹 Nitpick comments (1)
app/models/assistant/responder.rb (1)

94-98: Remove redundant user_id presence check
The belongs_to :user association in Chat requires user_id by default, so chat.user_id will never be nil—replace

return unless chat&.user_id

with

return unless chat

to simplify.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7273878 and 25de680.

📒 Files selected for processing (4)
  • app/models/assistant/responder.rb (2 hunks)
  • app/models/provider/llm_concept.rb (1 hunks)
  • app/models/provider/openai.rb (4 hunks)
  • test/models/assistant_test.rb (4 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
app/models/**/*.rb

📄 CodeRabbit inference engine (.cursor/rules/project-design.mdc)

Domain models should not call Provider::Registry directly; use a Provided concern within the model’s namespace to select providers and expose convenience methods

Use ActiveRecord validations for forms and complex domain constraints.

app/models/**/*.rb: Place business logic in POROs and model classes under app/models
Models should answer questions about themselves (e.g., prefer account.balance_series over service objects)
Implement complex validations and business logic with ActiveRecord validations
Model-level validations may mirror DB constraints but are not strictly required

Files:

  • app/models/provider/openai.rb
  • app/models/assistant/responder.rb
  • app/models/provider/llm_concept.rb
app/models/provider/**/*.rb

📄 CodeRabbit inference engine (.cursor/rules/project-design.mdc)

Concrete provider classes must be under the Provider:: namespace, inherit from Provider, wrap calls with with_provider_response, and raise on invalid/unavailable data

Files:

  • app/models/provider/openai.rb
  • app/models/provider/llm_concept.rb
app/**/*.rb

📄 CodeRabbit inference engine (AGENTS.md)

Place Rails application Ruby code (models, controllers, services, jobs, mailers, components) under app/

Files:

  • app/models/provider/openai.rb
  • app/models/assistant/responder.rb
  • app/models/provider/llm_concept.rb
**/*.rb

📄 CodeRabbit inference engine (AGENTS.md)

Ruby style: 2-space indentation; snake_case for methods/variables; CamelCase for classes/modules

Files:

  • app/models/provider/openai.rb
  • test/models/assistant_test.rb
  • app/models/assistant/responder.rb
  • app/models/provider/llm_concept.rb
**/*.{rb,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{rb,js,jsx,ts,tsx}: Make changes atomic, testable, and explain their impact briefly in code suggestions.
Respect existing tests and add tests when changing critical logic.

Files:

  • app/models/provider/openai.rb
  • test/models/assistant_test.rb
  • app/models/assistant/responder.rb
  • app/models/provider/llm_concept.rb
**/app/**/*.{rb,erb,js,css}

📄 CodeRabbit inference engine (CLAUDE.md)

Push Rails to its limits before adding new dependencies; a strong technical/business reason is required for new dependencies.

Files:

  • app/models/provider/openai.rb
  • app/models/assistant/responder.rb
  • app/models/provider/llm_concept.rb
**/app/models/**/*.rb

📄 CodeRabbit inference engine (CLAUDE.md)

Business logic should primarily reside in models; use concerns and POROs for organization.

Files:

  • app/models/provider/openai.rb
  • app/models/assistant/responder.rb
  • app/models/provider/llm_concept.rb
**/*.{rb,erb,haml,slim}

📄 CodeRabbit inference engine (.cursor/rules/general-rules.mdc)

**/*.{rb,erb,haml,slim}: Use Current.user for the current user; do not use current_user
Use Current.family for the current family; do not use current_family
Ignore i18n methods; hardcode strings in English for now (do not use I18n.t, t, or similar)

Files:

  • app/models/provider/openai.rb
  • test/models/assistant_test.rb
  • app/models/assistant/responder.rb
  • app/models/provider/llm_concept.rb
app/{helpers,models}/**/*.rb

📄 CodeRabbit inference engine (.cursor/rules/project-conventions.mdc)

Format currencies, numbers, and dates on the server side (Ruby) before sending to the client

Files:

  • app/models/provider/openai.rb
  • app/models/assistant/responder.rb
  • app/models/provider/llm_concept.rb
app/{models,controllers,views}/**/*.{rb,erb}

📄 CodeRabbit inference engine (.cursor/rules/project-conventions.mdc)

Avoid N+1 queries

Files:

  • app/models/provider/openai.rb
  • app/models/assistant/responder.rb
  • app/models/provider/llm_concept.rb
test/**/*_test.rb

📄 CodeRabbit inference engine (AGENTS.md)

Name Minitest files with *_test.rb and mirror the app/ structure under test/

test/**/*_test.rb: ALWAYS use Minitest + fixtures + Mocha for tests; NEVER RSpec or FactoryBot.
Use Mocha for mocking in tests when necessary.
Use VCR for external API tests.

test/**/*_test.rb: Always use Minitest for tests; do not use RSpec
Do not use factories (e.g., FactoryBot) in tests; rely on fixtures instead
For tests needing many records, use Rails helpers to construct data and inline the creation in the test
Only write tests for critical and important code paths
Avoid tests that merely verify framework/ActiveRecord behavior
Test boundaries correctly: for queries, assert returned values; for commands, assert collaborators are called with correct params
Never test the implementation details of one class in another class’s test suite
Use the mocha gem for stubs and mocks
Prefer OpenStruct for mock instances; use a mock class for complex cases
Only mock what’s necessary; don’t mock return values unless they are under test

Files:

  • test/models/assistant_test.rb
**/test/**/*.rb

📄 CodeRabbit inference engine (CLAUDE.md)

**/test/**/*.rb: ALWAYS use Minitest and fixtures for Ruby tests; NEVER RSpec or factories.
Only test critical and important code paths; system tests should be used sparingly for critical user flows.

Files:

  • test/models/assistant_test.rb
🧬 Code graph analysis (2)
app/models/provider/openai.rb (1)
app/models/provider/llm_concept.rb (1)
  • chat_response (21-33)
app/models/provider/llm_concept.rb (1)
app/models/provider/openai.rb (1)
  • chat_response (61-133)
🔇 Additional comments (11)
test/models/assistant_test.rb (3)

15-16: LGTM! Test setup correctly mirrors the production implementation.

The expected values match the implementation in app/models/assistant/responder.rb: session_id as the chat ID string and user_identifier as the SHA256 digest of the user_id.


51-52: LGTM! Assertions verify metadata propagation in basic response flow.

The test correctly asserts that session_id and user_identifier are passed through the provider.chat_response call.


105-106: LGTM! Comprehensive coverage of metadata propagation across multiple provider calls.

The assertions correctly verify that session_id and user_identifier propagate through both provider calls in the tool function sequence (initial function request + follow-up response).

Also applies to: 116-117

app/models/assistant/responder.rb (3)

70-72: LGTM! Session and user metadata correctly passed to LLM.

The new parameters are appropriately added to the chat_response call, enabling per-session tracking in Langfuse.


90-92: LGTM! Safe session ID extraction.

The safe-navigation operators correctly handle the case where chat or id might be nil.


100-102: LGTM! Appropriate memoization of chat.

Memoizing the chat reference avoids repeated database queries and is consistent with Rails conventions.

app/models/provider/llm_concept.rb (1)

21-31: LGTM! Interface signature correctly extended for session tracking.

The addition of session_id and user_identifier parameters with nil defaults maintains backward compatibility while enabling per-session tracking in concrete implementations.

app/models/provider/openai.rb (4)

61-71: LGTM! Signature correctly implements the LlmConcept interface.

The chat_response method signature matches the interface defined in app/models/provider/llm_concept.rb with the new session_id and user_identifier parameters.


110-117: LGTM! Session metadata correctly logged in streaming path.

The streaming path properly forwards session_id and user_identifier to Langfuse generation logging.


121-129: LGTM! Session metadata correctly logged in non-streaming path.

The non-streaming path properly forwards session_id and user_identifier to Langfuse generation logging.


144-165: LGTM! Langfuse integration correctly enhanced with session tracking.

The log_langfuse_generation method properly:

  • Accepts session_id and user_identifier parameters
  • Maps user_identifier to user_id for Langfuse API
  • Includes metadata in both trace() and generation() calls
  • Maintains existing error handling

@jjmata
Copy link
Collaborator Author

jjmata commented Oct 1, 2025

@coderabbitai generate docstrings

@coderabbitai
Copy link

coderabbitai bot commented Oct 1, 2025

✅ Actions performed

Docstrings generation started.

coderabbitai bot added a commit that referenced this pull request Oct 1, 2025
Docstrings generation was requested by @jjmata.

* #174 (comment)

The following files were modified:

* `app/models/assistant/responder.rb`
* `app/models/provider/llm_concept.rb`
* `app/models/provider/openai.rb`
@coderabbitai
Copy link

coderabbitai bot commented Oct 1, 2025

Note

Generated docstrings for this pull request at #175

coderabbitai bot added a commit that referenced this pull request Oct 1, 2025
Docstrings generation was requested by @jjmata.

* #174 (comment)

The following files were modified:

* `app/models/assistant/responder.rb`
* `app/models/provider/llm_concept.rb`
* `app/models/provider/openai.rb`
@coderabbitai
Copy link

coderabbitai bot commented Oct 1, 2025

Note

Generated docstrings for this pull request at #176

@jjmata jjmata merged commit cbc653a into main Oct 1, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex Touched by OpenAI Codex somehow

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants