feat: add IP geolocation tracking and include location in prompts

- Add GeoLite2-City.mmdb database for IP lookup
- Create geoip.py module for IP location services
- Extract client IP from requests and log location info
- Pass location context to LLM prompts for enhanced responses
This commit is contained in:
2026-02-18 08:59:28 +08:00
parent 2b79f20e19
commit d2b64ad5d6
7 changed files with 181 additions and 13 deletions
+20 -10
View File
@@ -1,4 +1,4 @@
from fastapi import FastAPI
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse, JSONResponse
from pydantic import BaseModel
@@ -9,6 +9,7 @@ import logging
from prompt import build_prompt, prepare_prompt_context
from llm import call_ollama, call_vlm_ocr
from geoip import get_ip_location_text
logging.basicConfig(
level=logging.INFO,
@@ -43,23 +44,32 @@ def _preview(text: str, limit: int = 80) -> str:
return value
return value[:limit] + "..."
def get_client_ip(request: Request) -> str:
return request.headers.get("X-Client-IP") or request.client.host if request.client else "unknown"
@app.post("/v1/completions")
async def create_completion(request: CompletionRequest):
async def create_completion(request: Request, req: CompletionRequest):
request_id = str(uuid.uuid4())[:8]
client_ip = get_client_ip(request)
# 查询 IP 归属地
location = get_ip_location_text(client_ip)
if location:
logger.info("[%s] client_location=%s", request_id, location)
try:
logger.info(
"[%s] /v1/completions prefix_chars=%d suffix_chars=%d lang=%s prefix_tail='%s' suffix_head='%s'",
"[%s] /v1/completions client_ip=%s prefix_chars=%d suffix_chars=%d lang=%s prefix_tail='%s' suffix_head='%s'",
request_id,
len(request.prefix or ""),
len(request.suffix or ""),
request.languageId,
_preview((request.prefix or "")[-120:]),
_preview((request.suffix or "")[:120]),
client_ip,
len(req.prefix or ""),
len(req.suffix or ""),
req.languageId,
_preview((req.prefix or "")[-120:]),
_preview((req.suffix or "")[:120]),
)
llm_prefix, llm_suffix = prepare_prompt_context(request.prefix or "", request.suffix or "")
llm_prefix, llm_suffix = prepare_prompt_context(req.prefix or "", req.suffix or "")
logger.info("[%s] llm_input_prefix=%r", request_id, llm_prefix)
logger.info("[%s] llm_input_suffix=%r", request_id, llm_suffix)
prompt = build_prompt(request.prefix, request.suffix, request.languageId)
prompt = build_prompt(req.prefix, req.suffix, req.languageId, location=location)
result = await call_ollama(prompt, tag=f"{request_id}-primary", temperature=0.7)
content = result["content"] or ""