Skip to content

Commit a57d949

Browse files
Merge pull request #37 from Pseudo-Lab/feature/qa-set-issue
Feature/qa set issue
2 parents ff376f4 + c598afa commit a57d949

13 files changed

Lines changed: 1035 additions & 404 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
@@ -48,6 +48,7 @@ class TableState(TypedDict, total=False):
4848
errors: List[str]
4949
synthetic_json: dict # 파싱된 합성 데이터 JSON
5050
qa_results: List[Dict] # 생성된 QA 쌍
51+
token_usage: int # QA 생성에 사용된 총 토큰 수
5152

5253

5354
def _encode_image(image_path: Path) -> str:
@@ -67,8 +68,18 @@ def _encode_image(image_path: Path) -> str:
6768

6869

6970
def _call_llm(
70-
llm: ChatOpenAI, prompt: str, image_urls: Optional[List[str]] = None) -> str:
71-
"""Call the multi-modal LLM with optional multiple images."""
71+
llm: ChatOpenAI, prompt: str, image_urls: Optional[List[str]] = None, return_token_usage: bool = False) -> str:
72+
"""Call the multi-modal LLM with optional multiple images.
73+
74+
Args:
75+
llm: The LLM instance
76+
prompt: The text prompt
77+
image_urls: Optional list of image URLs
78+
return_token_usage: If True, returns tuple of (content, total_tokens)
79+
80+
Returns:
81+
Response content string, or tuple of (content, total_tokens) if return_token_usage=True
82+
"""
7283

7384
content: List[Dict] = [{"type": "text", "text": prompt}]
7485

@@ -83,7 +94,31 @@ def _call_llm(
8394
})
8495

8596
response = llm.invoke([HumanMessage(content=content)])
86-
return response.content if isinstance(response.content, str) else json.dumps(response.content)
97+
response_content = response.content if isinstance(response.content, str) else json.dumps(response.content)
98+
99+
if return_token_usage:
100+
# Extract token usage from response metadata
101+
token_usage = 0
102+
if hasattr(response, 'response_metadata'):
103+
usage_metadata = response.response_metadata.get('usage', {})
104+
# OpenAI/Gemini format
105+
token_usage = usage_metadata.get('total_tokens', 0)
106+
# Fallback: prompt_tokens + completion_tokens
107+
if not token_usage:
108+
token_usage = usage_metadata.get('prompt_tokens', 0) + usage_metadata.get('completion_tokens', 0)
109+
# Fallback: input_tokens + output_tokens
110+
if not token_usage:
111+
token_usage = usage_metadata.get('input_tokens', 0) + usage_metadata.get('output_tokens', 0)
112+
# Alternative: usage_metadata attribute (dict or object)
113+
if not token_usage and hasattr(response, 'usage_metadata') and response.usage_metadata:
114+
usage = response.usage_metadata
115+
if isinstance(usage, dict):
116+
token_usage = usage.get('total_tokens', 0) or (usage.get('input_tokens', 0) + usage.get('output_tokens', 0))
117+
else:
118+
token_usage = getattr(usage, 'total_tokens', 0) or (getattr(usage, 'input_tokens', 0) + getattr(usage, 'output_tokens', 0))
119+
return response_content, token_usage
120+
121+
return response_content
87122

88123

89124
def _load_yaml_prompts(filename: str) -> Dict[str, str]:
@@ -649,7 +684,7 @@ def _node(state: TableState) -> TableState:
649684

650685
prompt = prompt_template
651686

652-
response_text = _call_llm(llm, prompt, image_urls=image_data_urls)
687+
response_text, token_usage = _call_llm(llm, prompt, image_urls=image_data_urls, return_token_usage=True)
653688
response_json = robust_json_parse(response_text)
654689

655690
qa_results = []
@@ -658,7 +693,7 @@ def _node(state: TableState) -> TableState:
658693
else:
659694
logger.warning("QA generation from image did not return valid JSON or 'qa_pairs' key.")
660695

661-
return {**state, "qa_results": qa_results}
696+
return {**state, "qa_results": qa_results, "token_usage": token_usage}
662697

663698
return _node
664699

75 KB
Loading

0 commit comments

Comments
 (0)