Skip to content

feat: add conversation analysis workflow#430

Closed
satra wants to merge 1 commit into
mainfrom
codex/conversation-analysis-features
Closed

feat: add conversation analysis workflow#430
satra wants to merge 1 commit into
mainfrom
codex/conversation-analysis-features

Conversation

@satra

@satra satra commented Mar 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add a new Zoom-oriented conversation analysis workflow that composes diarization, ASR, acoustic features, linguistic heuristics, engagement markers, optional emotion/embedding/PPG outputs, and automated step checks
  • add a design doc with the implementation plan, task checklist, testing strategy, and GPU follow-up notes
  • add CPU-safe workflow tests built with mocks and export the workflow lazily from the audio workflows package

Testing

  • MPLCONFIGDIR=.matplotlib XDG_CACHE_HOME=.cache .venv/bin/ruff check src/senselab/audio/workflows/conversation_analysis.py src/senselab/audio/workflows/init.py src/tests/audio/workflows/conversation_analysis_test.py
  • MPLCONFIGDIR=.matplotlib XDG_CACHE_HOME=.cache .venv/bin/python -m pytest src/tests/audio/workflows/conversation_analysis_test.py -q

Notes

  • this PR is intentionally stacked on top of enh/uv-refactor
  • full model-backed smoke tests for diarization, ASR, SER, embeddings, and PPG extraction should still be run when CUDA is available

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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!

This pull request introduces a robust and comprehensive workflow for analyzing multi-speaker conversations, particularly those from Zoom recordings. The system processes audio to provide detailed insights into speaker turns, transcription accuracy, acoustic and linguistic features, emotional states, and engagement markers. It is designed with automated checks at various stages and includes a thorough plan for its development and testing, prioritizing CPU-safe operations while preparing for future GPU-accelerated capabilities.

Highlights

  • New Conversation Analysis Workflow: Added a new Zoom-oriented conversation analysis workflow that integrates diarization, ASR, acoustic features, linguistic heuristics, engagement markers, and optional emotion/embedding/PPG outputs.
  • Design Documentation: Included a detailed design document outlining the implementation plan, task checklist, testing strategy, and considerations for GPU usage.
  • CPU-Safe Testing: Implemented CPU-safe workflow tests utilizing mocks to ensure functionality without requiring heavy model dependencies.
  • Lazy Workflow Export: Modified the audio workflows package to lazily export the new conversation analysis workflow, alongside the existing conversation exploration workflow.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • docs/conversation-analysis-workflow-plan.md
    • Added a detailed plan for the conversation analysis workflow, outlining its goals, reusable capabilities, proposed processing stages, output structure, TDD implementation plan, testing strategy, key design decisions, and potential risks.
  • src/senselab/audio/workflows/init.py
    • Modified the __init__.py to lazily import and export the new analyze_conversation_recordings function from conversation_analysis.py.
    • Updated the import of explore_conversation to also be a lazy export.
  • src/senselab/audio/workflows/conversation_analysis.py
    • Added a new module implementing the analyze_conversation_recordings function.
    • Included helper functions for audio preparation, segment collection, transcript accuracy estimation, linguistic feature extraction, dialogue act inference, engagement marker detection, lexical sentiment estimation, acoustic feature mapping, and summarization of turn-taking, speakers, transcripts, and PPG segments.
    • Implemented automated checks for recording input, preprocessing, environment, and per-turn analysis.
  • src/tests/audio/workflows/conversation_analysis_test.py
    • Added new unit tests for the _estimate_transcript_accuracy, _extract_dialogue_acts, _extract_engagement_markers, _summarize_turn_taking, and _summarize_ppg_segments helper functions.
    • Included a comprehensive integration test for the analyze_conversation_recordings workflow using mocked dependencies.
    • Added a test to ensure the workflow rejects missing input files.
Activity
  • No specific activity has been recorded for this pull request yet.
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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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 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. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

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.

@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 introduces a comprehensive conversation analysis workflow. The implementation is well-structured, with good use of lazy loading for dependencies and clear separation of concerns into helper functions. The accompanying design document and tests are also well-written. I've identified a couple of high-severity issues related to a resource leak from unmanaged temporary files and a potential crash when no transcription models are provided. I've also included some medium-severity suggestions to improve type safety and code style. Overall, this is a great addition, and addressing these points will make it more robust and maintainable.


