Skip to content

Merging feat/full stack into main#37

Merged
xenoblade246 merged 15 commits intomainfrom
feat/full-stack
Jun 19, 2025
Merged

Merging feat/full stack into main#37
xenoblade246 merged 15 commits intomainfrom
feat/full-stack

Conversation

@xenoblade246
Copy link
Copy Markdown
Collaborator

No description provided.

@xenoblade246 xenoblade246 merged commit e313a29 into main Jun 19, 2025
1 check passed
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

Summary of Changes

Hello @ThePrunerator, 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 complete full-stack application for audio transcription and summarization. It includes a React frontend for user interaction and a FastAPI backend for processing audio files and managing transcriptions. The application allows users to upload audio, view transcriptions, and manage historical data, providing a comprehensive solution for meeting memo creation.

Highlights

  • Full-Stack Implementation: This PR merges the full-stack application, including a React frontend and a FastAPI backend, into the main branch.
  • Audio Transcription: The application now supports audio uploads to the backend, which are then transcribed and output to the user.
  • Historical Transcriptions: Users can now view all stored transcriptions from the past and expand them to display the transcribed text.
  • Backend API: The FastAPI backend includes endpoints for uploading, transcribing, deleting, and summarizing audio files.
  • Frontend UI: The React frontend provides a user interface for uploading audio files, viewing transcriptions, and managing historical data.
  • Docker Configuration: The Dockerfile for the backend has been updated to include necessary dependencies and use uv for package management.
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.

Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

Code Review

The pull request introduces a full-stack structure with a React frontend and FastAPI backend, enabling audio transcription and summarization. Key changes include setting up routing in the frontend, implementing file upload, recording, listing, viewing details, and deletion functionalities, and updating the backend Dockerfile and main application file. Several areas for improvement were identified, particularly regarding error handling, state management in the frontend, and consistency in the backend API.

Comment thread frontend/src/Home.js
Comment thread app.py


@app.delete("/jobs/{uuid}")
async def delete_item(uuid: int) -> dict[str, str]:
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 UUID parameter here is typed as int, while in other routes (/jobs/{uuid}/filename, /jobs/{uuid}/transcript, /jobs/{uuid}/summarise) it is typed as str. This inconsistency can lead to unexpected type errors or incorrect routing. It should be consistent across all routes that use a UUID.

Suggested change
async def delete_item(uuid: int) -> dict[str, str]:
async def delete_item(uuid: str) -> dict[str, str]:

Comment thread frontend/src/JobDetail.js
Comment on lines +27 to +30
.catch((err) => {
setSummary("Error fetching summary.");
setIsSummarizing(false);
});
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 isSummarizing state is not set back to false in the .catch block of the fetchSummary function. If the summarization request fails, the loading spinner will remain visible indefinitely. Ensure setIsSummarizing(false) is called in the catch block.

      .catch((err) => {
        console.error("Error fetching summary:", err);
        setSummary("Error fetching summary.");
        setIsSummarizing(false);
      });

Comment thread app.py
Comment on lines +1 to +128
from fastapi import FastAPI, UploadFile, File
import time

app = FastAPI()

@app.get("/jobs/{uuid}/filename")
async def get_file_name(uuid: str) -> dict[str, str]:
"""
Returns the filename associated with a given UUID.
"""
csv_list = {
"1": "file_1",
"2": "file_2",
"3": "file_3",
"4": "file_4",
"5": "file_5"
}

if uuid in csv_list:
return {"name": csv_list[uuid]}
return {"error": "UUID not found"}


@app.get("/jobs")
async def check_files() -> dict[str, dict[str, str]]:
"""
Dummy route to return a JSON response including a list of strings.
"""
return {
"csv_list":
{
"1": "file_1",
"2": "file_2",
"3": "file_3",
"4": "file_4",
"5": "file_5"
}
}


@app.post("/jobs")
async def transcribe(file: UploadFile = File(...)) -> dict[str, str | list[dict[str, str]]]:
"""
Dummy function to transcribe input audio file.
"""
time.sleep(3)
dummy_transcription = [
{"Customer": "Hi, I'm having trouble connecting to the internet."},
{"Support Agent": "I'm sorry to hear that. Can you tell me if any of the router lights are blinking red?"},
{"Customer": "Yes, the one labeled 'WAN' is flashing red."},
{"Support Agent": "Alright. That usually means the router isn't detecting a signal. Let's try restarting it first."},
{"Customer": "Okay, I've unplugged it and plugged it back in."},
{"Support Agent": "Great. Let's give it a minute... Are the lights back to normal now?"},
{"Customer": "Yes, they're all green now!"},
{"Support Agent": "Perfect. You should be back online. Is everything working on your end?"},
{"Customer": "Yes, thank you so much for your help!"},
{"Support Agent": "You're very welcome. Have a great day!"}
]

return {
"uuid": "1",
"file_name": "new_file",
"transcript": dummy_transcription
}


