Skip to content

fix: prevent duplicate Task and Response display when using litellm with memory#613

Merged
MervinPraison merged 1 commit into
mainfrom
claude/issue-612-20250605_213542
Jun 6, 2025
Merged

fix: prevent duplicate Task and Response display when using litellm with memory#613
MervinPraison merged 1 commit into
mainfrom
claude/issue-612-20250605_213542

Conversation

@MervinPraison

@MervinPraison MervinPraison commented Jun 6, 2025

Copy link
Copy Markdown
Owner

User description

Fixes #612

Summary

This PR fixes the duplicate Task and Response printing issue when using litellm with memory in PraisonAI agents.

Root Cause

The issue occurred because both the Agent class and LLM class were independently calling display_interaction() when using custom LLM instances with memory:

  1. Agent.chat()_chat_completion()llm.get_response()
  2. llm.get_response() calls display_interaction() internally
  3. After getting response, Agent.chat() calls display_interaction() again

Solution

Implemented a minimal fix with backward compatibility:

  • Added display_interaction parameter to LLM.get_response() method (default: True)
  • Updated all internal display_interaction() calls in LLM class to respect this parameter
  • Modified agent calls to pass display_interaction=False when using custom LLM instances

Changes

  • llm.py:293: Added display_interaction: bool = True parameter
  • llm.py: Updated ~20 display calls to check verbose and display_interaction
  • agent.py:924, 941, 1114, 1388: Added display_interaction=False to LLM calls

Backward Compatibility

This change maintains full backward compatibility as the new parameter defaults to True.

Generated with Claude Code


PR Type

Bug fix, Enhancement


Description

  • Prevent duplicate Task and Response display in agent-LLM interactions

    • Added display_interaction parameter to LLM.get_response() and related methods
    • Updated all internal LLM display calls to respect this parameter
    • Modified agent calls to pass display_interaction=False when using custom LLMs
  • Maintains backward compatibility with default display behavior


Changes walkthrough 📝

Relevant files
Bug fix
agent.py
Prevent duplicate display by disabling agent-side interaction display

