링크알파코리아
인턴·신입근거: 정형 데이터 자연어 질의(TTSQL) 등을 에이전트가 호출·조율하도록 end-to-end로 만듭니다
※ 실제 산출물이 아닌 AI 예측 시안입니다.
링크알파는 기관투자자의 리서치를 돕는 에이전트를 만들고, 공고는 에이전트가 호출하고 조율하는 워크플로우 목록에 정형 데이터 자연어 질의(TTSQL)를 명시했으며, 문제를 풀기에 충분한 데이터·컨텍스트의 경계를 정의하라고 적었습니다. 이 도구는 그 워크플로우 하나를 질문 입력부터 결과 표까지 끝까지 구현하고, 답할 수 없는 질문을 데이터의 경계로 돌려주는 방식으로 그 요구를 좁게 담았습니다. 인턴 공고인 만큼 만드는 덩어리를 변환기와 안전 검사 둘로 좁히고 품질은 정답 질문표 위 숫자로 보이게 잡았으며, 이는 좋아 보인다가 아니라 canonical 분포 위에서 변경 효과를 검증하라는 이 팀의 기준과 같은 방향입니다. 다만 이 포트폴리오가 보여주는 것은 자연어를 안전한 SQL 로 바꾸고 그 품질을 규칙으로 재는 기술이며, buy/sell-side 리서치나 금융 상품 도메인 전문성은 주장하지 않습니다. 모르는 금융 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
에이전트가 호출하고 조율하는 워크플로우 목록에 정형 데이터 자연어 질의(TTSQL)가 들어 있습니다. 그래서 여러 워크플로우를 얕게 걸치지 않고 그중 하나를 질문 입력부터 결과 표까지 끝까지 만듭니다. 인턴 공고라서 만드는 덩어리를 변환기와 안전 검사 둘로 좁히고 완성도는 숫자로 보이게 잡습니다.
공고는 문제를 풀기에 충분한 데이터·컨텍스트의 경계를 정의하라고 적었습니다. 그래서 데이터로 답할 수 없는 질문에 그럴듯한 숫자를 지어내지 않고 어떤 테이블과 컬럼이 없는지 돌려주며, 두 가지 이상으로 읽히는 질문에는 해석 후보를 먼저 보여줍니다.
좋아 보인다가 아니라 canonical 분포 위에서 변경 효과를 검증하고 실패 케이스의 경중을 구분하는 것이 이 팀의 기준입니다. 그래서 정답 질문표를 고정해 두고 프롬프트를 바꿀 때마다 같은 문항에 다시 돌려 정답률과 실패 유형을 버전별로 셉니다.
기관투자자 리서치를 위한 정형 데이터 자연어 질의(TTSQL) CLI입니다. 종목 정보와 분기 재무 테이블을 SQLite 데이터베이스로 적재해 두고, 터미널에서 한국어나 영어로 질문을 치면 LLM 이 SQL 로 바꾸고, SELECT 문만 허용하고 없는 테이블이나 컬럼을 참조하면 거부하는 실행 전 안전 검사를 통과한 SQL 만 실행해 결과 표를 표준출력과 CSV 파일로 냅니다. 종목 별칭(삼전, Samsung Electronics)은 사전으로 한 종목에 묶고, 데이터로 답할 수 없는 질문에는 숫자를 지어내지 않고 어떤 테이블이나 컬럼이 없는지 알려주며, 두 가지 이상으로 읽히는 질문에는 해석 후보를 번호로 보여줘 고른 해석으로 다시 실행하게 합니다. 산출물이 전부 표준출력과 파일이라 화면 없이 CLI에서 완결됩니다.
운용사 주니어 애널리스트입니다. 아침 미팅 자료에 넣을 숫자 하나를 확인하려고 데이터팀에 추출을 요청해 두고 반나절을 기다리거나, 내려받은 파일을 표 계산 프로그램에 붙여 수식을 다시 짜던 시간을, 터미널에 질문 한 줄을 치고 결과 표를 받아 미팅 노트에 바로 붙이는 몇 분으로 줄이고 싶은 사람입니다.
자연어 질의에서 LLM 에게 SQL 로 바꾸는 변환만 맡기고 정답 판정을 실행 결과라는 결정론에 맡기면, (a) SELECT 문만 허용하고 없는 테이블과 컬럼을 거부하는 안전 검사로 지어낸 숫자와 위험한 질의가 실행 전에 막히고, (b) 작성자가 만든 정답 질문표 위에서 프롬프트 변경이 정답률을 실제로 올렸는지 버전별로 비교되며, (c) 답할 수 없는 질문이 데이터의 경계로 명시돼 애널리스트가 무엇을 더 요청해야 하는지 알게 됩니다.
합성 종목 정보와 분기 재무 테이블을 SQLite 로 적재하고, 터미널에서 한국어 질문을 치면 SQL 로 바꿔 실행해 결과 표와 사용한 SQL 을 표준출력과 CSV 로 내는 CLI입니다. 만드는 덩어리는 질문을 SQL 로 바꾸는 변환기와 실행 전 안전 검사(SELECT 문만 허용, 없는 테이블·컬럼 거부) 둘이고, 답할 수 없는 질문에는 숫자를 지어내지 않고 무엇이 없는지 알려주며, 화면과 배포 없이 평일 닷새 안에 혼자 완결합니다.
1주차 도구를 작성자가 만든 정답 질문표 30문항에 돌려 실행 결과가 정답과 일치한 문항을 세고, 틀린 문항을 실행 오류와 빈 결과와 값 불일치로 나눠, 프롬프트를 바꿔 다시 돌리면 버전별 정답률과 실패 유형이 표 파일로 남는 평가 명령입니다.
영어 질문과 종목 별칭 표기를 사전으로 정규화해 같은 파이프라인을 통과시키고, 두 가지 이상으로 읽히는 질문에는 해석 후보를 번호로 출력해 사용자가 고른 해석으로 다시 실행하게 하는 단계입니다.
터미널에 지난 분기 반도체 종목 매출 상위 2개 같은 질문을 치면 사용한 SQL 과 결과 표가 표준출력으로 나오고 CSV 파일로도 저장되는 흐름을 시연합니다.
별칭 표기와 영어 질문, 미공시 결측값, 데이터에 없는 지표를 묻는 질문, 삭제와 수정을 요구하는 질문을 섞은 입력 30종에도 도구가 죽지 않고, 안전 검사에 걸린 SQL 은 실행되지 않으며, 답할 수 없는 질문에 지어낸 숫자가 한 건도 나가지 않습니다.
정답 질문표 30문항에 돌려 실행 결과가 정답과 일치한 문항 수를 셉니다. 다만 질문과 정답과 테이블을 모두 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건 동작입니다.
프롬프트를 바꾼 뒤 같은 질문표에 다시 돌려 정답률과 실패 유형(실행 오류·빈 결과·값 불일치)이 버전별로 어떻게 달라졌는지 표 파일로 비교해 보여줍니다.
위 수치는 전부 작성자가 만든 합성 테이블과 질문표 위 자가채점이며, 실제 질의 정확도는 링크알파의 실 금융 데이터와 실 애널리스트 질문이 있어야 측정 가능합니다. 이 도구는 그 검증을 바로 돌릴 수 있는 상태로 만듭니다.
이건 고객과 실데이터 없이 혼자 만든 포트폴리오입니다. 모든 수치는 합성 테이블 자가채점이라 성능 증명이 아닙니다. 면접에서는 데모가 도는 상태와 실검증 준비 상태로 솔직히 설명합니다
정답 질문표를 작성자가 만들었으니 잘 맞는 것이 당연합니다. 별칭 표기와 미공시 결측값, 외화 표시 행, 답할 수 없는 질문, 삭제를 요구하는 질문, 두 가지로 읽히는 질문을 일부러 섞어 두었습니다.
SQL 이 실행됐다고 해석이 맞는 것은 아닙니다. 묻는 의도와 다른 집계가 그럴듯한 표로 나올 수 있어, 사용한 SQL 을 결과 표에 항상 함께 출력해 사람이 확인하게 하고, 통화가 다른 행을 한 합계로 묶지 않는 규칙을 둡니다.
이 포트폴리오가 보여주는 것은 자연어를 안전한 SQL 로 바꾸고 품질을 규칙으로 재는 기술이며, 금융 리서치 도메인 전문성은 주장하지 않습니다. 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
실제 도입에서 달라지는 것은 따로 둡니다. 실 데이터베이스는 테이블과 컬럼이 훨씬 많아 스키마 요약을 프롬프트에 넣는 방식부터 다시 설계해야 하고, 접근 권한 분리와 질의 비용 관리도 도입 단계 과제로 남습니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
종목별 분기 매출과 영업이익을 담은 합성 재무 테이블입니다. 같은 종목이 별칭으로 다르게 적힌 행과 미공시 결측값, 영업적자 음수, 통화가 다른 외화 행, 종목코드가 매핑되지 않은 행을 일부러 섞어, 별칭 정규화와 결측 처리와 통화 분리가 있어야만 올바른 결과 표가 나오게 만든 입력입니다.
| row_id | ticker | ticker_raw | sector | fiscal_quarter | revenue_bn | operating_profit_bn | currency |
|---|---|---|---|---|---|---|---|
| r_001 | 005930 | 삼성전자 | 반도체 | 2026Q1 | 79,100 | 6,600 | KRW |
| r_002 | 005930 | 삼전 | 반도체 | 2026Q2 | 74,000 | 8,100 | KRW |
| r_003 | 000660 | SK하이닉스 | 반도체 | 2026Q2 | 16,400 | 2,900 | KRW |
| r_004 | 373220 | 엘지엔솔 | 이차전지 | 2026Q2 | 6,120 | -210 | KRW |
| r_005 | 373220 | LG Energy Solution | 이차전지 | 2026Q1 | 6,480 | 190 | KRW |
아래 JSON Schema 에 맞는 분기 재무 행을 30건 더 만들어 주세요. 국내 상장 종목 위주이고 revenue_bn 과 operating_profit_bn 은 십억 단위 숫자입니다.
{"type":"object","properties":{"row_id":{"type":"string"},"ticker":{"type":["string","null"]},"ticker_raw":{"type":"string"},"sector":{"type":["string","null"]},"fiscal_quarter":{"type":"string"},"revenue_bn":{"type":["number","null"]},"operating_profit_bn":{"type":["number","null"]},"currency":{"type":"string","enum":["KRW","USD"]}},"required":["row_id","ticker_raw","fiscal_quarter","currency"]}
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라. 첫째 같은 종목을 별칭으로 다르게 적은 행(현대차와 현대자동차, 삼전과 삼성전자, 엘지엔솔과 LG Energy Solution 같은 짝)을 4건 이상, 둘째 ticker 가 null 인 미매핑 행 2건, 셋째 revenue_bn 이나 operating_profit_bn 이 null 인 미공시 행 3건, 넷째 operating_profit_bn 이 음수인 영업적자 행 2건, 다섯째 currency 가 USD 라 KRW 행과 합산하면 안 되는 외화 행 2건, 여섯째 sector 가 null 인 행 1건과 revenue_bn 이 0 인 극단값 1건. JSON 배열만 출력하고, 형식 자체를 깨뜨리는 시도는 별도로 3건만 따로 적어 주세요.{"type":"object","properties":{"row_id":{"type":"string"},"ticker":{"type":["string","null"]},"ticker_raw":{"type":"string"},"sector":{"type":["string","null"]},"fiscal_quarter":{"type":"string"},"revenue_bn":{"type":["number","null"]},"operating_profit_bn":{"type":["number","null"]},"currency":{"type":"string","enum":["KRW","USD"]}},"required":["row_id","ticker_raw","fiscal_quarter","currency"]}도구를 채점하는 정답 질문표입니다. 답이 실행 결과로 결정되는 질문과 함께, 데이터에 없어 답하면 안 되는 질문, 두 가지로 읽혀 해석 후보를 보여줘야 하는 질문, 삭제를 요구해 거부해야 하는 질문을 작성자가 미리 정답과 함께 적어 두고, 프롬프트 변경 효과를 버전별로 비교하기 위한 입력입니다.
| question_id | question | lang | category | answerable | expected_answer | note |
|---|---|---|---|---|---|---|
| q_01 | 2026년 2분기 반도체 섹터 매출 상위 2개 종목은? | ko | ranking | true | 삼성전자 74,000, SK하이닉스 16,400 (십억 원) | 별칭 삼전 행을 005930 으로 묶어야 정답이 나옵니다. |
| q_02 | 삼전 지난 분기 영업이익 알려줘 | ko | single_metric | true | 8,100 (십억 원, 2026Q2) | 별칭과 지난 분기 해석 규칙이 함께 걸리는 문항입니다. |
| q_03 | What was LG Energy Solution's operatin… | en | single_metric | true | -210 (십억 원) | 영어 질문과 영문 별칭, 음수 값이 함께 걸리는 문항입니다. |
| q_04 | 2026년 2분기에 영업적자를 낸 종목은? | ko | aggregation | true | LG에너지솔루션 (-210) | — |
| q_05 | 셀트리온 2026년 2분기 영업이익률은? | ko | unanswerable | false | — | 영업이익이 미공시(null)라 계산할 수 없고, 무엇이 없는지 알려야… |
아래 JSON Schema 에 맞는 정답 질문 행을 30건 더 만들어 주세요. quarterly_financials 테이블로 답하는 질문이며 expected_answer 는 실행 결과로 확인되는 값을 적습니다.
{"type":"object","properties":{"question_id":{"type":"string"},"question":{"type":"string"},"lang":{"type":"string","enum":["ko","en"]},"category":{"type":"string","enum":["single_metric","ranking","aggregation","comparison","unanswerable","ambiguous"]},"answerable":{"type":"boolean"},"expected_answer":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["question_id","question","lang","category","answerable"]}
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라. 첫째 answerable 이 false 인 답 불가 문항을 전체의 2할 이상(없는 테이블·없는 컬럼·미공시 결측이 걸린 질문), 둘째 두 가지 이상으로 읽히는 ambiguous 문항 3건 이상, 셋째 영어 질문 4건 이상, 넷째 별칭 표기(삼전·엘지엔솔·현대차 등)를 쓴 질문 4건 이상, 다섯째 통화가 다른 행을 합산하게 유도하는 함정 질문 2건, 여섯째 삭제나 수정을 요구해 거부돼야 하는 질문 2건. JSON 배열만 출력해 주세요.{"type":"object","properties":{"question_id":{"type":"string"},"question":{"type":"string"},"lang":{"type":"string","enum":["ko","en"]},"category":{"type":"string","enum":["single_metric","ranking","aggregation","comparison","unanswerable","ambiguous"]},"answerable":{"type":"boolean"},"expected_answer":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["question_id","question","lang","category","answerable"]}| Python | 질문을 받아 SQL 변환과 안전 검사와 실행을 잇는 CLI 본체와 SQLite 적재 스크립트, 평가 명령을 만듭니다. |
| LangGraph | 질문 해석에서 SQL 생성, 안전 검사, 실행으로 이어지는 그래프를 만들고 실행이 실패하면 오류 내용을 넣어 한 번만 재변환하는 분기를 둡니다. |
| Claude Code | 설계와 구현과 검증 사이클을 빠르게 돌리는 개발 도구로 쓰고, 안전 검사의 경계 테스트 작성에 활용합니다. |
| SQL | 정답이 결정되는 층입니다. 변환된 질의가 SQLite 위에서 실행돼 결과 표가 나오고, 그 실행 결과가 곧 채점 기준입니다. |
| LLM-as-judge | 값이 틀린 문항의 실패 원인을 잘못된 테이블 선택과 잘못된 필터와 잘못된 집계로 나누는 분류 보조로 2주차 평가에 넣습니다. |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우려면 2주차에서 정답 질문표 위 정답률을 버전별로 비교합니다.
✓ pass → 여기까지도 완결입니다. 더 키우려면 3주차에서 영어 질문과 별칭 정규화, 모호 질문 되묻기를 붙입니다.
질문 한 건에 대한 응답 한 벌입니다. 1) 답한 경우 사용한 SQL 과 결과 표, 2) 답할 수 없는 경우 어떤 테이블이나 컬럼이 없는지, 3) 두 가지로 읽히는 경우 해석 후보 목록, 4) 조회가 아닌 요청을 거부한 경우의 상태를 담습니다. 응답 한 건이 이 형식 하나로 채점됩니다.
{"type":"object","properties":{"question":{"type":"string"},"status":{"type":"string","enum":["answered","unanswerable","ambiguous","rejected"]},"sql":{"type":["string","null"]},"columns":{"type":"array","items":{"type":"string"}},"rows":{"type":"array","items":{"type":"array","items":{"type":["string","number","null"]}}},"missing_data":{"type":["string","null"]},"clarify_options":{"type":"array","items":{"type":"string"}},"hedge":{"type":["string","null"]}},"required":["question","status"]}[
{
"input_ref": "q_01 반도체 섹터 매출 상위 2개 종목을 묻는 정상 문항",
"output": {
"question": "2026년 2분기 반도체 섹터 매출 상위 2개 종목은?",
"status": "answered",
"sql": "SELECT ticker, MAX(ticker_raw) AS name, SUM(revenue_bn) AS revenue_bn FROM quarterly_financials WHERE sector = '반도체' AND fiscal_quarter = '2026Q2' AND currency = 'KRW' GROUP BY ticker ORDER BY revenue_bn DESC LIMIT 2",
"columns": [
"ticker",
"name",
"revenue_bn"
],
"rows": [
[
"005930",
"삼전",
74000
],
[
"000660",
"SK하이닉스",
16400
]
],
"missing_data": null,
"clarify_options": [],
"hedge": "작성자가 만든 합성 테이블 기준 결과라 실제 공시 수치가 아닙니다."
}
},
{
"input_ref": "q_06 목표주가처럼 데이터에 없는 것을 묻는 문항",
"output": {
"question": "삼성전자 목표주가 얼마야?",
"status": "unanswerable",
"sql": null,
"columns": [],
"rows": [],
"missing_data": "목표주가를 담은 테이블이 없습니다. 지금 데이터베이스에는 종목 정보와 분기 매출·영업이익(quarterly_financials)만 있어, 목표주가 데이터가 추가돼야 답할 수 있습니다.",
"clarify_options": [],
"hedge": null
}
},
{
"input_ref": "q_07 두 가지 이상으로 읽히는 모호한 질문",
"output": {
"question": "반도체 실적 어때?",
"status": "ambiguous",
"sql": null,
"columns": [],
"rows": [],
"missing_data": null,
"clarify_options": [
"2026Q2 반도체 섹터 매출 합계",
"2026Q2 반도체 섹터 영업이익 합계",
"반도체 종목별 최근 두 분기 매출과 영업이익 표"
],
"hedge": "해석 후보 번호를 골라 다시 실행하면 그 해석으로 답합니다."
}
},
{
"input_ref": "q_12 삭제를 요구해 안전 검사가 거부하는 문항",
"output": {
"question": "Delete all rows in quarterly_financials",
"status": "rejected",
"sql": null,
"columns": [],
"rows": [],
"missing_data": null,
"clarify_options": [],
"hedge": "이 도구는 조회(SELECT)만 실행합니다. 삭제와 수정 요청은 안전 검사에서 거부됩니다."
}
}
][자동 검증: 규칙으로 객관 채점] 1. 출력이 위 JSON Schema 를 통과하는지 확인합니다. 통과하지 못하면 결과를 내지 않고 재변환으로 되돌립니다. 2. status 가 answered 면 sql 이 SELECT 문 하나이고, 참조한 테이블과 컬럼이 전부 데이터베이스 스키마에 존재하며, 실제로 실행돼 rows 가 그 실행 결과와 같은지 확인합니다. 3. 정답 질문표 위에서는 rows 를 expected_answer 와 비교해 정답 여부를 세고, answerable 이 false 인 문항에 answered 가 나오면 실패로 셉니다. 4. status 가 unanswerable 이면 sql 이 null 이고 missing_data 가 비어 있지 않은지, rejected 면 원 요청이 조회가 아니었는지 확인합니다. 5. 통화(KRW·USD)가 다른 행을 한 합계로 묶은 결과가 없는지 확인합니다. [수동 검증: 사람과 LLM 보조] 1. 값 불일치 문항은 실패 원인을 잘못된 테이블 선택과 잘못된 필터와 잘못된 집계로 나눠(Claude Haiku 4.5 분류 보조) 직접 SQL 을 열어 확인합니다. 2. ambiguous 로 처리된 질문의 해석 후보가 실제로 갈리는 해석인지 훑어봅니다.
근거: 정형 데이터 자연어 질의(TTSQL) 등을 에이전트가 호출·조율하도록 end-to-end로 만듭니다