본문 바로가기

알토르

알토르 6주차 MongoDB

알토르 6주차 MongoDB

from flask import Flask, request, jsonify
from flask_cors import CORS
import os
import time
from dotenv import load_dotenv
from openai import OpenAI
from pymongo import MongoClient  # ✅ 추가

# 1. 환경 변수 로드
load_dotenv()

# 2. OpenAI 설정
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
    raise ValueError("OpenAI API 키가 설정되지 않았습니다. .env 확인하세요.")
assistant_id_from_env = os.getenv("OPENAI_ASSISTANT_ID")

# 3. MongoDB 연결 설정
mongo_uri = os.getenv("MONGO_URI")
if not mongo_uri:
    raise ValueError("MongoDB URI가 설정되지 않았습니다. .env 확인하세요.")

client_mongo = MongoClient(mongo_uri)
db = client_mongo.get_database()  # 기본 DB
messages_collection = db["messages"]  # messages 컬렉션 생성

# 4. Flask 앱 설정
app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": ["https://orkr.shop", "https://www.orkr.shop"]}})

# 5. OpenAI 클라이언트 생성
client = OpenAI(api_key=api_key)

# 6. Assistants API 기반 채팅 엔드포인트
@app.route('/sendMessage', methods=['POST', 'OPTIONS'])
def send_message():
    if request.method == "OPTIONS":
        return "", 204

    data = request.json
    username = data.get("username", "anonymous")
    message = data.get("message", "")
    provided_assistant_id = data.get("assistant_id")
    thread_id = data.get("thread_id")

    assistant_id = provided_assistant_id or assistant_id_from_env
    if not assistant_id:
        return jsonify({
            "error": "assistant_id가 없습니다. 요청 바디에 assistant_id를 포함하거나 환경 변수 OPENAI_ASSISTANT_ID를 설정하세요."
        }), 400

    try:
        # 🧩 1. 스레드 생성 (없으면)
        if not thread_id:
            thread = client.beta.threads.create()
            thread_id = thread.id

        # 🧩 2. 사용자 메시지 추가
        client.beta.threads.messages.create(
            thread_id=thread_id,
            role="user",
            content=message
        )

        # 🧩 3. Run 생성 후 완료 대기
        run = client.beta.threads.runs.create(
            thread_id=thread_id,
            assistant_id=assistant_id
        )

        max_wait_seconds = 60
        start_time = time.time()
        while True:
            run = client.beta.threads.runs.retrieve(
                thread_id=thread_id,
                run_id=run.id
            )
            if run.status in ["completed", "failed", "cancelled", "expired"]:
                break
            if time.time() - start_time > max_wait_seconds:
                break
            time.sleep(0.7)

        bot_reply = ""
        run_status = getattr(run, "status", "unknown")

        # 🧩 4. 응답 메시지 가져오기
        if run_status == "completed":
            messages = client.beta.threads.messages.list(
                thread_id=thread_id,
                order="desc",
                limit=5
            )
            assistant_message = next(
                (m for m in messages.data if m.role == "assistant"),
                None
            )
            if assistant_message and assistant_message.content:
                text_parts = [
                    part.text.value for part in assistant_message.content
                    if getattr(part, "type", "") == "text" and getattr(part, "text", None)
                ]
                bot_reply = "\n".join(text_parts) if text_parts else ""
        else:
            bot_reply = f"Run 상태: {run_status}"

        # ✅ MongoDB에 저장
        messages_collection.insert_one({
            "username": username,
            "user_message": message,
            "bot_reply": bot_reply,
            "thread_id": thread_id,
            "timestamp": time.time(),
            "run_status": run_status
        })

    except Exception as e:
        return jsonify({
            "error": f"Assistants API 호출 실패: {e}",
        }), 500

    print(f"[{username}] {message} -> {bot_reply}")

    return jsonify({
        "username": username,
        "user_message": message,
        "bot_reply": bot_reply,
        "timestamp": time.time(),
        "thread_id": thread_id,
        "run_status": run_status
    })


# ✅ 메시지 조회용 라우트 추가 (선택)
@app.route("/getMessages", methods=["GET"])
def get_messages():
    username = request.args.get("username")
    if not username:
        return jsonify({"error": "username이 필요합니다."}), 400

    messages = list(messages_collection.find(
        {"username": username},
        {"_id": 0}
    ))

    return jsonify(messages)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
pymongo.errors.ConfigurationError: No default database defined
db = client_mongo.get_database()
이 줄에서 "기본 DB가 정의되지 않았다" 라고 터진 거야.

✅ 방법 1. .env의 URI에 기본 DB 명시

MONGO_URI=mongodb+srv://user:pass@cluster.mongodb.net/[mydb]?retryWrites=true&w=majority
  • DB 이름 [mydb] 작성 필요

✅ 방법 2. 코드에서 DB 직접 지정

db = client_mongo["mydb"]

또는

db = client_mongo.get_database("mydb")
  • mydb는 MongoDB Atlas에 생성한 DB 이름
  • PostMan
  1. POST

http://aws.orkr.shop:5000/sendMessage

  • 새 메시지를 보내거나 저장
  • Body -json으로 메시지 전송 및 저장
  1. GET

http://aws.orkr.shop:5000/getMessages

  • MongoDB 내 데이터 조회
  • Postman에서 /getMessages를 호출 시
    - username 조건에 맞는 메시지 배열이 그대로 반환

http://aws.orkr.shop:5000/getMessages?username=Ju-hyeok

  • MongoDB - Cluster - Browse Collections -
# ✅ 전체 메시지 조회용 라우트
@app.route("/getMessages", methods=["GET"])
def get_messages():
    username = request.args.get("username")  # 선택적

    if username:
        # username이 있으면 해당 사용자 메시지만 조회
        query = {"username": username}
    else:
        # username이 없으면 전체 메시지 조회
        query = {}

    # MongoDB에서 조회, _id 제외
    messages = list(messages_collection.find(query, {"_id": 0}))

    return jsonify(messages)

'알토르' 카테고리의 다른 글

알토르 7주차 추가  (0) 2026.05.22
알토르 7주차 과제 - Response API 변경  (0) 2026.05.21
알토르 6주차 MongoDB  (0) 2026.05.20
알토르 6주차 과제 추가  (0) 2026.05.19
알토르 5주차 과제  (0) 2026.05.18