Skip to content

Commit da79f95

Browse files
committed
중간 개발 저장
1 parent ab79e86 commit da79f95

11 files changed

Lines changed: 569 additions & 10 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"""Entry point for running the package as a module."""
2+
3+
from .cli import main
4+
5+
if __name__ == "__main__":
6+
main()

generate_synthetic_table/flow.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class TableState(TypedDict, total=False):
3636
errors: List[str]
3737
synthetic_json: dict # 파싱된 합성 데이터 JSON
3838
qa_results: List[Dict] # 생성된 QA 쌍
39+
token_usage: int # QA 생성에 사용된 총 토큰 수
3940

4041

4142
def _encode_image(image_path: Path) -> str:
@@ -55,8 +56,18 @@ def _encode_image(image_path: Path) -> str:
5556

5657

5758
def _call_llm(
58-
llm: ChatOpenAI, prompt: str, image_urls: Optional[List[str]] = None) -> str:
59-
"""Call the multi-modal LLM with optional multiple images."""
59+
llm: ChatOpenAI, prompt: str, image_urls: Optional[List[str]] = None, return_token_usage: bool = False) -> str:
60+
"""Call the multi-modal LLM with optional multiple images.
61+
62+
Args:
63+
llm: The LLM instance
64+
prompt: The text prompt
65+
image_urls: Optional list of image URLs
66+
return_token_usage: If True, returns tuple of (content, total_tokens)
67+
68+
Returns:
69+
Response content string, or tuple of (content, total_tokens) if return_token_usage=True
70+
"""
6071

6172
content: List[Dict] = [{"type": "text", "text": prompt}]
6273

@@ -71,7 +82,31 @@ def _call_llm(
7182
})
7283

7384
response = llm.invoke([HumanMessage(content=content)])
74-
return response.content if isinstance(response.content, str) else json.dumps(response.content)
85+
response_content = response.content if isinstance(response.content, str) else json.dumps(response.content)
86+
87+
if return_token_usage:
88+
# Extract token usage from response metadata
89+
token_usage = 0
90+
if hasattr(response, 'response_metadata'):
91+
usage_metadata = response.response_metadata.get('usage', {})
92+
# OpenAI/Gemini format
93+
token_usage = usage_metadata.get('total_tokens', 0)
94+
# Fallback: prompt_tokens + completion_tokens
95+
if not token_usage:
96+
token_usage = usage_metadata.get('prompt_tokens', 0) + usage_metadata.get('completion_tokens', 0)
97+
# Fallback: input_tokens + output_tokens
98+
if not token_usage:
99+
token_usage = usage_metadata.get('input_tokens', 0) + usage_metadata.get('output_tokens', 0)
100+
# Alternative: usage_metadata attribute (dict or object)
101+
if not token_usage and hasattr(response, 'usage_metadata') and response.usage_metadata:
102+
usage = response.usage_metadata
103+
if isinstance(usage, dict):
104+
token_usage = usage.get('total_tokens', 0) or (usage.get('input_tokens', 0) + usage.get('output_tokens', 0))
105+
else:
106+
token_usage = getattr(usage, 'total_tokens', 0) or (getattr(usage, 'input_tokens', 0) + getattr(usage, 'output_tokens', 0))
107+
return response_content, token_usage
108+
109+
return response_content
75110

76111

77112
def _load_yaml_prompts(filename: str) -> Dict[str, str]:
@@ -566,7 +601,7 @@ def _node(state: TableState) -> TableState:
566601

567602
prompt = prompt_template
568603

569-
response_text = _call_llm(llm, prompt, image_urls=image_data_urls)
604+
response_text, token_usage = _call_llm(llm, prompt, image_urls=image_data_urls, return_token_usage=True)
570605
response_json = robust_json_parse(response_text)
571606

572607
qa_results = []
@@ -575,7 +610,7 @@ def _node(state: TableState) -> TableState:
575610
else:
576611
logger.warning("QA generation from image did not return valid JSON or 'qa_pairs' key.")
577612

578-
return {**state, "qa_results": qa_results}
613+
return {**state, "qa_results": qa_results, "token_usage": token_usage}
579614

580615
return _node
581616

75 KB
Loading

0 commit comments

Comments
 (0)