# Project export: MD FactFarm

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 11.0
- Tagline: Truth in the Digital Age: Mastering Information Literacy
- Devpost: https://devpost.com/software/md-factfarm
- GitHub: https://github.com/courtofdreams/md-fact-farm-api
- Demo: https://github.com/courtofdreams/md-fact-farm-extenstion
- Video: https://www.youtube.com/embed/Rcab4yp58jQ?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Result: winner (Fetch.ai: Agentic Track Prize)
- Team: 1 GitHub contributor(s) — Supakarn B (6 commits)

## Devpost submission (written by the team)

### Inspiration

Our mission is rooted in the fight against fake news, misinformation, and disinformation, which are increasingly pervasive threats in today’s digital world. As the saying goes, "the pen is mightier than the sword," which underscores the power of words and information. We aim to ensure that no one falls victim to digital deception. While technology has contributed to the spread of misinformation, we believe it can also be a powerful ally in promoting the truth. By leveraging AI for good, we aim to combat falsehoods and uphold the integrity of information. Fun fact: Moodeng is a pygmy hippopotamus born on July 10, 2024, living in Khao Kheow Open Zoo, Thailand. She became a viral internet sensation during a busy political season in the US. Amid the flood of true and half-true information, Moodeng, symbolizing purity and honesty, stood as a beacon of clarity. Like Moodeng, our tool is here to cut through the noise and keep things transparent. So, Vote for Moodeng!

### What it does

Social media platforms are now major sources of rapidly shared information. Our Chrome extension, MD FactFarm, simplifies fact-checking through AI-driven content analysis and verification. Initially focused on YouTube, our tool offers real-time fact-checking by scanning video content to identify and flag misinformation while providing reliable sources for users to verify accuracy.

### How we built it

At the core of our system is a Large Language Model (LLM) that we trained and optimized to accurately understand and interpret various forms of misinformation, powering our fact-checking capabilities. At the core of our system is a Large Language Model (LLM) that we trained and optimized to accurately understand and interpret various forms of misinformation, powering our fact-checking capabilities. We integrated an AI agent using Fetch.ai and built services and APIs to enable seamless communication with the agent. We integrated an AI agent using Fetch.ai and built services and APIs to enable seamless communication with the agent. Our front-end, built with HTML, CSS, and JavaScript, was designed and deployed as a Chrome extension. Our front-end, built with HTML, CSS, and JavaScript, was designed and deployed as a Chrome extension.

### Challenges we ran into

One of the major challenges we encountered was ensuring that the AI could accurately differentiate between fact, opinion, and misleading content. Early on, the outputs were inconsistent, making it difficult to trust the results. To achieve this, we had to rethink our approach to prompt engineering. We provided the AI with more detailed context and built a structured framework to clearly separate different types of content. Additionally, we implemented a formula for the AI to use to determine a confidence score for each output. These changes helped us generate more consistent and reliable results, enabling the AI to better recognize the subtle distinctions between fact, opinion, and misleading content. One of the major challenges we encountered was ensuring that the AI could accurately differentiate between fact, opinion, and misleading content. Early on, the outputs were inconsistent, making it difficult to trust the results. To achieve this, we had to rethink our approach to prompt engineering. We provided the AI with more detailed context and built a structured framework to clearly separate different types of content. Additionally, we implemented a formula for the AI to use to determine a confidence score for each output. These changes helped us generate more consistent and reliable results, enabling the AI to better recognize the subtle distinctions between fact, opinion, and misleading content. Another challenge was integrating multiple agent frameworks into a unified system that could operate seamlessly. Managing the intricacies of coordinating tasks and data flow between these diverse components contributed to a complex integration process. Another challenge was integrating multiple agent frameworks into a unified system that could operate seamlessly. Managing the intricacies of coordinating tasks and data flow between these diverse components contributed to a complex integration process.

### Accomplishments we're proud of

We successfully developed a Chrome extension that that provides real-time fact-checking for YouTube, empowering users to make informed decisions. We successfully developed a Chrome extension that that provides real-time fact-checking for YouTube, empowering users to make informed decisions. We crafted prompts that effectively leverage the LLM's ability to detect misinformation. We crafted prompts that effectively leverage the LLM's ability to detect misinformation. We successfully integrated Fetch.ai, utilizing agents that lay the foundation for scalability. We successfully integrated Fetch.ai, utilizing agents that lay the foundation for scalability.

