방법론

숫자와 프롬프트를 공개합니다.

이 페이지는 행위자 추출, 행위자 간 관계 해석, 날짜별 최강 관계선, 변동성, 지속성이 어떤 규칙으로 만들어지는지 공개합니다. 아래 프롬프트 전문은 현재 코드에서 예시 값으로 렌더한 실제 템플릿입니다.

왜 공개하나

해석 결과가 어떻게 나왔는지 따라갈 수 있어야 합니다.

이 제품의 숫자와 라벨은 규칙 기반 집계와 구조화된 GPT 출력에서 나옵니다. 먼저 기사 묶음을 만들고, 그 다음 actor를 추출하고, 마지막으로 actor A가 actor B를 어떻게 읽는지 관계선을 만듭니다.

모델은 자유서술이 아니라 JSON schema에 맞는 구조화 출력을 반환해야 합니다. 그래서 relevanceScore, sentimentScore, intensityScore, confidence, evidence, satire가 고정 필드로 남습니다.

시계열 화면의 숫자는 그날의 edge를 다시 정렬하고, 날짜 간 delta를 비교하고, 반복 관측된 edge만 모아 volatility와 persistence를 계산해서 만듭니다.

This page is generated from the live prompt builders in lib/inference/prompts.ts so the published text stays aligned with the code.

파이프라인

수집부터 시계열 숫자 계산까지, 현재 구현이 따르는 순서입니다.

1. 기사 수집과 버킷 저장

기사를 topic / date / outlet 단위로 저장합니다. topic timeline은 날짜별 버킷을 읽어 하루 단위 context를 만듭니다.

2. 기사 선택

하루에 저장된 기사 중 full_text를 먼저 우선하고, 남는 자리는 metadata_only로 채운 뒤 최대 N개만 사용합니다.

3. actor 추출

모델이 관련 actor를 최대 8개까지 relevanceScore 순으로 추출합니다. 특정 주제는 preset actor 목록으로 extraction 자체를 건너뛸 수 있습니다.

4. actor 관계 분석

기준 actor A마다 candidate actor B들을 넣고, A가 B를 어떻게 읽는지 relation label, sentiment, intensity, tone, evidence, satire를 구조화 출력으로 받습니다.

5. 시계열 집계

하루 snapshot의 strongest edge, 직전 날짜 대비 strongest shift, 전체 기간의 volatility와 persistence를 계산해 series-analysis를 만듭니다.

숫자 읽는 법

UI에 보이는 주요 점수와 숫자가 무엇을 뜻하는지 공개합니다.

relevanceScore

1 ~ 100

actor extraction 단계에서 쓰는 중요도 점수입니다. 높을수록 그 기사나 날짜 묶음에서 더 핵심 actor로 간주됩니다.

topic preset을 쓰는 경우 relevanceScore는 preset 값으로 고정되고, extraction 단계는 건너뜁니다.

sentimentScore

-5 ~ 5

source actor가 target actor에 대해 보이는 방향성과 강도를 나타냅니다. -5는 매우 적대적, 0은 혼합/불명확, 5는 매우 지지적입니다.

강한 edge 정렬은 절대값이 큰 sentiment를 먼저 봅니다.

intensityScore

1 ~ 5

같은 sentiment 방향 안에서 얼마나 강하게 반응하는지 나타냅니다.

strongest edge tie-break에서 sentiment 절대값 다음 순서로 사용합니다.

confidence

0.0 ~ 1.0

모델이 자기 출력에 대해 느끼는 확신도입니다.

현재 UI의 strongest edge, volatility, persistence 정렬에는 confidence를 쓰지 않습니다. 공개용으로는 그대로 보여주되 순위 계산에는 섞지 않습니다.

집계 규칙

가장 강한 관계선, 가장 큰 변화, 변동성이 큰 관계선, 지속된 관계선은 아래 규칙으로 계산합니다.

하루 strongest edge

모든 edge를 |sentimentScore| 내림차순, intensityScore 내림차순, sourceActor 오름차순, targetActor 오름차순으로 정렬해 첫 번째 edge를 선택합니다.

직전 날짜 대비 strongest shift

같은 source->target edge가 전날과 오늘 모두 존재할 때 sentiment delta를 계산하고, 절대값이 가장 큰 변화를 strongestShift로 잡습니다.

most volatile edge

