generated from john/python-template
25 KiB
25 KiB
In [1]:
%load_ext autoreload
%autoreload 2In [2]:
from pathlib import Path
import rich
from sqlmodel.ext.asyncio.session import AsyncSession
from transcription.config import Settings
from transcription.config import configure_logging
from transcription.config import get_settings
from transcription.db.operations import create_all
from transcription.db.runtime import get_engine
from transcription.db.runtime import get_session
from transcription.models import Document
from transcription.models import Job
from transcription.services import ServiceBundle
from transcription.services import workflows as wf
from transcription.services.jobs import JobStatus
from transcription.services.store import create_upload_job
from transcription.services.transcription import transcribe_document_imageIn [3]:
configure_logging()
settings = get_settings(worker_max_retries=2)
engine = get_engine(settings=settings)
await create_all(engine=engine)
s = ServiceBundle()2026-06-28 12:53:12 DEBUG | Logging configured 2026-06-28 12:53:12 DEBUG | Initialized async database runtime for database_url=sqlite+aiosqlite:///./transcription.db 2026-06-28 12:53:12 DEBUG | Database schema bootstrap complete for database_url=sqlite+aiosqlite:///./transcription.db
In [4]:
settings.openrouter_api_keyOut [4]:
'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'
In [ ]:
test_file = Path("uploads/7c6ee648-4171-4e70-b901-ba94ee227d6a_Time Rolls On - page 013.jpg")In [ ]:
async def upload_file(file_path: str | Path, session: AsyncSession):
path = Path(file_path)
filename = path.name.rpartition("_")[2]
return await create_upload_job(
filename=filename,
file_bytes=path.read_bytes(),
session=session,
)
async with get_session() as session:
result = await upload_file(test_file, session)
rich.print(result)In [5]:
jobs = await s.jobs.list_jobs()
rich.print(jobs)
document = jobs[0].document
rich.print(document)[ Job( document_id=UUID('5c769d26-30bf-4950-ba3d-5dcabce690e7'), status=<JobStatus.QUEUED: 'queued'>, created_at=datetime.datetime(2026, 6, 28, 17, 9, 26, 395914), id=UUID('7a0d5e44-64e9-4916-83e0-bde3a8fb8c58'), retry_count=2, updated_at=datetime.datetime(2026, 6, 28, 17, 47, 26, 755438) ) ]
Document( uploaded_at=datetime.datetime(2026, 6, 28, 17, 9, 26, 392233), file_path='uploads/86a8f2c6-bfb7-4980-9941-56768902a9c0_Time Rolls On - page 013.jpg', filename='Time Rolls On - page 013.jpg', id=UUID('5c769d26-30bf-4950-ba3d-5dcabce690e7') )
In [6]:
await transcribe_document_image(document.file_path)Out [6]:
2026-06-28 12:53:20 INFO | Loaded prompt artifact: prompts/transcribe_document.md 2026-06-28 12:53:20 INFO | Starting transcription for image=uploads/86a8f2c6-bfb7-4980-9941-56768902a9c0_Time Rolls On - page 013.jpg mime_type=image/jpeg 2026-06-28 12:53:22 INFO | HTTP Request: POST https://openrouter.ai/api/v1/chat/completions "HTTP/1.1 200 OK" 2026-06-28 12:53:26 INFO | OpenRouter transcription completed using model=google/gemini-2.5-flash 2026-06-28 12:53:26 INFO | Transcription completed for image=uploads/86a8f2c6-bfb7-4980-9941-56768902a9c0_Time Rolls On - page 013.jpg provider=openrouter
TranscriptionResult(text='-13-\nWe lived fairly well. We had plenty of wheat at the flour mill. We had\n[taken this wheat as pay for our work in harvest. Beef was very cheap,\nfour and five cents per pound, syrup one dollar per gallon in tin cans,\nsugar five cents a pound, brown sugar, and my sister Texie was a good\ncook, and Billy and Pleas would entertain us of an evening with their\nwierd tales of their hardships in their travels to the railroad to\nget work. They got $2.00 per day driving scraper teams on the dump.\nThey had to go to Sprague, a distance of 60 miles, and carry their\nblankets on their backs. Billy always carried a pistol and Pleas a\npipe. They were pretty short of change and finally went broke. This\ntook place near Rock Lake, Washington Territory. So Billy traded his\npistol for two loaves of bread and supper and breakfast for both of\nthem. But before they got a job Pleas had to trade his pipe for a\ncouple more loaves.\n\nNow this winter of 1880 was a long and dreary winter. There was lots\nof snow and we did not go to any of the social activities such as church\nor debates at the school house, or singings in the neighborhood, and\nTexie and I named the entertainments given from time to time each\nevening "The Modoc Struggle." Until this day the phrase used in the\nCochran or Kittrell families expresses some memorable hardships in the\nbattle of life.\n\nIn February of 1881 I visited our old friends, the Stevensons, and Mr.\nStevenson was wanting a man to help him cut some cordwood and would\npay one dollar per day. Snow! Snow! Snow! Everyday I was expecting\nhim to have to quit work. Mr. Stevenson told me afterward he was expect-\ning me to quit anytime on account of the snow and cold and he was anxious\nto get enough wood cut to give him employment hauling wood to Colfax\nduring the summer to get his groceries and pay his store bill, as credit\nwas all the go with the homesteader.\n\nCapital stood in with men who were trying to improve the land and make\na home. This credit system worked, especially for the merchant and the\nimplement concerns and fairly well for the banker. The common interest\nwas 1½ percent per month, and sometimes as high as two percent. There\nwere many stock mortgages or a man on your note. The notes were usually\npayable in 90 days or renew your note.\n\nSo the spring of 1881 was here and the O.R. and N. railroad was being\nbuilt from Texas Ferry on the Snake River to Colfax. Men teams were\nwanted at $4.00 per day. Pleas, Texie, Billy and I were anxious to\nstart. We bought us a tent and a team apiece and went to Texas Ferry\nto make our fortune. The roads were not very good. The horses were\nrather cold shouldered and we had to be pulled out of the mud sometimes\nbut teamsters were good hearted and seldom charged each other. This\nwas March. When we go[t] to Snake River it was fine spring weather.\n\nNow it was December 1880 that Billy and I had come from Walla Walla in\na storm of snow and hundreds of head of cattle were in the road. They\nwere lowing and taking shelter along the bluffs. Now as we were going\nalong the same road for miles a person could step from one [carcass?] to\nanother. There were carcasses of cows, calves, big steers, and some\nhorses, lining the road.\n\nThe Company had to clear the way for travel. Stock men had prepared\nno feed. Now they had no stock. It was referred to as the "Cow Killer"', provider='openrouter', prompt_name='', model='google/gemini-2.5-flash')
In [ ]:
async with get_session() as session:
queued_jobs = await s.jobs.query_jobs(status=JobStatus.QUEUED, session=session)
job = await s.jobs.read_job(queued_jobs[0].id, session=session)
rich.print(job)
job = Job.model_copy(job)
rich.print(job.document)In [7]:
async with get_session() as session:
queued_jobs = await s.jobs.list_jobs(session=session)
job = await s.jobs.read_job(queued_jobs[0].id, session=session)
result = await wf.advance_job(
job,
services=s,
settings=settings,
# session=session,
)
rich.print(result)2026-06-28 12:53:53 DEBUG | Initialized async database runtime for database_url=sqlite+aiosqlite:///./transcription.db 2026-06-28 12:53:53 INFO | Loaded prompt artifact: prompts/transcribe_document.md 2026-06-28 12:53:53 INFO | Starting transcription for image=uploads/86a8f2c6-bfb7-4980-9941-56768902a9c0_Time Rolls On - page 013.jpg mime_type=image/jpeg 2026-06-28 12:53:54 INFO | HTTP Request: POST https://openrouter.ai/api/v1/chat/completions "HTTP/1.1 200 OK" 2026-06-28 12:53:58 INFO | OpenRouter transcription completed using model=google/gemini-2.5-flash 2026-06-28 12:53:58 INFO | Transcription completed for image=uploads/86a8f2c6-bfb7-4980-9941-56768902a9c0_Time Rolls On - page 013.jpg provider=openrouter 2026-06-28 12:53:58 INFO | Job transcribed operation=worker.process_job job_id=7a0d5e44-64e9-4916-83e0-bde3a8fb8c58 document_id=5c769d26-30bf-4950-ba3d-5dcabce690e7 provider=openrouter
Job( document_id=UUID('5c769d26-30bf-4950-ba3d-5dcabce690e7'), status=<JobStatus.TRANSCRIBED: 'transcribed'>, created_at=datetime.datetime(2026, 6, 28, 17, 9, 26, 395914), id=UUID('7a0d5e44-64e9-4916-83e0-bde3a8fb8c58'), retry_count=2, updated_at=datetime.datetime(2026, 6, 28, 17, 53, 58, 96639) )
In [ ]:
rich.print(settings)In [ ]:
async def reset_jobs():
"""Reset all jobs to QUEUED for testing purposes."""
async with get_session() as session:
jobs = await s.jobs.query_jobs(session=session)
for job in jobs:
job.status = JobStatus.QUEUED
await s.jobs.update_job(job, session=session)
await session.commit()
await reset_jobs()In [ ]: