import os
import sys
import json
import requests
def debug_llm_connection(base_url: str, model_name: str = None):
"""
[디버거 1]: LLM 서버 접속 전 엔드포인트 및 모델 라우트 정밀 점검 (Pre-flight)
"""
print(f"\n🔍 [LLM Debugger] Target Base URL: {base_url}")
base_url = base_url.rstrip('/')
test_endpoints = [
f"{base_url}/models",
f"{base_url}/v1/models",
f"{base_url}/api/tags"
]
success = False
print("📡 [1/2] 엔드포인트 라우팅 헬스체크 진행 중...")
for ep in test_endpoints:
try:
res = requests.get(ep, timeout=5)
print(f" 👉 GET {ep} ➡️ HTTP Status: {res.status_code}")
if res.status_code == 200:
print(f" ✅ 정상 응답 수신! (응답 요약: {res.text[:100]}...)")
success = True
break
except Exception as e:
print(f" ❌ 접속 실패 ({ep}): {str(e)}")
if not success:
print("\n🚨 [404 원인 추정]: 등록된 API 엔드포인트 경로를 찾지 못했습니다.")
print(" - URL 끝에 '/v1' 이 빠졌는지 확인하세요. (예: http://llm-server:8000 ➡️ http://llm-server:8000/v1)")
print(" - Ollama 사용 시: http://localhost:11434/v1 또는 http://localhost:11434/api/chat")
print(" - vLLM/LiteLLM 사용 시: http://localhost:8000/v1\n")
def invoke_llm_with_trace(base_url: str, model: str, prompt: str, api_key: str = "EMPTY"):
"""
[디버거 2]: 404 발생 시 Request URL과 Server Raw Response를 정밀 트레이싱하는 LLM 호출기
"""
base_url = base_url.rstrip('/')
if not base_url.endswith("/v1"):
endpoint_url = f"{base_url}/v1/chat/completions"
else:
endpoint_url = f"{base_url}/chat/completions"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
payload = {
"model": model,
"messages": [
{"role": "system", "content": "You are an expert SRE and Cloud Infrastructure Architect."},
{"role": "user", "content": prompt}
],
"temperature": 0.2
}
print(f"\n🚀 [LLM Request Dispatch]")
print(f" - Target Endpoint : {endpoint_url}")
print(f" - Target Model : {model}")
try:
response = requests.post(
endpoint_url,
headers=headers,
data=json.dumps(payload),
timeout=60
)
response.raise_for_status()
res_json = response.json()
print("✅ [LLM 호출 성공]")
return res_json['choices'][0]['message']['content']
except requests.exceptions.HTTPError as http_err:
print(f"\n💥 [HTTP 에러 발생] Status Code: {response.status_code}")
print(f" - Full Requested URL : {response.url}")
print(f" - Request Headers : {headers}")
print(f" - Request Payload : {json.dumps(payload, indent=2)}")
print(f" - Server Raw Response: {response.text}")
raise http_err
except Exception as err:
print(f"\n💥 [일반 통신 에러 발생]: {str(err)}")
raise err
if __name__ == "__main__":
LLM_BASE_URL = os.getenv("LLM_BASE_URL", "http://llm-service.internal.zone:8000")
LLM_MODEL_NAME = os.getenv("LLM_MODEL_NAME", "meta-llama/Llama-3-8B-Instruct")
debug_llm_connection(LLM_BASE_URL, LLM_MODEL_NAME)
test_prompt = "Perform a brief RCA analysis for CPU throttled pods."
try:
result = invoke_llm_with_trace(
base_url=LLM_BASE_URL,
model=LLM_MODEL_NAME,
prompt=test_prompt
)
print(f"\n🤖 [LLM Response Preview]:\n{result[:200]}...")
except Exception as e:
print("\n❌ [Step5 LLM 연동 중단] 위 출력된 Target Endpoint 및 Server Raw Response를 확인하세요.")