Skip to content

Commit

Permalink
fix: enametoolong error
Browse files Browse the repository at this point in the history
  • Loading branch information
arshad-yaseen committed Nov 5, 2024
1 parent 3708707 commit 5638fde
Show file tree
Hide file tree
Showing 17 changed files with 1,336 additions and 2,987 deletions.
3,797 changes: 837 additions & 2,960 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ export const API_ENDPOINTS: Record<Provider, string> = {
* Prompt template for the LLM.
*/
export const PROMPT_TEMPLATE =
'Extract all visible text from this image. Format the output as markdown. Include only the text content, no explanations or additional context.';
'Extract all visible text from this image. Format the output as markdown. Include only the text content, no explanations or additional context. Fix any formatting issues, typos, or inconsistencies found in the extracted content.';
2 changes: 1 addition & 1 deletion src/constants/llm.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const DEFAULT_MODEL_TEMPERATURE = 0.3;
export const DEFAULT_MODEL_TEMPERATURE = 0.1;
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
export {Ocra} from './core/ocra';
export {
OcraConfig,
ImageResult,
PageResult,
InputSource,
OCRMetadata,
Provider,
} from './types';
3 changes: 2 additions & 1 deletion src/processors/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {promises as fs} from 'fs';

import {ImageResult, InputSource, Provider} from '../types';
import {callLLM} from '../utils/call-llm';
import {removeCodeBlockMarkers} from '../utils/string';

/**
* Processes an image input and extracts text content.
Expand Down Expand Up @@ -33,7 +34,7 @@ export async function processImage(
const content = await callLLM(apiKey, base64Image, provider);

return {
content,
content: removeCodeBlockMarkers(content),
metadata: {
size: imageBuffer.length,
timestamp: new Date().toISOString(),
Expand Down
4 changes: 4 additions & 0 deletions src/processors/pdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,20 @@ export async function processPdf(
try {
// Save input to temporary PDF file
let pdfBuffer: Buffer;

if (typeof input === 'string') {
if (input.startsWith('http')) {
const response = await fetch(input);
pdfBuffer = Buffer.from(await response.arrayBuffer());
} else if (input.startsWith('data:application/pdf')) {
pdfBuffer = Buffer.from(input.split(',')[1], 'base64');
} else {
pdfBuffer = await fs.readFile(input);
}
} else {
pdfBuffer = input;
}

await fs.writeFile(tempPdfPath, pdfBuffer);

const pdfDoc = await PDFDocument.load(pdfBuffer);
Expand Down
15 changes: 15 additions & 0 deletions src/utils/string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Removes code block markers from text content.
* Handles both language-specific (```language) and plain (```) code blocks.
* @param text - The text content to process
* @returns The text with code block markers removed
*/
export function removeCodeBlockMarkers(text: string): string {
// Remove ```language and closing ```
text = text.replace(/```[a-zA-Z0-9]*\n([\s\S]*?)```/g, '$1');

// Remove plain ``` wrapping
text = text.replace(/```\n([\s\S]*?)```/g, '$1');

return text.trim();
}
44 changes: 44 additions & 0 deletions tests/ui/app/api/extract/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {Ocra} from 'ocra';

const ocra = new Ocra({
provider: 'openai',
key: process.env.OPENAI_API_KEY!,
});

export async function POST(request: Request) {
try {
if (!process.env.OPENAI_API_KEY) {
return Response.json(
{error: 'OpenAI API key not configured'},
{status: 500},
);
}

const {url, type} = await request.json();

if (!url || !type) {
return Response.json(
{error: 'Missing required fields: url and type'},
{status: 400},
);
}

if (type !== 'image' && type !== 'pdf') {
return Response.json(
{error: 'Invalid type: must be "image" or "pdf"'},
{status: 400},
);
}

const result =
type === 'image' ? await ocra.image(url) : await ocra.pdf(url);

return Response.json({result});
} catch (error) {
console.error('Error processing request:', error);
return Response.json(
{error: 'An error occurred while processing your request'},
{status: 500},
);
}
}
71 changes: 61 additions & 10 deletions tests/ui/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,71 @@
@tailwind components;
@tailwind utilities;

:root {
--background: #ffffff;
--foreground: #171717;
body {
font-family: Arial, Helvetica, sans-serif;
}

@media (prefers-color-scheme: dark) {
@layer base {
:root {
--background: #0a0a0a;
--foreground: #ededed;
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}

body {
color: var(--foreground);
background: var(--background);
font-family: Arial, Helvetica, sans-serif;
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
118 changes: 115 additions & 3 deletions tests/ui/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,119 @@
export default function Home() {
'use client';

import {useState} from 'react';

import FileUpload from '@/components/file-upload';
import {ImageResult, PageResult} from 'ocra';

// Preview component for displaying uploaded file
const Preview = ({url, type}: {url: string; type: 'image' | 'pdf'}) => {
return type === 'image' ? (
<img
src={url}
alt="Preview"
className="w-full h-full object-contain rounded-lg"
/>
) : (
<iframe
src={url}
className="w-full h-full rounded-lg border-0"
title="PDF preview"
/>
);
};

// Content display component
const ContentDisplay = ({
contents,
isLoading,
}: {
contents?: (PageResult | ImageResult)[];
isLoading: boolean;
}) => {
if (isLoading) {
return (
<div className="flex items-center justify-center h-full">
<div className="text-xl text-neutral-500 animate-pulse">
Extracting...
</div>
</div>
);
}

return (
<div className="h-full overflow-y-auto">
<div className="whitespace-pre-wrap space-y-6">
{contents?.map((content, i) => (
<div key={i} className="text-base leading-relaxed">
{content.content}
</div>
))}
</div>
</div>
);
};

// Landing component
const Landing = ({
onUpload,
}: {
onUpload: (url: string, type: 'image' | 'pdf') => void;
}) => {
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
<h1 className="text-4xl tracking-tighter">Ocra</h1>
<div className="flex flex-col items-center justify-center min-h-screen p-4 sm:p-8 md:p-12 lg:p-20">
<div className="max-w-3xl w-full space-y-8">
<div className="space-y-4 text-center">
<h1 className="text-4xl sm:text-5xl font-bold tracking-tighter">
Ocra
</h1>
<p className="text-lg sm:text-xl text-neutral-500 leading-relaxed">
Fast, ultra-accurate text extraction from any image{' '}
<br className="hidden sm:block" />
or PDF, even challenging ones, with structured markdown output.
</p>
</div>
<FileUpload onUpload={onUpload} />
</div>
</div>
);
};

export default function Home() {
const [contents, setContents] = useState<PageResult[] | ImageResult[]>();
const [isLoading, setIsLoading] = useState(false);
const [previewUrl, setPreviewUrl] = useState<string>();
const [fileType, setFileType] = useState<'image' | 'pdf'>();

const handleUpload = async (url: string, type: 'image' | 'pdf') => {
setIsLoading(true);
setPreviewUrl(url);
setFileType(type);

try {
const response = await fetch('/api/extract', {
method: 'POST',
body: JSON.stringify({url, type}),
});

const {result} = (await response.json()) ?? {};
setContents(type === 'image' ? [result] : result);
} finally {
setIsLoading(false);
}
};

if (previewUrl && fileType) {
return (
<div className="flex flex-col lg:flex-row min-h-screen p-4 sm:p-6 md:p-8 lg:p-12 gap-6 lg:gap-8">
<div className="w-full lg:w-1/2 h-[40vh] lg:h-[85vh]">
<Preview url={previewUrl} type={fileType} />
</div>
<div className="w-full lg:w-1/2 h-[40vh] lg:h-[85vh]">
<ContentDisplay contents={contents} isLoading={isLoading} />
</div>
</div>
);
}

return <Landing onUpload={handleUpload} />;
}
20 changes: 20 additions & 0 deletions tests/ui/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
Loading

0 comments on commit 5638fde

Please sign in to comment.