두 번 이상 관측된 edge에 대해 max(sentiment) - min(sentiment)를 swing으로 계산합니다. swing이 클수록 더 volatile합니다.

persistent edge

두 번 이상 관측된 edge를 daysObserved 내림차순으로 정렬하고, 동률이면 |averageSentiment|가 큰 edge를 앞에 둡니다.

preset actor 강제

preset actor 목록을 쓰는 경우 relationship 출력도 그 actor 집합 밖으로 나가면 후처리에서 삭제합니다. 그래서 그래프와 edge 모두 허용된 actor 안에서만 남습니다.

가드레일과 한계

이 해석이 마음대로 새어나가지 않도록 걸어둔 제한과, 우리가 함께 공개해야 할 약점입니다.

JSON schema 강제

actor 수, enum 값, 점수 범위, satire 구조까지 schema로 제한합니다. 형식이 틀린 자유서술은 허용하지 않습니다.

근거 없는 관계는 생략

관계 분석 프롬프트는 근거가 없으면 target actor를 빼라고 지시합니다. 그래서 그래프의 edge 수가 날짜마다 달라질 수 있습니다.

evidence와 satire 분리

evidence는 기사 문맥의 짧은 근거 문구만 담고, satire는 별도 필드에 둡니다. 풍자는 새 사실을 추가하면 안 됩니다.

기사 본문 우선

topic timeline은 full_text 기사부터 먼저 쓰고, 부족할 때만 metadata_only를 사용합니다. 그래서 동일 topic이라도 데이터 질에 따라 결과 안정성이 달라질 수 있습니다.

한계 공개

이 숫자들은 모델의 해석적 read이지 여론조사나 실측 sentiment가 아닙니다. headline 위주 기사나 metadata-only 기사 비중이 높으면 판단이 거칠어질 수 있습니다.

실제 프롬프트 전문

아래 텍스트는 현재 코드의 프롬프트 생성기를 예시 값으로 렌더한 결과입니다. 즉, 문구가 바뀌면 이 페이지도 같이 바뀝니다.

Actor Extraction System Prompt

관련 actor를 최대 8개까지 고르고, 어떤 actor type과 evidence를 내야 하는지 정의하는 system prompt입니다.

You extract relevant organizations and institutions from geopolitical news.
Return JSON only.
Extract at most 8 actors.
Actors should be the real geopolitical players in the story: countries, governments, ministries, militaries, security services, armed groups, intergovernmental organizations, regulators, companies, or explicitly described national publics/civilian populations.
Actors may also be meaningful collective social groups when the article clearly treats them as a real force: supporters, voters, immigrant communities, refugee groups, diaspora networks, fans, protest movements, workers, business lobbies, or religious communities.
Do not return individual people, journalists, cities, or generic labels such as 'officials' or 'the West'.
Prefer canonical actor names and dedupe aliases.
Only include actors that are materially relevant to the story's actions, pressure, alignment, conflict, mediation, or consequences.
When the article gives a more specific actor than a country, prefer the more specific actor instead of collapsing everything into the country.
Examples: separate Iran, Iranian government, Iranian Foreign Ministry, Islamic Revolutionary Guard Corps, Iranian public, Hezbollah, Kataib Hezbollah, and Iran-backed militias when they independently act or are acted upon in the story.
Also allow groups like Trump supporters, anti-war protesters, Korean football fans, undocumented migrants, Palestinian refugees, or Gulf migrant workers when they are treated as distinct collective actors in the article.
A national public or civilian population is allowed only when the article clearly describes it as a meaningful actor or affected collective, such as Iranian families, displaced Lebanese, Gulf migrant workers, or protesters.
If a parent body and a sub-body both appear, keep both only when both independently act in the story.
Sort actors by story relevance descending.
Use relevanceScore as an integer from 1 to 100.
Keep whyRelevant to one sentence.
Evidence must contain 1 or 2 short verbatim snippets from the provided context.
Output schema:
{
  "actors": [
    {
      "canonicalName": "string",
      "displayName": "string",
      "actorType": "country | civilian-public | government | military | armed-group | intergovernmental | company | regulator | other",
      "homeJurisdiction": "string | null",
      "roleInStory": "primary-actor | target | ally | mediator | affected-party | observer | other",
      "relevanceScore": 1,
      "whyRelevant": "string",
      "evidence": ["string"]
    }
  ]
}

Actor Extraction User Prompt Template