results: List[Dict[str, Any]] = []
offset = 0
primary_model_name = next(iter(transcript_outputs.keys()))

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.

high

This line will raise a StopIteration error if transcript_outputs is an empty dictionary, which occurs if the user provides an empty list for transcription_models. This will crash the workflow. You should handle this case explicitly, for example by raising a ValueError at the beginning of the function if transcription_models is an empty list, or by adjusting the logic to produce results without transcript information.

"""Extract a mono WAV audio track from a local video recording."""
import ffmpeg

output_dir = Path(tempfile.mkdtemp(prefix="senselab-conversation-audio-"))

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.

high

The temporary directory created by tempfile.mkdtemp is never deleted, which will lead to a resource leak as temporary files accumulate. This can fill up disk space, especially with many or large video files. It's recommended to manage the lifecycle of this temporary directory. One approach is to create a single temporary directory at the beginning of the analyze_conversation_recordings workflow, pass it down to be used for all temporary files, and ensure it's cleaned up at the end. For example, you could use a try...finally block or a tempfile.TemporaryDirectory context manager if the results don't need to persist after the function returns.

Comment on lines +142 to +147
diarization_model: Optional[Any] = None, # noqa: ANN401
transcription_models: Optional[Sequence[Any]] = None, # noqa: ANN401
features_config: Optional[Dict[str, Any]] = None,
speaker_embeddings_models: Optional[Sequence[Any]] = None, # noqa: ANN401
ssl_embeddings_models: Optional[Sequence[Any]] = None, # noqa: ANN401
emotion_model: Optional[Any] = None, # noqa: ANN401

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

The use of Any for model parameters (diarization_model, transcription_models, etc.) weakens type safety and makes the code harder to understand and maintain. To improve type hinting without incurring runtime import costs, you can use typing.TYPE_CHECKING with string forward references. This will allow static type checkers to validate the model types while avoiding circular dependencies or slow imports.

You would need to add the following at the top of the file:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from senselab.utils.data_structures import SenselabModel
Suggested change
diarization_model: Optional[Any] = None, # noqa: ANN401
transcription_models: Optional[Sequence[Any]] = None, # noqa: ANN401
features_config: Optional[Dict[str, Any]] = None,
speaker_embeddings_models: Optional[Sequence[Any]] = None, # noqa: ANN401
ssl_embeddings_models: Optional[Sequence[Any]] = None, # noqa: ANN401
emotion_model: Optional[Any] = None, # noqa: ANN401
diarization_model: "Optional[SenselabModel]" = None,
transcription_models: "Optional[Sequence[SenselabModel]]" = None,
features_config: Optional[Dict[str, Any]] = None,
speaker_embeddings_models: "Optional[Sequence[SenselabModel]]" = None,
ssl_embeddings_models: "Optional[Sequence[SenselabModel]]" = None,
emotion_model: "Optional[SenselabModel]" = None,

diarization_results = diarize_audios(audios=recording_audios, model=diarization_model, device=device)
segments_info = _collect_segment_boundaries(recording_audios, diarization_results)
segmented_audios_list = extract_segments(segments_info)
flattened_segments = [segment for group in segmented_audios_list for segment in group]

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

Using a list comprehension to flatten the list of segment groups can be less efficient for very large lists compared to using itertools.chain.from_iterable. A more memory-efficient and idiomatic way to flatten a list of lists is to use this function. Since downstream functions expect a list, you can wrap it with list(). You will need to import itertools at the top of the file.

Suggested change
flattened_segments = [segment for group in segmented_audios_list for segment in group]
flattened_segments = list(itertools.chain.from_iterable(segmented_audios_list))

@satra
satra changed the base branch from enh/uv-refactor to main March 13, 2026 11:58
@satra

satra commented Apr 25, 2026

Copy link
Copy Markdown
Collaborator Author

Closing — superseded by the explore_conversation workflow and new tutorials (PRs #460, #462).

@satra satra closed this Apr 25, 2026
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