Skip to content

Commit ae54b2b

Browse files
authored
Merge branch 'mongodb-developer:main' into RealtimeVoiceTS
2 parents 03c8af6 + d276d35 commit ae54b2b

File tree

125 files changed

+9138
-56
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+9138
-56
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ As you work through these examples, if you encounter any problems, please [open
3838

3939
* [AI Learning Hub](https://www.mongodb.com/resources/use-cases/artificial-intelligence)
4040
* [GenAI Community Forum](https://www.mongodb.com/community/forums/c/generative-ai/162)
41+
* [Tutorials and code examples from our official docs](https://github.com/mongodb/docs-notebooks)

apps/mongo-feed/.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
.env
3+
.env.local
4+
package-lock.json
5+
.next

apps/mongo-feed/README.md

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# MongoFeed
2+
3+
MongoFeed is a comprehensive platform for product feedback analysis and sentiment tracking. It leverages MongoDB for data storage and Amazon Bedrock for AI-powered sentiment analysis, providing valuable insights into customer feedback and product reviews.
4+
5+
> ♥️ Inpired by a customer success story : [Syncly](https://www.mongodb.com/customers/syncly)
6+
7+
## Hosted Version
8+
9+
https://mongo-feed.vercel.app
10+
11+
## Features
12+
13+
- File upload for product feedback analysis (JSON, HTML, images)
14+
- Chat paste functionality for direct input of customer interactions
15+
- Sentiment analysis using Amazon Bedrock AI
16+
- Real-time processing queue for feedback analysis
17+
- Interactive charts and visualizations:
18+
- Feedback trends over time
19+
- Sentiment distribution
20+
- Top issues identification
21+
- Agent performance tracking and sentiment analysis
22+
23+
## Prerequisites
24+
25+
Before you begin, ensure you have the following installed:
26+
- Node.js (v14 or later)
27+
- npm (v6 or later)
28+
- MongoDB (6.0+)
29+
- An AWS account with access to Amazon Bedrock and Claude 3.5 V2 model
30+
31+
## Installation
32+
33+
1. **Clone the repository:**
34+
```bash
35+
git clone <repository-url>
36+
cd mongo-feed
37+
```
38+
39+
2. **Install dependencies:**
40+
```bash
41+
npm install
42+
```
43+
44+
3. **Configure environment variables:**
45+
- Create a `.env.local` file in the root directory.
46+
- Add your MongoDB connection string and AWS Bedrock credentials.
47+
```env
48+
MONGODB_URI=your_mongodb_connection_string
49+
AWS_REGION=your_aws_region
50+
AWS_ACCESS_KEY_ID=your_aws_access_key_id
51+
AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key
52+
```
53+
**Note:** Ensure you have the necessary permissions for Amazon Bedrock and MongoDB.
54+
55+
## Development
56+
57+
1. **Run the development server:**
58+
```bash
59+
npm run dev
60+
```
61+
Open [http://localhost:3000](http://localhost:3000) in your browser to view the application.
62+
63+
## Building for Production
64+
65+
1. **Build the application:**
66+
```bash
67+
npm run build
68+
```
69+
70+
2. **Start the production server:**
71+
```bash
72+
npm run start
73+
```
74+
75+
## Usage
76+
77+
To use MongoFeed:
78+
79+
1. **Access the application** in your browser at [http://localhost:3000](http://localhost:3000) after running the development or production server.
80+
2. **Upload Feedback Files or Paste Chat Interactions:**
81+
- Navigate to the feedback input section.
82+
- Choose to upload files (JSON, HTML, images) or paste text from chat interactions.
83+
- Follow the on-screen instructions to input your feedback data.
84+
3. **View Sentiment Analysis Results and Visualizations:**
85+
- Once the feedback is processed, navigate to the dashboard.
86+
- Explore interactive charts and visualizations to understand:
87+
- Feedback trends over time
88+
- Sentiment distribution across feedback
89+
- Top issues identified from the feedback
90+
4. **Navigate the Dashboard:**
91+
- Use the dashboard to access different features, such as:
92+
- Real-time processing queue monitoring.
93+
- Agent performance tracking and sentiment analysis (if applicable).
94+
- Detailed views of individual feedback entries and their sentiment analysis.
95+
96+
## Configuration
97+
98+
- **Environment Variables:**
99+
- `MONGODB_URI`: MongoDB connection string for your MongoDB database.
100+
- `AWS_REGION`: AWS region where your Bedrock service is configured.
101+
- `AWS_ACCESS_KEY_ID`: AWS access key ID for authentication.
102+
- `AWS_SECRET_ACCESS_KEY`: AWS secret access key for authentication.
103+
104+
- **Other configurations:**
105+
- The application may have additional configurations that can be set in the `.env.local` file or through the application's settings panel. Refer to the application documentation for advanced configuration options.
106+
107+
## Contributing
108+
109+
If you'd like to contribute to MongoFeed, please follow these guidelines:
110+
1. Fork the repository.
111+
2. Create a branch for your feature or bug fix.
112+
3. Ensure your code adheres to the project's coding standards.
113+
4. Submit a pull request with a clear description of your changes.
114+
115+
## License
116+
117+
[Specify the project license, e.g., MIT License]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { NextResponse } from "next/server"
2+
import clientPromise from "@/lib/mongodb"
3+
4+
export const dynamic = "force-dynamic"
5+
export const revalidate = 0
6+
7+
export async function GET() {
8+
try {
9+
const client = await clientPromise
10+
const db = client.db("mongofeed")
11+
12+
const agentAnalysis = await db
13+
.collection("chat_analyses")
14+
.aggregate([
15+
{ $unwind: "$messages" },
16+
{ $match: { "messages.role": "Agent" } },
17+
{
18+
$group: {
19+
_id: "$messages.agentName",
20+
positiveSentiment: { $sum: { $cond: [{ $eq: ["$messages.sentiment", "positive"] }, 1, 0] } },
21+
neutralSentiment: { $sum: { $cond: [{ $eq: ["$messages.sentiment", "neutral"] }, 1, 0] } },
22+
negativeSentiment: { $sum: { $cond: [{ $eq: ["$messages.sentiment", "negative"] }, 1, 0] } },
23+
totalInteractions: { $sum: 1 },
24+
},
25+
},
26+
{
27+
$project: {
28+
agentName: "$_id",
29+
positiveSentiment: 1,
30+
neutralSentiment: 1,
31+
negativeSentiment: 1,
32+
totalInteractions: 1,
33+
_id: 0,
34+
},
35+
},
36+
{ $sort: { totalInteractions: -1 } },
37+
])
38+
.toArray()
39+
40+
return NextResponse.json(agentAnalysis)
41+
} catch (error) {
42+
console.error("Error fetching agent analysis:", error)
43+
return NextResponse.json({ error: "An error occurred while fetching agent analysis." }, { status: 500 })
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { NextResponse } from "next/server"
2+
import clientPromise from "@/lib/mongodb"
3+
4+
export const dynamic = "force-dynamic"
5+
export const revalidate = 0
6+
7+
export async function GET() {
8+
try {
9+
const client = await clientPromise
10+
const db = client.db("mongofeed")
11+
12+
// First get all agents with their sentiment data
13+
const agentData = await db
14+
.collection("agent_sentiment")
15+
.aggregate([
16+
{
17+
$lookup: {
18+
from: "chat_analyses",
19+
let: { agentName: "$agentName" },
20+
pipeline: [
21+
{
22+
$match: {
23+
$expr: { $eq: ["$analysis.agentName", "$$agentName"] },
24+
},
25+
},
26+
{ $sort: { createdAt: -1 } },
27+
{ $limit: 5 },
28+
{
29+
$project: {
30+
id: { $toString: "$_id" },
31+
date: "$createdAt",
32+
summary: "$analysis.summary",
33+
sentiment: "$analysis.overallSentiment",
34+
issues: "$analysis.mainTopics",
35+
},
36+
},
37+
],
38+
as: "recentChats",
39+
},
40+
},
41+
{ $sort: { totalInteractions: -1 } },
42+
])
43+
.toArray()
44+
45+
return NextResponse.json(agentData)
46+
} catch (error) {
47+
console.error("Error fetching agent sentiment:", error)
48+
return NextResponse.json({ error: "An error occurred while fetching agent sentiment." }, { status: 500 })
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { type NextRequest, NextResponse } from "next/server"
2+
import { analyzeAgentFeedback, analyzeProductReview } from "@/lib/analyze-content"
3+
import clientPromise from "@/lib/mongodb"
4+
5+
export const dynamic = "force-dynamic"
6+
export const runtime = "nodejs"
7+
8+
export async function POST(req: NextRequest) {
9+
try {
10+
const formData = await req.formData()
11+
const file = formData.get("file") as File
12+
const type = formData.get("type") as string
13+
14+
if (!file) {
15+
return NextResponse.json({ error: "No file uploaded" }, { status: 400 })
16+
}
17+
18+
const contentType = file.type
19+
const fileName = file.name
20+
21+
let content: string | ArrayBuffer
22+
if (contentType.startsWith("image/")) {
23+
content = await file.arrayBuffer()
24+
} else {
25+
const buffer = await file.arrayBuffer()
26+
content = new TextDecoder().decode(buffer)
27+
}
28+
29+
let analysisResult
30+
31+
if (type === "agent") {
32+
analysisResult = await analyzeAgentFeedback(content as string)
33+
} else if (type === "product") {
34+
analysisResult = await analyzeProductReview(content, contentType, fileName)
35+
} else {
36+
return NextResponse.json({ error: "Invalid analysis type" }, { status: 400 })
37+
}
38+
39+
// Store the analysis result in MongoDB
40+
const client = await clientPromise
41+
const db = client.db("mongofeed")
42+
await db.collection("chat_analyses").insertOne({
43+
type,
44+
contentType,
45+
fileName,
46+
analysis: analysisResult,
47+
createdAt: new Date(),
48+
})
49+
50+
return NextResponse.json({ sentiments: analysisResult })
51+
} catch (error) {
52+
console.error("Error analyzing feedback:", error)
53+
return NextResponse.json({ error: "An error occurred while analyzing feedback." }, { status: 500 })
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
import { bedrock } from '@/lib/bedrock';
3+
import { generateText } from 'ai';
4+
5+
export async function POST(req: NextRequest) {
6+
try {
7+
const data = await req.json();
8+
const documents = data.documents;
9+
10+
if (!Array.isArray(documents)) {
11+
return NextResponse.json({ error: 'Invalid input. Expected an array of documents.' }, { status: 400 });
12+
}
13+
14+
const sentiments = await Promise.all(
15+
documents.map(async (doc) => {
16+
try {
17+
const { text } = await generateText({
18+
model: bedrock('aanthropic.claude-3-5-sonnet-20241022-v2:0'),
19+
prompt: `Analyze the sentiment of the following text and respond with only one word: "positive", "negative", or "neutral". Text: "${doc}"`,
20+
});
21+
return text.trim().toLowerCase();
22+
} catch (error) {
23+
console.error('Error analyzing individual document:', error);
24+
return 'error';
25+
}
26+
})
27+
);
28+
29+
return NextResponse.json({ sentiments });
30+
} catch (error) {
31+
console.error('Error analyzing sentiment:', error);
32+
return NextResponse.json({ error: 'An error occurred while analyzing sentiment.' }, { status: 500 });
33+
}
34+
}

0 commit comments

Comments
 (0)