First Commit
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
import json
|
||||
|
||||
|
||||
SYSTEM = '''You are a technical literature triage assistant for an automotive radar engineer.
|
||||
|
||||
Analyze ONLY the supplied metadata.
|
||||
Do not invent experimental results, methods, conclusions, or claims that are not supported by the supplied metadata.
|
||||
|
||||
Return:
|
||||
- relevance: integer from 1 to 5
|
||||
- categories: technical categories
|
||||
- summary: 1-2 concise Korean sentences
|
||||
- reason: concise Korean explanation of why this paper is relevant
|
||||
|
||||
Preferred categories:
|
||||
Antenna,
|
||||
Waveform,
|
||||
DOA,
|
||||
MIMO,
|
||||
Target Modeling,
|
||||
Interference,
|
||||
RF Impairment,
|
||||
Imaging Radar,
|
||||
Signal Processing,
|
||||
Hardware,
|
||||
Other.
|
||||
'''
|
||||
|
||||
|
||||
AI_RESPONSE_SCHEMA = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"relevance": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 5,
|
||||
},
|
||||
"categories": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
},
|
||||
"summary": {
|
||||
"type": "string"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string"
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"relevance",
|
||||
"categories",
|
||||
"summary",
|
||||
"reason",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _make_payload(paper):
|
||||
return {
|
||||
"title": paper.title,
|
||||
"abstract": paper.abstract,
|
||||
"venue": paper.venue,
|
||||
"year": paper.year,
|
||||
"current_categories": paper.categories,
|
||||
"current_relevance": paper.relevance,
|
||||
}
|
||||
|
||||
|
||||
def _apply_result(paper, data):
|
||||
paper.relevance = max(
|
||||
1,
|
||||
min(
|
||||
5,
|
||||
int(data.get("relevance", paper.relevance))
|
||||
)
|
||||
)
|
||||
|
||||
if isinstance(data.get("categories"), list) and data["categories"]:
|
||||
paper.categories = [
|
||||
str(x)
|
||||
for x in data["categories"][:5]
|
||||
]
|
||||
|
||||
paper.summary = str(
|
||||
data.get("summary", "")
|
||||
).strip()
|
||||
|
||||
paper.ai_reason = str(
|
||||
data.get("reason", "")
|
||||
).strip()
|
||||
|
||||
return paper
|
||||
|
||||
|
||||
def enrich_with_gemini(paper, api_key, model):
|
||||
if not api_key:
|
||||
return paper
|
||||
|
||||
from google import genai
|
||||
from google.genai import types
|
||||
|
||||
client = genai.Client(api_key=api_key)
|
||||
|
||||
payload = _make_payload(paper)
|
||||
|
||||
prompt = (
|
||||
SYSTEM
|
||||
+ "\n\nPaper metadata:\n"
|
||||
+ json.dumps(payload, ensure_ascii=False)
|
||||
)
|
||||
|
||||
response = client.models.generate_content(
|
||||
model=model,
|
||||
contents=prompt,
|
||||
config=types.GenerateContentConfig(
|
||||
temperature=0.1,
|
||||
response_mime_type="application/json",
|
||||
response_schema=AI_RESPONSE_SCHEMA,
|
||||
),
|
||||
)
|
||||
|
||||
data = json.loads(response.text)
|
||||
|
||||
paper = _apply_result(paper, data)
|
||||
paper.ai_analysis_level = "abstract"
|
||||
|
||||
return paper
|
||||
|
||||
def enrich_with_gemini_full_text(
|
||||
paper,
|
||||
full_text,
|
||||
api_key,
|
||||
model,
|
||||
):
|
||||
if not api_key:
|
||||
return paper
|
||||
|
||||
if not full_text or not full_text.strip():
|
||||
return paper
|
||||
|
||||
from google import genai
|
||||
from google.genai import types
|
||||
|
||||
client = genai.Client(api_key=api_key)
|
||||
|
||||
payload = {
|
||||
"title": paper.title,
|
||||
"abstract": paper.abstract,
|
||||
"venue": paper.venue,
|
||||
"year": paper.year,
|
||||
"full_text": full_text,
|
||||
"current_categories": paper.categories,
|
||||
"current_relevance": paper.relevance,
|
||||
}
|
||||
|
||||
prompt = (
|
||||
SYSTEM
|
||||
+ """
|
||||
|
||||
You are given extracted full text from the paper.
|
||||
|
||||
Base the analysis primarily on the supplied full text.
|
||||
Do not invent information that is not present in the supplied text.
|
||||
If the extracted text appears incomplete or corrupted, be conservative.
|
||||
|
||||
The summary should describe the paper's main technical approach,
|
||||
contribution, and relevance to automotive radar when supported by the text.
|
||||
"""
|
||||
+ "\n\nPaper data:\n"
|
||||
+ json.dumps(payload, ensure_ascii=False)
|
||||
)
|
||||
|
||||
response = client.models.generate_content(
|
||||
model=model,
|
||||
contents=prompt,
|
||||
config=types.GenerateContentConfig(
|
||||
temperature=0.1,
|
||||
response_mime_type="application/json",
|
||||
response_schema=AI_RESPONSE_SCHEMA,
|
||||
),
|
||||
)
|
||||
|
||||
data = json.loads(response.text)
|
||||
|
||||
paper = _apply_result(paper, data)
|
||||
paper.ai_analysis_level = "full_text"
|
||||
|
||||
return paper
|
||||
|
||||
def enrich_with_openai(paper, api_key, model):
|
||||
if not api_key:
|
||||
return paper
|
||||
|
||||
from openai import OpenAI
|
||||
|
||||
client = OpenAI(api_key=api_key)
|
||||
|
||||
payload = _make_payload(paper)
|
||||
|
||||
response = client.responses.create(
|
||||
model=model,
|
||||
instructions=SYSTEM,
|
||||
input=json.dumps(
|
||||
payload,
|
||||
ensure_ascii=False
|
||||
),
|
||||
)
|
||||
|
||||
text = response.output_text.strip()
|
||||
|
||||
if text.startswith("```"):
|
||||
text = text.strip("`")
|
||||
|
||||
if text.lower().startswith("json"):
|
||||
text = text[4:].strip()
|
||||
|
||||
data = json.loads(text)
|
||||
|
||||
return _apply_result(paper, data)
|
||||
Reference in New Issue
Block a user