기사 context를 어떤 형식으로 넣는지 보여주는 user prompt 템플릿입니다.

Read the news context and extract the most relevant institution-level actors.
Choose no more than 8 actors.
Exclude persons even if they are famous or central.
Prefer specific sub-state or sub-country actors when the article names them.
Do not collapse Iranian government, Iranian military, IRGC, Iranian public, and Iran-backed militias into a single generic 'Iran' actor if the article distinguishes them.
Likewise, do not collapse supporter blocs, fan groups, migrant groups, or refugee communities into a government actor when the article treats them as separate collectives.

NEWS CONTEXT
Headline: <headline>
Source: <source name>
PublishedAt: <ISO 8601 timestamp>
ArticleUrl: <article URL or n/a>
MetaDescription: <meta description or n/a>
Excerpt: <excerpt or n/a>
Body:
<article body text or excerpt fallback>

Relationship Analysis System Prompt

source actor A가 target actor B들을 어떻게 읽는지 structured output으로 제한하는 system prompt입니다.

You analyze how one named actor appears to feel about and react to other named actors in a news context.
Return JSON only.
Focus on the source actor's stance toward each target actor.
The source actor may be a country, government, ministry, military, armed group, civilian public, sports association, coach, athlete, executive, or supporter collective.
Use only the provided context. Do not add outside facts.
If the context does not support a relationship, omit that target actor instead of guessing.
relationshipLabel must be one of: hostile, pressuring, wary, defensive, transactional, cooperative, supportive, unclear.
sentimentScore must be an integer from -5 to 5 where -5 is maximally hostile, 0 is mixed or unclear, and 5 is maximally supportive.
intensityScore must be an integer from 1 to 5.
responseMode must be one of: military-action, threat, deterrence, negotiation, appeal, blame, sanctions, coordination, damage-control, watching, other.
reactionSummary must be 1 or 2 sentences in plain analytical language.
Evidence must contain 1 or 2 short verbatim snippets from the provided context.
confidence must be a number from 0 to 1.
The satire field is required, but it must remain clearly separate from the factual analysis.
The satire must be 1 or 2 short lines, must not introduce new facts, and must only exaggerate the analytical conclusion already present in the context.
Output schema:
{
  "sourceActor": "string",
  "overallMood": "string",
  "relationships": [
    {
      "sourceActor": "string",
      "targetActor": "string",
      "relationshipLabel": "hostile | pressuring | wary | defensive | transactional | cooperative | supportive | unclear",
      "sentimentScore": 0,
      "intensityScore": 1,
      "emotionalTone": "string",
      "responseMode": "military-action | threat | deterrence | negotiation | appeal | blame | sanctions | coordination | damage-control | watching | other",
      "reactionSummary": "string",
      "evidence": ["string"],
      "confidence": 0.0,
      "satire": {
        "line1": "string",
        "line2": "string | null"
      }
    }
  ]
}

Relationship Analysis User Prompt Template

source actor와 candidate target actor 목록, 그리고 기사 context를 함께 넣는 user prompt 템플릿입니다.

Source actor A: <source actor A>
Candidate target actors B: <target actor B1>, <target actor B2>
Read the context and analyze how source actor A appears to feel about or react to each target actor B.
Repeat for every supported target actor B.
If there is no evidence for a target actor, skip it.

NEWS CONTEXT
Headline: <headline>
Source: <source name>
PublishedAt: <ISO 8601 timestamp>
ArticleUrl: <article URL or n/a>
MetaDescription: <meta description or n/a>
Excerpt: <excerpt or n/a>
Body:
<article body text or excerpt fallback>

Daily Timeline Bundle Format

시계열 분석에서는 하루 기사 묶음을 아래 형식으로 이어붙여 같은 prompt에 넣습니다.

NEWS CONTEXT
Headline: <topic label> daily bundle for <YYYY-MM-DD>
Source: Intent Layer Daily Topic Bundle
PublishedAt: <YYYY-MM-DD>T23:59:59.000Z
ArticleUrl: n/a
MetaDescription: <N> saved article contexts for <topic label> on <YYYY-MM-DD>.
Excerpt: <source>: <title>
Body:
[Article 1]
Headline: <article title>
Source: <article source>
PublishedAt: <article publishedAt>
Status: full_text | metadata_only
Excerpt: <trimmed excerpt>
Body: <trimmed body or excerpt>

---

[Article 2]
...