-
-
Notifications
You must be signed in to change notification settings - Fork 76
Feat/ RAG chat endpoint + Pinecone metadata fix #113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3feff7b
53a1c3b
db0520c
c53eb08
90c9dcb
ab32dda
aeb92c0
a8cc25d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,57 +3,67 @@ name: 🚀 Deploy Backend to HF Space | |
| on: | ||
| push: | ||
| branches: | ||
| - main # or your primary branch | ||
| - main | ||
| paths: | ||
| - "backend/**" # only trigger when anything under backend/ changes | ||
| - "backend/**" | ||
|
|
||
| jobs: | ||
| deploy: | ||
| runs-on: ubuntu-latest | ||
| # set your HF username here (or replace with a secret if you prefer) | ||
| env: | ||
| HF_USER: Thunder1245 | ||
| HF_REPO: perspective-backend | ||
|
|
||
| steps: | ||
| - name: 👉 Checkout code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: 🔒 Install HF CLI | ||
| run: pip install huggingface_hub | ||
|
|
||
| - name: 🔑 HF login | ||
| env: | ||
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | ||
| run: huggingface-cli login --token "$HF_TOKEN" | ||
| - name: 🔍 Ensure HF_TOKEN is set | ||
| run: | | ||
| if [ -z "${{ secrets.HF_TOKEN }}" ]; then | ||
| echo "ERROR: HF_TOKEN secret is not set. Add it in repository secrets: Settings → Secrets & variables → Actions." | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: 📂 Prepare Space repo | ||
| - name: 📂 Prepare Space repo (clone) | ||
| env: | ||
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | ||
| run: | | ||
| rm -rf space-backend | ||
| rm -rf space-backend || true | ||
| # clone using token in URL (this authenticates the clone) | ||
| git clone https://Thunder1245:${HF_TOKEN}@huggingface.co/spaces/Thunder1245/perspective-backend.git space-backend | ||
|
|
||
| - name: 📦 Install rsync | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y rsync | ||
|
|
||
| - name: 📤 Sync backend code | ||
| - name: 📤 Sync backend code to Space | ||
| env: | ||
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | ||
| run: | | ||
| set -e | ||
|
|
||
| cd space-backend | ||
|
|
||
| # Only remove tracked files (preserve .git and config) | ||
| # Remove tracked files while preserving .git and config (ignore failure) | ||
| git rm -r . || true | ||
| cd .. | ||
|
|
||
| # Copy new backend files in | ||
| # Copy backend files into the cloned space directory | ||
| cp -R backend/. space-backend/ | ||
|
|
||
|
Comment on lines
+52
to
58
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Ensure repo is fully synchronized (handle untracked files); simplify with rsync. git rm -r . won’t remove untracked files and the cp step doesn’t delete removed files. Use rsync --delete to mirror backend/ into the Space repo (excluding .git). - # Remove tracked files while preserving .git and config (ignore failure)
- git rm -r . || true
- cd ..
-
- # Copy backend files into the cloned space directory
- cp -R backend/. space-backend/
+ # Mirror backend files into the cloned space directory (preserve .git)
+ rsync -av --delete --exclude '.git' backend/ space-backend/🤖 Prompt for AI Agents |
||
| # Push new code to HF Space | ||
| # Commit & push | ||
| cd space-backend | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add --all | ||
| git commit -m "Auto‑deploy backend: ${{ github.sha }}" || echo "No changes to commit" | ||
| git commit -m "Auto-deploy backend: ${{ github.sha }}" || echo "No changes to commit" | ||
| git push origin main | ||
|
|
||
| - name: ✅ Done | ||
| run: | | ||
| echo "Backend deployed to Hugging Face Space: https://huggingface.co/spaces/${HF_USER}/${HF_REPO}" | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,15 +2,32 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### Table of Contents | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [System Overview](#system-overview) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Architecture Components](#architecture-components) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Technical Stack](#technical-stack) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Core Features](#core-features) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Data Flow & Security](#data-flow--security) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Setup & Deployment](#setup--deployment) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Detailed Architecture Diagram](#detailed-architecture-diagram) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Expected Outcomes](#expected-outcomes) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Required Skills](#required-skills) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Perspective-AI](#perspective-ai) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Table of Contents](#table-of-contents) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [System Overview](#system-overview) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [High-Level Concept](#high-level-concept) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Architecture Components](#architecture-components) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [1. Frontend Layer](#1-frontend-layer) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [3. Core Backend](#3-core-backend) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [4. AI \& NLP Integration](#4-ai--nlp-integration) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [5. Data Storage](#5-data-storage) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Technical Stack](#technical-stack) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Frontend Technologies](#frontend-technologies) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Backend Technologies](#backend-technologies) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [I Integration](#i-integration) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Core Features](#core-features) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [1. Counter-Perspective Generation](#1-counter-perspective-generation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [2. Reasoned Thinking](#2-reasoned-thinking) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [3. Updated Facts](#3-updated-facts) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [4. Seamless Integration](#4-seamless-integration) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [5. Real-Time Analysis](#5-real-time-analysis) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Data Flow \& Security](#data-flow--security) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Setup \& Deployment](#setup--deployment) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Frontend Setup](#frontend-setup) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Backend Setup](#backend-setup) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Architecture Diagram](#architecture-diagram) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Expected Outcomes](#expected-outcomes) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - [Required Skills](#required-skills) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+5
to
+30
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainFix TOC indentation and remove the stray "I Integration" item to satisfy markdownlint and avoid broken anchors Current list indentation is inconsistent (MD005/MD007), and the "I Integration" entry looks like a typo/duplicate of "AI & NLP Integration". Apply the following TOC cleanup: - - [Perspective-AI](#perspective-ai)
- - [Table of Contents](#table-of-contents)
- - [System Overview](#system-overview)
- - [High-Level Concept](#high-level-concept)
- - [Architecture Components](#architecture-components)
- - [1. Frontend Layer](#1-frontend-layer)
- - [3. Core Backend](#3-core-backend)
- - [4. AI \& NLP Integration](#4-ai--nlp-integration)
- - [5. Data Storage](#5-data-storage)
- - [Technical Stack](#technical-stack)
- - [Frontend Technologies](#frontend-technologies)
- - [Backend Technologies](#backend-technologies)
- - [I Integration](#i-integration)
- - [Core Features](#core-features)
- - [1. Counter-Perspective Generation](#1-counter-perspective-generation)
- - [2. Reasoned Thinking](#2-reasoned-thinking)
- - [3. Updated Facts](#3-updated-facts)
- - [4. Seamless Integration](#4-seamless-integration)
- - [5. Real-Time Analysis](#5-real-time-analysis)
- - [Data Flow \& Security](#data-flow--security)
- - [Setup \& Deployment](#setup--deployment)
- - [Frontend Setup](#frontend-setup)
- - [Backend Setup](#backend-setup)
- - [Architecture Diagram](#architecture-diagram)
- - [Expected Outcomes](#expected-outcomes)
- - [Required Skills](#required-skills)
+ - [Perspective-AI](#perspective-ai)
+ - [Table of Contents](#table-of-contents)
+ - [System Overview](#system-overview)
+ - [High-Level Concept](#high-level-concept)
+ - [Architecture Components](#architecture-components)
+ - [1. Frontend Layer](#1-frontend-layer)
+ - [3. Core Backend](#3-core-backend)
+ - [4. AI & NLP Integration](#4-ai--nlp-integration)
+ - [5. Data Storage](#5-data-storage)
+ - [Technical Stack](#technical-stack)
+ - [Frontend Technologies](#frontend-technologies)
+ - [Backend Technologies](#backend-technologies)
+ - [Core Features](#core-features)
+ - [1. Counter-Perspective Generation](#1-counter-perspective-generation)
+ - [2. Reasoned Thinking](#2-reasoned-thinking)
+ - [3. Updated Facts](#3-updated-facts)
+ - [4. Seamless Integration](#4-seamless-integration)
+ - [5. Real-Time Analysis](#5-real-time-analysis)
+ - [Data Flow & Security](#data-flow--security)
+ - [Setup & Deployment](#setup--deployment)
+ - [Frontend Setup](#frontend-setup)
+ - [Backend Setup](#backend-setup)
+ - [Architecture Diagram](#architecture-diagram)
+ - [Expected Outcomes](#expected-outcomes)
+ - [Required Skills](#required-skills)Notes:
Please confirm whether “I Integration” was intended to be “AI Integration” (it appears redundant with “AI & NLP Integration”). If you want it retained, update both the TOC entry and the corresponding section heading for consistency. 🏁 Script executed: #!/bin/bash
# Check for stray "I Integration" entry
grep -n "I Integration" README.md
# Print first 30 lines of README.md to inspect TOC indentation
sed -n '1,30p' README.mdLength of output: 1443 Remove stray “I Integration” entry and normalize TOC indentation
Suggested diff: --- a/README.md
+++ b/README.md
@@ -17,1 +17,0 @@
- - [I Integration](#i-integration)
@@ -75,1 +74,0 @@
-### I Integration📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.17.2)6-6: Unordered list indentation (MD007, ul-indent) 7-7: Inconsistent indentation for list items at the same level (MD005, list-indent) 9-9: Inconsistent indentation for list items at the same level (MD005, list-indent) 14-14: Inconsistent indentation for list items at the same level (MD005, list-indent) 18-18: Inconsistent indentation for list items at the same level (MD005, list-indent) 24-24: Inconsistent indentation for list items at the same level (MD005, list-indent) 25-25: Inconsistent indentation for list items at the same level (MD005, list-indent) 28-28: Inconsistent indentation for list items at the same level (MD005, list-indent) 29-29: Inconsistent indentation for list items at the same level (MD005, list-indent) 30-30: Inconsistent indentation for list items at the same level (MD005, list-indent) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -137,20 +154,25 @@ npm run dev | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - add .env file in `/new-backend`directory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - add following environment variable in your .env file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| HF_TOKEN = <Your_hugging_face_access_token> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| GROQ_API_KEY= <groq_api_key> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PINECONE_API_KEY = <your_pinecone_API_KEY> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PORT = 8000 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SEARCH_KEY = <your_Google_custom_search_engine_API_key> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+157
to
161
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainStandardize .env variable formatting and naming for clarity Make the keys consistent (no spaces around =, consistent placeholders). This also prevents copy-paste pitfalls. - GROQ_API_KEY= <groq_api_key>
-PINECONE_API_KEY = <your_pinecone_API_KEY>
-PORT = 8000
-SEARCH_KEY = <your_Google_custom_search_engine_API_key>
+GROQ_API_KEY=<GROQ_API_KEY>
+PINECONE_API_KEY=<PINECONE_API_KEY>
+PORT=8000
+SEARCH_KEY=<GOOGLE_CSE_API_KEY>
🏁 Script executed: #!/bin/bash
# Search for Pinecone usage in codebase
grep -R "pinecone" -n .
# Search for HuggingFace related usage in codebase and README
grep -R "HuggingFace" -n .
grep -R "get_huggingface_access_token" -n .Length of output: 3242 🏁 Script executed: #!/bin/bash
# Check which environment variables are used for Pinecone initialization
grep -R "os.getenv" -n backend/app/db/vector_store.py
# Preview the beginning of the file to see how Pinecone is configured
sed -n '1,200p' backend/app/db/vector_store.pyLength of output: 1289 🏁 Script executed: #!/bin/bash
# Search for GROQ usage in the codebase
grep -R "GROQ" -n .Length of output: 469 #!/bin/bash
# List all environment variables used via os.getenv across the codebase
grep -R "os.getenv" -n .
# Preview the usage of SEARCH_KEY or equivalent in get_rag_data.py
sed -n '1,200p' backend/app/modules/chat/get_rag_data.py#!/bin/bash
# Check which environment variables are used in get_rag_data.py
grep -R "os.getenv" -n backend/app/modules/chat/get_rag_data.py
# Preview the contents to see how the search key is retrieved and used
sed -n '1,200p' backend/app/modules/chat/get_rag_data.py🏁 Script executed: #!/bin/bash
# List environment variables used in get_rag_data.py
grep -R "os.getenv" -n backend/app/modules/chat/get_rag_data.py
# Show the beginning of the file for context
sed -n '1,200p' backend/app/modules/chat/get_rag_data.pyLength of output: 834 🏁 Script executed: #!/bin/bash
# Check if SEARCH_KEY or related env vars are used in the codebase
grep -R "SEARCH_KEY" -n .
grep -R "GOOGLE_CSE" -n .Length of output: 213 Standardize .env entries in README.md for consistency and accuracy Please update the README’s environment-variable block (lines 157–161) to remove extra spaces around “=”, align placeholder names with the actual keys used in code, and drop the unused HuggingFace step. No additional Pinecone or GROQ variables are required beyond File: README.md, lines 157–161 - GROQ_API_KEY= <groq_api_key>
-PINECONE_API_KEY = <your_pinecone_API_KEY>
-PORT = 8000
-SEARCH_KEY = <your_Google_custom_search_engine_API_key>
+GROQ_API_KEY=<GROQ_API_KEY>
+PINECONE_API_KEY=<PINECONE_API_KEY>
+PORT=8000
+SEARCH_KEY=<GOOGLE_CSE_API_KEY>• Remove the Get HuggingFace Access Token step (no HuggingFace calls remain in this PR). 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| *Run backend:* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cd new-backend | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cd backend | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uv sync # Creating virtual environment at: .venv | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uv run main.py #Runs the backend server | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Architecture Diagram | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ```mermaid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| graph TB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| %% Define Subgraphs with Colors and Text Styles | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -168,6 +190,7 @@ graph TB | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Analyzer[Content Analyzer] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CNEngine[Counter-Narrative Engine] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Context[Context Manager] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subgraph AI & NLP Layer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -212,7 +235,7 @@ graph TB | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Required Skills | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Frontend Development**: Experience with Next.js and modern UI frameworks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Frontend Development**: Experience with Next.js and modern UI frameworks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Backend Development**: Proficiency in Python and FastAPI. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **AI & NLP**: Familiarity with LangChain, Langgraph, and prompt engineering techniques. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Database Management**: Knowledge of vector databases system. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,57 @@ | ||||||||||||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||||||||||||
| from groq import Groq | ||||||||||||||||||||||||||||||||||||||||
| from dotenv import load_dotenv | ||||||||||||||||||||||||||||||||||||||||
| import json | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| load_dotenv() | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| client = Groq(api_key=os.getenv("GROQ_API_KEY")) | ||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Fail fast if GROQ_API_KEY is missing and use a named parameter. Avoid constructing the client with a missing/None key. Use a named argument and validate the env var. -load_dotenv()
-
-client = Groq(api_key=os.getenv("GROQ_API_KEY"))
+load_dotenv()
+api_key = os.getenv("GROQ_API_KEY")
+if not api_key:
+ raise RuntimeError("GROQ_API_KEY is not set")
+client = Groq(api_key=api_key)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| def check_bias(text): | ||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||
| print(text) | ||||||||||||||||||||||||||||||||||||||||
| print(json.dumps(text)) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+13
to
+15
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove PII logging of full article text. Printing raw article content (and its JSON) to stdout is a PII/data-leak risk and noisy in production logs. Gate behind a debug logger or remove. - print(text)
- print(json.dumps(text))
+ # Consider using a structured logger at DEBUG level if needed:
+ # logger.debug("check_bias called with text length=%d", len(text or ""))📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| if not text: | ||||||||||||||||||||||||||||||||||||||||
| raise ValueError("Missing or empty 'cleaned_text'") | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| chat_completion = client.chat.completions.create( | ||||||||||||||||||||||||||||||||||||||||
| messages=[ | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| "role": "system", | ||||||||||||||||||||||||||||||||||||||||
| "content": ( | ||||||||||||||||||||||||||||||||||||||||
| "You are an assistant that checks " | ||||||||||||||||||||||||||||||||||||||||
| "if given article is biased and give" | ||||||||||||||||||||||||||||||||||||||||
| "score to each based on biasness where 0 is lowest bias and 100 is highest bias" | ||||||||||||||||||||||||||||||||||||||||
| "Only return a number between 0 to 100 base on bias." | ||||||||||||||||||||||||||||||||||||||||
| "only return Number No Text" | ||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||
| "role": "user", | ||||||||||||||||||||||||||||||||||||||||
| "content": ( | ||||||||||||||||||||||||||||||||||||||||
| "Give bias score to the following article " | ||||||||||||||||||||||||||||||||||||||||
| f"\n\n{text}" | ||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||
| model="gemma2-9b-it", | ||||||||||||||||||||||||||||||||||||||||
| temperature=0.3, | ||||||||||||||||||||||||||||||||||||||||
| max_tokens=512, | ||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| bias_score = chat_completion.choices[0].message.content.strip() | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||
| "bias_score": bias_score, | ||||||||||||||||||||||||||||||||||||||||
| "status": "success", | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+44
to
+49
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Parse and validate numeric output; return a number type. Currently the function returns a string and trusts the model to output only a number. Parse robustly, clamp to [0,100], and return an int/float to simplify frontend usage. - bias_score = chat_completion.choices[0].message.content.strip()
-
- return {
- "bias_score": bias_score,
- "status": "success",
- }
+ raw = chat_completion.choices[0].message.content.strip()
+ # Extract first integer/float from the response
+ import re
+ m = re.search(r"(\d{1,3})(?:\.\d+)?", raw)
+ if not m:
+ raise ValueError(f"Model did not return a numeric score: {raw!r}")
+ score = int(m.group(1))
+ # Enforce bounds
+ score = max(0, min(100, score))
+ return {
+ "bias_score": score,
+ "status": "success",
+ }Note: Add 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||
| print(f"Error in bias_detection: {e}") | ||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||
| "status": "error", | ||||||||||||||||||||||||||||||||||||||||
| "error_from": "bias_detection", | ||||||||||||||||||||||||||||||||||||||||
| "message": str(e), | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,10 @@ | ||||||||||||||||||||||||||||||||||||||||
| from sentence_transformers import SentenceTransformer | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| embedder = SentenceTransformer("all-MiniLM-L6-v2") | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| def embed_query(query: str): | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| embeddings = embedder.encode(query).tolist() | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| return embeddings | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+10
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Reuse the existing embedder; add types and input validation. Avoid loading the same model twice. Import the singleton -from sentence_transformers import SentenceTransformer
-
-embedder = SentenceTransformer("all-MiniLM-L6-v2")
-
-
-def embed_query(query: str):
-
- embeddings = embedder.encode(query).tolist()
-
- return embeddings
+from typing import List
+from app.modules.vector_store.embed import embedder
+
+def embed_query(query: str) -> List[float]:
+ if not query or not query.strip():
+ raise ValueError("query must be a non-empty string")
+ embedding = embedder.encode(query).tolist()
+ # Optionally: normalize if index uses cosine similarity without normalized vectors
+ return embedding📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| from pinecone import Pinecone | ||
| from dotenv import load_dotenv | ||
| from app.modules.chat.embed_query import embed_query | ||
| import os | ||
|
|
||
| load_dotenv() | ||
|
|
||
| pc = Pinecone(os.getenv("PINECONE_API_KEY")) | ||
| index = pc.Index("perspective") | ||
|
|
||
|
Comment on lines
+8
to
+10
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Harden Pinecone client/index initialization and make names configurable. Validate the API key, use named arg, and allow index/namespace via env for portability. -load_dotenv()
-
-pc = Pinecone(os.getenv("PINECONE_API_KEY"))
-index = pc.Index("perspective")
+load_dotenv()
+api_key = os.getenv("PINECONE_API_KEY")
+if not api_key:
+ raise RuntimeError("PINECONE_API_KEY is not set")
+pc = Pinecone(api_key=api_key)
+index_name = os.getenv("PINECONE_INDEX_NAME", "perspective")
+namespace = os.getenv("PINECONE_NAMESPACE", "default")
+index = pc.Index(index_name)🤖 Prompt for AI Agents |
||
|
|
||
| def search_pinecone(query: str, top_k: int = 5): | ||
|
|
||
| embeddings = embed_query(query) | ||
|
|
||
| results = index.query( | ||
| vector=embeddings, | ||
| top_k=top_k, | ||
| include_metadata=True, | ||
| namespace="default" | ||
|
|
||
| ) | ||
|
|
||
| matches = [] | ||
| for match in results["matches"]: | ||
| matches.append({ | ||
| "id": match["id"], | ||
| "score": match["score"], | ||
| "metadata": match["metadata"] | ||
| }) | ||
| return matches | ||
|
Comment on lines
+12
to
+31
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Fix result parsing for Pinecone v3 responses; add validation and error handling.
-def search_pinecone(query: str, top_k: int = 5):
-
- embeddings = embed_query(query)
-
- results = index.query(
- vector=embeddings,
- top_k=top_k,
- include_metadata=True,
- namespace="default"
-
- )
-
- matches = []
- for match in results["matches"]:
- matches.append({
- "id": match["id"],
- "score": match["score"],
- "metadata": match["metadata"]
- })
- return matches
+def search_pinecone(query: str, top_k: int = 5):
+ if not query or not query.strip():
+ return []
+ embedding = embed_query(query)
+ try:
+ res = index.query(
+ vector=embedding,
+ top_k=top_k,
+ include_metadata=True,
+ namespace=namespace,
+ )
+ except Exception as e:
+ # Consider logging and surfacing a structured error upstream
+ # logger.exception("Pinecone query failed")
+ return []
+
+ # Support both dict-like and object-like responses
+ raw_matches = []
+ if hasattr(res, "matches"):
+ raw_matches = res.matches or []
+ elif isinstance(res, dict):
+ raw_matches = res.get("matches", []) or []
+
+ normalized = []
+ for m in raw_matches:
+ # Support both dict items and attribute access
+ mid = m.get("id") if isinstance(m, dict) else getattr(m, "id", None)
+ mscore = m.get("score") if isinstance(m, dict) else getattr(m, "score", None)
+ mmeta = m.get("metadata") if isinstance(m, dict) else getattr(m, "metadata", None)
+ if mid is None:
+ continue
+ normalized.append({"id": mid, "score": mscore, "metadata": mmeta})
+ return normalized
🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import os | ||
| from groq import Groq | ||
| from dotenv import load_dotenv | ||
|
|
||
| load_dotenv() | ||
|
|
||
| client = Groq(api_key=os.getenv("GROQ_API_KEY")) | ||
|
|
||
|
Comment on lines
+7
to
+8
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Fail fast when the API key is missing If 🤖 Prompt for AI Agents |
||
|
|
||
| def build_context(docs): | ||
|
|
||
| return "\n".join(f"{m['metadata'].get('explanation') or m['metadata'].get('reasoning', '')}"for m in docs) | ||
|
|
||
|
|
||
| def ask_llm(question, docs): | ||
| context = build_context(docs) | ||
| print(context) | ||
| prompt = f"""You are an assistant that answers based on context. | ||
|
Comment on lines
+17
to
+18
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove plaintext context logging in production
🤖 Prompt for AI Agents |
||
|
|
||
| Context: | ||
| {context} | ||
|
|
||
| Question: | ||
| {question} | ||
| """ | ||
|
|
||
| response = client.chat.completions.create( | ||
| model="gemma2-9b-it", | ||
| messages=[ | ||
| {"role": "system", "content": "Use only the context to answer."}, | ||
| {"role": "user", "content": prompt} | ||
| ] | ||
| ) | ||
|
|
||
| return response.choices[0].message.content | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,10 @@ | |
| from pydantic import BaseModel | ||
| from app.modules.pipeline import run_scraper_pipeline | ||
| from app.modules.pipeline import run_langgraph_workflow | ||
| from app.modules.bias_detection.check_bias import check_bias | ||
| from app.modules.chat.get_rag_data import search_pinecone | ||
| from app.modules.chat.llm_processing import ask_llm | ||
| import asyncio | ||
| import json | ||
|
|
||
| router = APIRouter() | ||
|
|
@@ -11,14 +15,37 @@ class URlRequest(BaseModel): | |
| url: str | ||
|
|
||
|
|
||
| class ChatQuery(BaseModel): | ||
| message: str | ||
|
|
||
|
|
||
| @router.get("/") | ||
| async def home(): | ||
| return {"message": "Perspective API is live!"} | ||
|
|
||
|
|
||
| @router.post("/bias") | ||
| async def bias_detection(request: URlRequest): | ||
| content = await asyncio.to_thread(run_scraper_pipeline, (request.url)) | ||
| bias_score = await asyncio.to_thread(check_bias, (content)) | ||
| print(bias_score) | ||
| return bias_score | ||
|
|
||
|
|
||
| @router.post("/process") | ||
| async def run_pipelines(request: URlRequest): | ||
| article_text = run_scraper_pipeline(request.url) | ||
| article_text = await asyncio.to_thread(run_scraper_pipeline, (request.url)) | ||
| print(json.dumps(article_text, indent=2)) | ||
| data = run_langgraph_workflow(article_text) | ||
| data = await asyncio.to_thread(run_langgraph_workflow, (article_text)) | ||
| return data | ||
|
Comment on lines
+37
to
40
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Same tuple issue in
🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| @router.post("/chat") | ||
| async def answer_query(request: ChatQuery): | ||
|
|
||
| query = request.message | ||
| results = search_pinecone(query) | ||
| answer = ask_llm(query, results) | ||
| print(answer) | ||
|
|
||
| return {"answer": answer} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use env vars in clone URL and avoid duplicating username; quote the URL.
The clone command hardcodes the username/repo and embeds the token in the command. Prefer env vars to prevent drift and quote the URL to avoid parsing issues.
Apply this diff:
🤖 Prompt for AI Agents