Skip to content

Commit fbe5d5b

Browse files
authored
Merge pull request #22 from OpenPecha/tokencounter
Feat: Token Counter using google genai
2 parents d492337 + 9365a25 commit fbe5d5b

File tree

4 files changed

+58
-4
lines changed

4 files changed

+58
-4
lines changed

api/Assistant/assistant_model.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from sqlalchemy.orm import relationship
2-
from sqlalchemy import Column,DateTime,String,ForeignKey,Boolean,UUID,Text
2+
from sqlalchemy import Column,DateTime,String,ForeignKey,Boolean,UUID,Text,Integer
33
from datetime import datetime,timezone
44
from uuid import uuid4
55
from api.db.pg_database import Base
@@ -30,6 +30,7 @@ class Context(Base):
3030
content=Column(Text,nullable=True)
3131
pecha_title = Column(String(255), nullable=True)
3232
pecha_text_id = Column(String(255), nullable=True)
33+
token_count = Column(Integer, nullable=True)
3334
assistant_id = Column(UUID(as_uuid=True),ForeignKey("assistant.id", ondelete="CASCADE"),nullable=False)
3435
created_at = Column(DateTime(timezone=True), default=datetime.now(timezone.utc),nullable=False)
3536
updated_at = Column(DateTime(timezone=True), default=datetime.now(timezone.utc))

api/Assistant/assistant_service.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from uuid import UUID
1010
from datetime import datetime, timezone
1111
from fastapi import HTTPException, status, UploadFile
12+
from api.config import get
13+
from api.llm.token_counter import TokenCounter
1214
from api.error_constant import ErrorConstants
1315
from api.cache.cache_enums import CacheType
1416
from api.Assistant.assistant_cache_service import (
@@ -18,6 +20,8 @@
1820
)
1921
from api.utils import Utils
2022

23+
token_counter = TokenCounter(api_key=get("GEMINI_API_KEY"))
24+
2125

2226
def _build_context_responses(contexts) -> List[ContextResponse]:
2327
return [
@@ -81,8 +85,9 @@ async def create_assistant_service(token: str, assistant_request: AssistantReque
8185
content = "\n\n".join([detail.content for detail in search_details]) if search_details else ""
8286
else:
8387
content = ctx.content
88+
token_count = token_counter.count_tokens(content)
8489
contexts_list.append(
85-
Context(content=content, pecha_title=ctx.pecha_title, pecha_text_id=ctx.pecha_text_id)
90+
Context(content=content, pecha_title=ctx.pecha_title, pecha_text_id=ctx.pecha_text_id, token_count=token_count)
8691
)
8792
if files:
8893
for file in files:
@@ -91,7 +96,8 @@ async def create_assistant_service(token: str, assistant_request: AssistantReque
9196
try:
9297
Utils.validate_file(file.filename, len(file_bytes))
9398
extracted_content = Utils.extract_content_from_file(file_bytes, file.filename)
94-
contexts_list.append(Context(content=extracted_content))
99+
file_token_count = token_counter.count_tokens(extracted_content)
100+
contexts_list.append(Context(content=extracted_content, token_count=file_token_count))
95101
except ValueError as e:
96102
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
97103

@@ -171,8 +177,9 @@ async def update_assistant_service(assistant_id: UUID, update_request: UpdateAss
171177
content = "\n\n".join([detail.content for detail in search_details]) if search_details else ""
172178
else:
173179
content = ctx.content
180+
token_count = token_counter.count_tokens(content)
174181
new_contexts.append(
175-
Context(content=content, pecha_title=ctx.pecha_title, pecha_text_id=ctx.pecha_text_id)
182+
Context(content=content, pecha_title=ctx.pecha_title, pecha_text_id=ctx.pecha_text_id, token_count=token_count)
176183
)
177184
assistant.contexts = new_contexts
178185

api/llm/token_counter.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from langchain_google_genai import ChatGoogleGenerativeAI
2+
from typing import Optional
3+
4+
class TokenCounter:
5+
def __init__(self, api_key: str, model_name: str = "gemini-2.5-flash"):
6+
self.model = ChatGoogleGenerativeAI(
7+
model=model_name,
8+
google_api_key=api_key
9+
)
10+
11+
def count_tokens(self, text: Optional[str]) -> int:
12+
if not text:
13+
return 0
14+
return self.model.get_num_tokens(text)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""added tokencount field in context table
2+
3+
Revision ID: 635acdc7f036
4+
Revises: 18cf46778420
5+
Create Date: 2026-02-25 14:29:23.227314
6+
7+
"""
8+
from typing import Sequence, Union
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
13+
14+
# revision identifiers, used by Alembic.
15+
revision: str = '635acdc7f036'
16+
down_revision: Union[str, Sequence[str], None] = '18cf46778420'
17+
branch_labels: Union[str, Sequence[str], None] = None
18+
depends_on: Union[str, Sequence[str], None] = None
19+
20+
21+
def upgrade() -> None:
22+
"""Upgrade schema."""
23+
# ### commands auto generated by Alembic - please adjust! ###
24+
op.add_column('context', sa.Column('token_count', sa.Integer(), nullable=True))
25+
# ### end Alembic commands ###
26+
27+
28+
def downgrade() -> None:
29+
"""Downgrade schema."""
30+
# ### commands auto generated by Alembic - please adjust! ###
31+
op.drop_column('context', 'token_count')
32+
# ### end Alembic commands ###

0 commit comments

Comments
 (0)