### What we learned

We learned the importance of defining the problem clearly and deciding on a minimum viable product (MVP) within a limited timeframe. Additionally, we focused on framing our work to align with the AI agent framework, which has been crucial in improving our approach to misinformation detection.

### What's next

Moving forward, we plan to expand our platform to include other social networks, such as Twitter and Facebook, where misinformation spreads rapidly. We aim to gather a wider range of information sources to ensure more comprehensive fact-checking and cover more diverse content. Moreover, we are working on enhancing our AI's fact-checking mechanics, utilizing more advanced techniques to improve accuracy.

## README (from the GitHub repository)

# MD Fact Farm
Social media platforms are now major sources of rapidly shared information. Our Chrome extension, MD FactFarm, simplifies fact-checking through AI-driven content analysis and verification. Initially focused on YouTube, our tool offers real-time fact-checking by scanning video content to identify and flag misinformation while providing reliable sources for users to verify accuracy.

[Read more](https://devpost.com/software/md-factfarm?ref_content=user-portfolio&ref_feature=in_progress)
## How to start this api server locally
0. Clone the repository
1. (Optional) Create a  python virtual environment, use what ever tool you like, I use anaconda
2. Install the required packages
```bash
pip install youtube-transcript-api
pip install openai
pip install flask
pip install flask-cors
pip install uagents-ai-engine
pip install uagents
```
4. add your openai api key and youtube key to openapi_service.py file
5. run fake news agent and api server
```bash
python fakenewsagnet.py
python api.py
```
6. The server should be running on localhost:5100, please validate by visiting the url in your browser
```bash
http://localhost:5100/api/v1/is-fake-news/sAmwIKTx9hs
```

## How it works
![Image](./image.png)
- API will receive youtube video id from client, send to openai service (part of analyze service, another agents that will call uAgents) and return the result whether the video is fake news or not. 
- For now it determine if the video is fake news by pulling transcript, comments title of the video then send to uAgennts (fakenew agent) to determine if the video is fake news or not.

## Detected evidence (automated analysis)

Indexed codebase: 4 recognized source files, 8 KB.
- Python (language) — detected in the code
- CSS (language) — claimed on Devpost, not found in the code
- Flask (technology) — claimed on Devpost, not found in the code
- HTML (language) — claimed on Devpost, not found in the code
- JavaScript (language) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (4 of 4)

```
api.py
fakenewsagent.py
openai_service.py
README.md
```

### Dependencies

No dependency index available.

### Recent commits (newest first)

- fix: update readme
- fix: update readme
- fix: update readme with image
- fix: update readme
- feat: init project
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### api.py

```python
from flask import Flask, json
import openai_service
from flask_cors import CORS

api = Flask(__name__)
CORS(api)


@api.route('/api/v1/is-fake-news/<id>', methods=['GET'])
async def is_fakenews(id):
    title = openai_service.get_youtube_title(id)
    transcript = openai_service.get_youtube_transcript(id)
    comments = openai_service.get_youtube_comments(id)
    result = await openai_service.process_fakenews(title, transcript, comments)

    split_index = result.index(".") + 1
    conclusion = result[:split_index].strip()  
    reasoning = result[split_index:].strip()
    print("conclusion " + conclusion)
    is_faknews_result = { "result": conclusion.lower() == 'yes', "reason": reasoning }
    
    return json.dumps(is_faknews_result)


@api.route('/api/v1/transcript/<id>', methods=['GET'])
def get_transcript(id):
    transcript = openai_service.get_youtube_transcript(id)
    return json.dumps({ "transcript": transcript })


@api.route('/api/v1/comments/<id>', methods=['GET'])
def get_comments(id):
    comment = openai_service.get_youtube_comments(id)
    
    print(comment)

    is_fakenews_result = { "result": "\n".join(comment) }
    
    return json.dumps(is_fakenews_result)

if __name__ == '__main__':
    api.run(host='0.0.0.0',port=5100)
```

### openai_service.py

```python
from youtube_transcript_api import YouTubeTranscriptApi
from openai import OpenAI
import requests
import os
from uagents.query import query
from uagents import Model
import json
from uagents.envelope import Envelope 

## Tmr change the prompt to be more specific on fake news and determine frontend
AGENT_ADDRESS = ""

class Request(Model):
    transcript: str
    title: str
    comments: list[str]

def get_youtube_transcript(url):
    print(url)
    video_id = url.replace('https://www.youtube.com/watch?v=', '')
    transcript = YouTubeTranscriptApi.get_transcript(video_id)
    output = ''
    for x in transcript:
        sentence = x['text']
        output += f' {sentence}\n'
    return output

def get_youtube_title(url):
    video_id = url.replace('https://www.youtube.com/watch?v=', '')
    api_url = f"https://www.googleapis.com/youtube/v3/videos?id={video_id}&part=snippet&key={youtube_api_key}"
    response = requests.get(api_url)

    if response.status_code == 200:
        data = response.json()
        title = data['items'][0]['snippet']['title']
        return title
    else:
        print("Error fetching video information: ", response.status_code)
        return None

def get_youtube_comments(url):
    video_id = url.replace('https://www.youtube.com/watch?v=', '')
    api_url = f"https://www.googleapis.com/youtube/v3/commentThreads?videoId={video_id}&part=snippet&key={youtube_api_key}"
    response = requests.get(api_url)

    if response.status_code == 200:
        data = response.json()
        comments = []
    
        for item in data['items']:
            text_display = item['snippet']['topLevelComment']['snippet']['textDisplay']
            comments.append(text_display)
        return comments;    
    else:
        print("Error fetching video information: ", response.status_code)
        return None


# Function to send a query to the agent
async def agent_query(req):
    response = await query(destination=AGENT_ADDRESS, message=req, timeout=15)
    if isinstance(response, Envelope):
        data = json.loads(response.decode_payload())
        print(data)
        return data
    return response
    
async def process_fakenews(title, transcript, comments):
    print(f"processing video: {title}")
    response = await agent_query(Request(transcript=transcript, title=title, comments=comments))
    return response['text']    
```

### fakenewsagent.py

```python
"""
This agent can respond to plain text questions with data from an AI model and convert it into a machine readable format.
"""
from uagents import Agent, Context, Model
import json
import os
from openai import OpenAI

agent = Agent(
    name="your_agent_name_here",
    seed="your_agent_seed_here",
    port=8001,
    endpoint="http://localhost:8001/submit",
)

os.environ["OPENAI_API_KEY"] = "" # your openai api key
youtube_api_key = "" # your youtube api key
client = OpenAI()

class Request(Model):
    transcript: str
    title: str
    comments: list[str]

class Error(Model):
    text: str

class Data(Model):
    value: int
    unit: str
    timestamp: str
    confidence: float
    source: str
    notes: str

class Response(Model):
    text: str  


def process_fakenews(transcript: str, title: str, comments: list[str], max_tokens: int = 1024):
    """Send a prompt and context to the AI model and return the content of the completion"""

    try:
        response = client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {"role": "assistant", "content": "Determine whether the following transcript and its title are fake news. Start the answer with 'Yes.' or 'No.' first, followed by a new line and the reasoning"},
                {"role": "user", "content": f'transcript: {transcript} video title: {title} comments: {",".join(comments)}'},
            ]
        )
        message = response.choices[0].message.content
    except Exception as ex:
        print(f"An error occurred retrieving data from the OpenAI: {ex}")
        return None

    print("Got response from AI model: " + message)
    return message


def get_data(ctx: Context, request: Request):
    message_content = process_fakenews(request.transcript, request.title, request.comments, max_tokens=2048)
    try:
        msg = Response(text=message_content)
        return msg
    except Exception as ex:
        ctx.logger.exception(f"An error occurred retrieving data from the AI model: {ex}")
        return Error(text="Sorry, I wasn't able to answer your request this time. Feel free to try again.")


@agent.on_event("startup")
async def hi(ctx: Context):
    ctx.logger.info(f"Starting up {agent.name}")
    ctx.logger.info(f"With address: {agent.address}")
    ctx.logger.info(f"And wallet address: {agent.wallet.address()}")
    

@agent.on_query(model=Request, replies={Response})
async def query_handler(ctx: Context, sender: str, request: Request):
    ctx.logger.info("Query received")
    try:
        response = get_data(ctx, request) 
        ctx.logger.info(f"Response: {response}")
        await ctx.send(sender, response)
    except Exception as e:
        error_message = f"Error fetching job details: {str(e)}"
        ctx.logger.error(error_message)
        await ctx.send(sender, Error(text=str(error_message)))

if __name__ == "__main__":
    agent.run()
```