@app.delete("/jobs/{uuid}")
async def delete_item(uuid: int) -> dict[str, str]:
uuid_files = {
1: "file_1",
2: "file_2",
3: "file_3",
4: "file_4",
5: "file_5"
}
return {"status": "success", "message": f"Job with UUID {uuid} and file {uuid_files[uuid]} deleted successfully."}


@app.get("/jobs/{uuid}/transcript")
async def get_file_transcript(uuid: str) -> dict[str, list[dict[str, str]]]:
"""
Gets the transcription contents from the file.
"""
dummy_transcripts = {
"1": [
{"Speaker 1": "Good morning, everyone. Let's begin with the project updates."},
{"Speaker 2": "Sure. We've completed the initial design phase and are moving into development."},
{"Speaker 1": "Excellent. Any blockers or concerns we should address now?"},
{"Speaker 3": "Not at the moment, but we'll need additional resources by next sprint."}
],
"2": [
{"Interviewer": "Can you tell me about a time you handled a challenging situation at work?"},
{"Candidate": "Yes, there was a time we had to deliver a project in half the usual time. I reorganized our workflow and prioritized key features."},
{"Interviewer": "Impressive. What was the result?"},
{"Candidate": "We launched on time and received positive feedback from the client."}
],
"3": [
{"Professor": "Today, we're going to explore the principles of quantum mechanics."},
{"Student": "Is this related to what we covered in thermodynamics?"},
{"Professor": "That's a great question. There are connections, but the foundational principles are quite different."}
],
"4": [
{"Host": "Welcome back to TechTalk Weekly. I'm your host, Jamie."},
{"Guest": "Thanks for having me, Jamie. Excited to dive into today's topic."},
{"Host": "Let's start with AI and privacy concerns. What's your take?"},
{"Guest": "It's a big issue. Transparency and data control need to be built into systems by default."}
],
"5": [
{"Alex": "Hey, did you watch the match last night?"},
{"Jordan": "Yeah! It was intense. That last-minute goal was wild."},
{"Alex": "I know, right? Totally unexpected turn."}
]
}

return {"result": dummy_transcripts[uuid]}

@app.post("/jobs/{uuid}/summarise")
def summarise_job(uuid: str) -> dict:
"""
Dummy function to summarise transcription result
with the help of an LLM.
"""
time.sleep(3)

return {
"status": "success",
"summary": "The quick brown fox jumps over the lazy dog."
} No newline at end of file
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 file appears to contain dummy API routes that duplicate functionality present in backend/main.py. Having two separate FastAPI applications or sets of routes serving similar purposes is confusing and likely unintended. It seems this file might have been a placeholder during development and should not be merged into the main branch alongside the actual backend implementation.

Comment thread frontend/src/Home.js
Comment on lines +138 to +139
setLoading(false);
if (data.uuid) summarizeTranscript(data.uuid);
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

Similar to the recording logic, the loading state is not reset to false in the .then block after a successful upload and transcription. It is only reset in the .catch block. This means the loading indicator will not disappear if the upload/transcription succeeds but summarization fails.

      setTranscription(Array.isArray(data.transcript) ? data.transcript : []);
      if (data.uuid) {
        await summarizeTranscript(data.uuid);
      }
      setLoading(false);
    })

Comment thread frontend/src/Home.js
return updated;
});
})
.catch(err => console.error("Failed to delete file:", err));
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

Error handling for the delete operation also only logs to the console. Displaying a user-friendly message in the UI upon deletion failure would be beneficial.

Comment thread frontend/src/Home.js
Comment on lines +142 to +145
.catch(err => {
console.error("Failed to fetch transcription:", err);
setLoading(false);
});
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

Error handling for the upload operation only logs to the console. Displaying a user-friendly message in the UI upon upload/transcription failure would be beneficial.

Comment thread backend/Dockerfile

# Install system packages, Rust + uv, and audio tools
RUN apt-get update && \
apt-get install -y curl build-essential gcc ffmpeg libsndfile1 bash && \
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

Installing build-essential and gcc adds significant size to the Docker image. While necessary for compiling some dependencies, consider if these are strictly required at runtime or if dependencies can be installed from pre-built wheels. If they are only needed for the build stage, consider a multi-stage build to keep the final image smaller.

Comment thread frontend/src/JobDetail.js
setFileName(data.name);
}
})
.catch(err => console.error("Failed to fetch file name:", err));
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

Error handling for fetching the file name only logs to the console. Consider displaying a message in the UI if the file name cannot be retrieved.

Comment thread frontend/src/JobDetail.js
)}
</div>

<a href="/" className="button-link">Back to home</a>
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 standard <a> tag with href="/" for internal navigation within a React Router application causes a full page reload. For client-side routing, use the <Link> component from react-router-dom or the useNavigate hook.

<Link to="/" className="button-link">Back to home</Link>

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