src/praisonai-agents/praisonaiagents/agent/agent.py

  • Passes display_interaction=False to LLM get_response() calls in four
    locations
  • Ensures agent does not redundantly display interactions when LLM
    handles it
  • +8/-4     
    Enhancement
    llm.py
    Add display_interaction flag and update display logic in LLM

    src/praisonai-agents/praisonaiagents/llm/llm.py

  • Adds display_interaction parameter (default True) to get_response()
    and related methods
  • Updates all internal display calls to check both verbose and
    display_interaction
  • Ensures only one display per interaction, fixing duplicate output
  • Applies change to both sync and async LLM response methods
  • +11/-10 

    Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • Summary by CodeRabbit

    • New Features
      • Added an option to control the display of interaction details during AI responses, allowing users to suppress or show interaction outputs based on preference. Interaction details are now hidden by default in certain scenarios.
    • Behavior Changes
      • Interaction display in AI responses is now gated by both verbosity and the new display setting, providing more granular control over output visibility.

    …ith memory
    
    - Add display_interaction parameter to LLM.get_response() method (default: True)
    - Update all internal display_interaction calls in LLM class to respect new parameter  
    - Modify agent calls to pass display_interaction=False when using custom LLM instances
    - Maintains backward compatibility while fixing duplicate displays (fixes #612)
    
    Co-authored-by: MervinPraison <MervinPraison@users.noreply.github.com>
    @coderabbitai

    coderabbitai Bot commented Jun 6, 2025

    Copy link
    Copy Markdown
    Contributor

    Caution

    Review failed

    The pull request is closed.

    Walkthrough

    A new boolean parameter display_interaction is introduced to the LLM response methods, defaulting to True. Internal agent logic now explicitly sets display_interaction=False when calling these methods, gating all interaction display output on this flag in addition to the existing verbose flag. No other logic or signatures are changed.

    Changes

    File(s) Change Summary
    src/praisonai-agents/praisonaiagents/llm/llm.py Added display_interaction param (default True) to LLM response methods; gated display logic on it.
    src/praisonai-agents/praisonaiagents/agent/agent.py Set display_interaction=False in all internal calls to LLM response methods.

    Sequence Diagram(s)

    sequenceDiagram
        participant Agent
        participant LLM
    
        Agent->>LLM: get_response(..., display_interaction=False)
        alt display_interaction == False
            LLM-->>LLM: Skip interaction display
        else display_interaction == True and verbose == True
            LLM-->>LLM: Display interaction output
        end
        LLM-->>Agent: Return response
    
    Loading

    Assessment against linked issues

    Objective Addressed Explanation
    Prevent duplicate Task/Response output when using litellm with memory (#612)
    Ensure fix is minimal and targeted, preserving all other verbose/debug logging (#612)
    Gate display logic to prevent double printing without disabling debug info (#612)
    Do not alter public signatures or unrelated logic (#612)

    Suggested labels

    codex

    Poem

    In the warren of code, a fix hops in,
    No more echoes, no double din.
    With a flag set low, the output’s neat,
    Only one Task, one Response to greet.
    The console’s calm, the logs are bright—
    This rabbit’s patch makes it just right! 🐇✨


    📜 Recent review details

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

    📥 Commits

    Reviewing files that changed from the base of the PR and between 1ff46bc and a90c306.

    📒 Files selected for processing (2)
    • src/praisonai-agents/praisonaiagents/agent/agent.py (4 hunks)
    • src/praisonai-agents/praisonaiagents/llm/llm.py (8 hunks)
    ✨ Finishing Touches
    • 📝 Generate Docstrings

    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
    🪧 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.
      • Explain this complex logic.
      • 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 explain this code block.
      • @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 explain its main purpose.
      • @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.

    Support

    Need 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)

    • @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.
    • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
    • @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.

    @qodo-code-review

    Copy link
    Copy Markdown

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Conditional Logic

    The changes in lines 458-466 replace an if/else with if/elif, which could potentially change behavior if both conditions were previously meant to execute independently. Verify this is the intended behavior.

    if verbose and display_interaction and reasoning_content:
        display_interaction(
            original_prompt,
            f"Reasoning:\n{reasoning_content}\n\nAnswer:\n{response_text}",
            markdown=markdown,
            generation_time=time.time() - current_time,
            console=console
        )
    elif verbose and display_interaction:

    @gemini-code-assist gemini-code-assist Bot left a comment

    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

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

    Hello @MervinPraison, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

    Summary of Changes

    Hello! Gemini here, providing a summary of this pull request to help everyone quickly understand the changes.

    This PR addresses an issue where using LiteLLM with memory in PraisonAI agents resulted in duplicate display of the agent's 'Task' and 'Response' in the console. The root cause was identified as both the Agent class and the LLM class independently calling the display_interaction() function when a custom LLM instance (like one configured with LiteLLM and memory) was used.

    The solution implemented is a minimal fix that maintains backward compatibility. It involves adding a new boolean parameter, display_interaction, to the LLM.get_response() and LLM.get_response_async() methods, defaulting to True. The internal calls to display_interaction() within the LLM class are updated to respect this new parameter. Finally, the agent's calls to the LLM's get_response methods are modified to pass display_interaction=False when using a custom LLM, effectively preventing the LLM from displaying the interaction itself, leaving the display responsibility solely with the Agent.

    Highlights

    • Bug Fix: Fixes a bug causing duplicate 'Task' and 'Response' output when using LiteLLM with memory in agents.
    • LLM Method Update: Adds a new display_interaction boolean parameter (defaulting to True) to the LLM.get_response() and LLM.get_response_async() methods to control whether the LLM class itself displays the interaction.
    • Agent Integration: Modifies the Agent's calls to LLM methods to pass display_interaction=False when using custom LLMs, ensuring only the Agent handles the display in these cases.
    • Backward Compatibility: The changes are backward compatible due to the new parameter defaulting to True.

    Changelog

    Click here to see the changelog
    • src/praisonai-agents/praisonaiagents/agent/agent.py
      • Added display_interaction=False to the llm.get_response call within _chat_completion (line 924).
      • Added display_interaction=False to the llm.get_response call within _chat_completion (line 941).
      • Added display_interaction=False to the llm.get_response call within chat (line 1114).
      • Added display_interaction=False to the llm.get_response_async call within achat (line 1388).
    • src/praisonai-agents/praisonaiagents/llm/llm.py
      • Added display_interaction: bool = True parameter to the get_response method signature (line 293).
      • Added and display_interaction condition to the if verbose check before calling display_interaction for reasoning/answer display (line 458).
      • Added and display_interaction condition to the elif verbose check before calling display_interaction for response display (line 466).
      • Added and display_interaction condition to the if verbose check before calling display_interaction after tool calls (line 745).
      • Added and display_interaction condition to the if verbose check before calling display_interaction for JSON/Pydantic output (line 760).
      • Added and display_interaction condition to the if verbose check before calling display_interaction when not self-reflecting (line 766).
      • Added and display_interaction condition to the if verbose check before calling display_interaction after reflection attempts (line 928).
      • Added and display_interaction condition to the if verbose check before calling display_interaction for JSON/Pydantic output in get_response_async (line 1382).
      • Added and display_interaction condition to the if verbose check before calling display_interaction when not self-reflecting in get_response_async (line 1388).
      • Added and display_interaction condition to the if verbose check before calling display_interaction in the base response method (line 1718).
      • Added and display_interaction condition to the if verbose check before calling display_interaction in the base aresponse method (line 1826).
    Using Gemini Code Assist

    The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

    Invoking Gemini

    You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

    Feature Command Description
    Code Review /gemini review Performs a code review for the current pull request in its current state.
    Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
    Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
    Help /gemini help Displays a list of available commands.

    Customization

    To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

    Limitations & Feedback

    Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

    You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

    Footnotes

    1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

    @qodo-code-review

    Copy link
    Copy Markdown

    PR Code Suggestions ✨

    No code suggestions found for the PR.

    @gemini-code-assist gemini-code-assist Bot left a comment

    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

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

    Code Review

    This pull request effectively addresses the issue of duplicate Task and Response displays when using litellm with memory by introducing a display_interaction flag. The core logic change is sound, and making the default True ensures backward compatibility, which is excellent.

    However, there are a few critical issues in llm.py where the new display_interaction parameter is used in the methods get_response_async, response, and aresponse but has not been added to their respective signatures. This will likely lead to NameError exceptions at runtime. Additionally, the docstring for get_response (and consequently for the other methods once the parameter is added) should be updated to reflect this new parameter.

    Overall, the approach is good, but these critical points need to be addressed before merging.

    Summary of Findings

    • Missing display_interaction parameter in method signatures: The display_interaction parameter is used within get_response_async, response, and aresponse methods in llm.py, but it has not been added to their respective method signatures. This is critical as it will likely cause NameError exceptions.
    • Docstring Update Needed for get_response: The docstring for the get_response method in llm.py should be updated to include information about the new display_interaction parameter. This is important for maintainability and user understanding.
    • Docstring Updates for Other Affected Methods: Once the display_interaction parameter is added to the signatures of get_response_async, response, and aresponse, their docstrings will also need to be updated accordingly.

    Merge Readiness

    The pull request introduces a valuable fix for duplicate displays. However, due to the critical issues identified (missing parameters in several method signatures in llm.py), I recommend that these changes be addressed before merging. Once these are fixed, and the relevant docstrings are updated, the PR should be in good shape. As a reviewer, I am not authorized to approve pull requests, so please ensure further review and approval from authorized maintainers after addressing the feedback.

    self.chat_history.append({"role": "user", "content": original_prompt})
    self.chat_history.append({"role": "assistant", "content": response_text})
    if verbose:
    if verbose and display_interaction:

    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

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

    critical

    The display_interaction variable is used in this conditional, but it doesn't appear to be defined as a parameter in the get_response_async method's signature (see full file, signature starts around line 950). It's also not explicitly extracted from **kwargs within the method body.

    This will likely cause a NameError when get_response_async is called.

    To ensure this method functions correctly and consistently with get_response, should display_interaction: bool = True be added to the get_response_async method signature? The PR description mentions that the change applies to 'related methods', which implies get_response_async should have this parameter explicitly.

    If it were intended to be passed via kwargs (though less ideal for clarity), it would need to be accessed like display_interaction = kwargs.get('display_interaction', True) at the beginning of the method.

    response_text = response.choices[0].message.content.strip()

    if verbose:
    if verbose and display_interaction:

    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

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

    critical

    Similar to get_response_async, the display_interaction variable is used here in the response method, but it's not defined in its signature (see full file, signature starts around line 1638). This is likely to cause a NameError.

    For consistency and correctness, should display_interaction: bool = True be added to the response method's signature? This would align with the changes made to get_response and the intent described in the PR.

    response_text = response.choices[0].message.content.strip()

    if verbose:
    if verbose and display_interaction:

    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

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

    critical

    The display_interaction variable is used here within the aresponse method, but it's missing from the method's signature (see full file, signature starts around line 1746). This will likely lead to a NameError at runtime.

    To fix this and maintain consistency with get_response, could we add display_interaction: bool = True to the aresponse method's signature?

    agent_role: Optional[str] = None,
    agent_tools: Optional[List[str]] = None,
    execute_tool_fn: Optional[Callable] = None,
    display_interaction: bool = True,

    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

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

    medium

    It's great that you've added the display_interaction parameter with a default value for backward compatibility!

    To help users and maintainers understand this new parameter, could we update the docstring for get_response (lines 296-...) to include a description of display_interaction, its purpose, and its default value? This would improve the method's documentation and maintainability.

    @cursor cursor Bot left a comment

    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

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

    Bug: Async Method Missing Parameter

    The display_interaction parameter was added to the get_response method signature (line 293) but omitted from its asynchronous counterpart, get_response_async. The agent code calls get_response_async with display_interaction=False (e.g., agent.py line 1388), which will cause a TypeError. Additionally, the get_response_async method body uses display_interaction in conditional checks (e.g., lines 1382, 1388), leading to a NameError as the variable is undefined within the method scope.

    src/praisonai-agents/praisonaiagents/agent/agent.py#L1387-L1388

    reasoning_steps=reasoning_steps,
    display_interaction=False

    src/praisonai-agents/praisonaiagents/llm/llm.py#L1381-L1388

    self.chat_history.append({"role": "assistant", "content": response_text})
    if verbose and display_interaction:
    display_interaction(original_prompt, response_text, markdown=markdown,
    generation_time=time.time() - start_time, console=console)
    return response_text
    if not self_reflect:
    if verbose and display_interaction:

    Fix in Cursor


    BugBot free trial expires on June 11, 2025
    You have used $0.00 of your $50.00 spend limit so far. Manage your spend limit in the Cursor dashboard.

    Was this report helpful? Give feedback by reacting with 👍 or 👎

    @MervinPraison MervinPraison merged commit afa747f into main Jun 6, 2025
    11 of 16 checks passed
    shaneholloman pushed a commit to shaneholloman/praisonai that referenced this pull request Feb 4, 2026
    …612-20250605_213542
    
    fix: prevent duplicate Task and Response display when using litellm with memory
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    duplicate response when using litellm with memory

    1 participant