new file: .dockerignore
new file: .env.example new file: Dockerfile new file: app.py new file: blueprints/__init__.py new file: blueprints/auth.py new file: blueprints/chat.py new file: blueprints/context.py new file: blueprints/documents.py new file: blueprints/main.py new file: config.py new file: docker-compose.yml new file: models/__init__.py new file: models/chat_session.py new file: models/document.py new file: models/user.py new file: requirements.txt new file: services/__init__.py new file: services/document_parser.py new file: services/llm_service.py new file: services/rag_service.py new file: services/url_scraper.py new file: static/css/style.css new file: static/js/chat.js new file: static/js/inline_chat.js new file: static/js/main.js new file: templates/base.html new file: templates/document_view.html new file: templates/index.html new file: templates/login.html new file: templates/register.html
This commit is contained in:
63
blueprints/context.py
Normal file
63
blueprints/context.py
Normal file
@@ -0,0 +1,63 @@
|
||||
from flask import Blueprint, request, jsonify, current_app
|
||||
from flask_login import login_required, current_user
|
||||
from models import db, UrlContext
|
||||
from services.url_scraper import scrape_url
|
||||
from services import rag_service
|
||||
|
||||
context_bp = Blueprint("context", __name__, url_prefix="/api/context")
|
||||
|
||||
|
||||
@context_bp.route("/urls", methods=["GET"])
|
||||
@login_required
|
||||
def list_urls():
|
||||
urls = UrlContext.query.filter_by(user_id=current_user.id).order_by(UrlContext.created_at.desc()).all()
|
||||
return jsonify([u.to_dict() for u in urls])
|
||||
|
||||
|
||||
@context_bp.route("/urls", methods=["POST"])
|
||||
@login_required
|
||||
def add_url():
|
||||
data = request.get_json(silent=True) or {}
|
||||
url = (data.get("url") or "").strip()
|
||||
if not url:
|
||||
return jsonify({"error": "No URL provided"}), 400
|
||||
if not url.startswith(("http://", "https://")):
|
||||
return jsonify({"error": "Invalid URL. Must start with http:// or https://"}), 400
|
||||
|
||||
# Check for duplicate per user
|
||||
existing = UrlContext.query.filter_by(user_id=current_user.id, url=url).first()
|
||||
if existing:
|
||||
return jsonify({"error": "URL already added"}), 409
|
||||
|
||||
url_ctx = UrlContext(user_id=current_user.id, url=url, indexed=False)
|
||||
db.session.add(url_ctx)
|
||||
db.session.commit()
|
||||
|
||||
try:
|
||||
title, text = scrape_url(url)
|
||||
url_ctx.title = title[:500]
|
||||
rag_service.index_source(
|
||||
text=text,
|
||||
user_id=current_user.id,
|
||||
source_id=url_ctx.id,
|
||||
source_type="url",
|
||||
chunk_size=current_app.config["RAG_CHUNK_SIZE"],
|
||||
chunk_overlap=current_app.config["RAG_CHUNK_OVERLAP"],
|
||||
)
|
||||
url_ctx.indexed = True
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
current_app.logger.error(f"Scraping/indexing failed for url {url_ctx.id}: {e}")
|
||||
|
||||
return jsonify(url_ctx.to_dict()), 201
|
||||
|
||||
|
||||
@context_bp.route("/urls/<int:url_id>", methods=["DELETE"])
|
||||
@login_required
|
||||
def delete_url(url_id):
|
||||
url_ctx = UrlContext.query.filter_by(id=url_id, user_id=current_user.id).first_or_404()
|
||||
|
||||
rag_service.delete_source(current_user.id, url_ctx.id, "url")
|
||||
db.session.delete(url_ctx)
|
||||
db.session.commit()
|
||||
return jsonify({"success": True})
|
||||
Reference in New Issue
Block a user