# Action Table - Document

## 1. Introduction

This tutorial will guide you through using the JamAI Base TypeScript SDK to create a simple news summarization system.

### What We'll Build

Get a news document and let AI tell you the main message!

In this tutorial, we'll create a news summarization system that:

* Takes a news document as input. The supported formats include: .csv, .tsv, .txt, .md, .doc, .docx, .pdf, .ppt, .pptx, .xls, .xlsx, .xml, .html, .json, .jsonl.
* Upload the document to JamAI Base action table.
* Obtain the key information like:
  * Summary
  * Tag

### Prerequisites

Before starting, you'll need:

* Node.js 16.x or higher installed
* Project ID and Personal Access Token (PAT)

## 2. Installation and Setup

### Installing the TypeScript SDK

```bash
npm install jamaibase
```

### Basic Configuration

Get your Personal Access Token (PAT) here:

Get your Project ID here:

```typescript
import JamAI from "jamaibase";

const PROJECT_ID = "your_project_id";
const PAT = "your_PAT";

const client = new JamAI({
  projectId: PROJECT_ID,
  token: PAT,
});
```

{% hint style="info" %}
You can use a .env file to manage your PROJECT\_ID and PAT.
{% endhint %}

## 3. Creating Your Action Table

For simplicity, you can set up your action table in the JamAI Base platform:

{% stepper %}
{% step %}

### Create the action table

* Navigate to your JamAI Base action table tab.
* Create a new action table named "news\_summarization".
  {% endstep %}

{% step %}

### Add columns

Create the following columns:

| Name          | Column Type | Data Type |
| ------------- | ----------- | --------- |
| document      | Input       | Document  |
| summary       | LLM Output  | Text      |
| tag           | LLM Output  | Text      |
| {% endstep %} |             |           |

{% step %}

### Update prompts for LLM Output columns

Update the Prompt for the LLM Output columns as follows:

| Column name      | Prompt                                                                                                                                                                                                                                                                                                                                                                                           |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| summary          | Table name: "news\_summarization"\n\ndocument: ${document}\n\nSummarize the article in not more than three sentences and not more than 50 words.\n\nProvide the summary in the number form.\n\nBe factual and do not hallucinate. Remember to act as a cell in a spreadsheet and provide concise, relevant information without explanations unless specifically requested.                       |
| tag              | Table name: "news\_summarization"\n\ndocument: ${document}\n\nProvide at most three tags that well represent the document. Each tag should not have more than three words.\n\nProvide the tag in the number form.\n\nBe factual and do not hallucinate. Remember to act as a cell in a spreadsheet and provide concise, relevant information without explanations unless specifically requested. |
| {% endstep %}    |                                                                                                                                                                                                                                                                                                                                                                                                  |
| {% endstepper %} |                                                                                                                                                                                                                                                                                                                                                                                                  |

## 4. Basic Implementation

### 4.1 Simple Document Processor

```typescript
async function processSingleNews(documentPath: string) {
  // Upload document file
  const fileResponse = await client.file.uploadFile({
    file_path: documentPath,
  });

  // Process in action table
  const response = await client.table.addRow({
    table_type: "action",
    table_id: "news_summarization",
    data: [{ document: fileResponse.uri }],
    concurrent: false,
  });

  // Extract results
  return {
    summary: response.rows[0]?.columns["summary"]?.choices[0]?.message?.content,
    tag: response.rows[0]?.columns["tag"]?.choices[0]?.message?.content,
  };
}
```

### 4.2 Complete Implementation with Error Handling

```typescript
import JamAI from "jamaibase";
import * as fs from "fs";
import * as path from "path";

class DocumentProcessor {
  private client: JamAI;

  constructor(projectId: string, pat: string) {
    this.client = new JamAI({
      projectId: projectId,
      token: pat,
    });
  }

  validateDocument(documentPath: string): boolean {
    // Validate if file exists and has correct extension
    if (!fs.existsSync(documentPath)) {
      throw new Error(`Document not found: ${documentPath}`);
    }

    const validExtensions = [
      ".csv",
      ".tsv",
      ".txt",
      ".md",
      ".doc",
      ".docx",
      ".pdf",
      ".ppt",
      ".pptx",
      ".xls",
      ".xlsx",
      ".xml",
      ".html",
      ".json",
      ".jsonl",
    ];

    const fileExt = path.extname(documentPath).toLowerCase();
    if (!validExtensions.includes(fileExt)) {
      throw new Error(
        `Unsupported file format. Use: ${validExtensions.join(", ")}`
      );
    }

    return true;
  }

  async processDocument(
    documentPath: string
  ): Promise<{ summary: string; tag: string } | null> {
    try {
      // Validate document
      this.validateDocument(documentPath);

      // Upload file
      console.log("Uploading document...");
      const fileResponse = await this.client.file.uploadFile({
        file_path: documentPath,
      });
      console.log(`Upload successful: ${fileResponse.uri}`);

      // Process in action table
      console.log("Processing document...");
      const response = await this.client.table.addRow({
        table_type: "action",
        table_id: "news_summarization",
        data: [{ document: fileResponse.uri }],
        concurrent: false,
      });

      // Extract and return results
      const results = {
        summary: String(
          response.rows[0]?.columns["summary"]?.choices[0]?.message?.content ??
            ""
        ),
        tag: String(
          response.rows[0]?.columns["tag"]?.choices[0]?.message?.content ?? ""
        ),
      };
      console.log("Processing complete!");
      return results;
    } catch (error) {
      console.error(`Error processing document: ${error}`);
      return null;
    }
  }
}
```

## 5. Usage Examples

### 5.1 Basic Usage

```typescript
// Initialize processor
const processor = new DocumentProcessor(PROJECT_ID, PAT);

// Process single document
const result = await processor.processDocument("path/to/news.txt");

if (result) {
  console.log(`Summary: ${result.summary}`);
  console.log(`Tag: ${result.tag}`);
}
```

### 5.2 Batch Processing

```typescript
async function processDocumentBatch(documentFolder: string) {
  const processor = new DocumentProcessor(PROJECT_ID, PAT);
  const results = [];

  const files = fs.readdirSync(documentFolder);

  for (const filename of files) {
    // Check if file has a supported document extension
    const validExtensions = [
      ".csv",
      ".tsv",
      ".txt",
      ".md",
      ".doc",
      ".docx",
      ".pdf",
      ".ppt",
      ".pptx",
      ".xls",
      ".xlsx",
      ".xml",
      ".html",
      ".json",
      ".jsonl",
    ];

    if (validExtensions.some((ext) => filename.toLowerCase().endsWith(ext))) {
      const documentPath = path.join(documentFolder, filename);
      const result = await processor.processDocument(documentPath);
      if (result) {
        results.push({
          filename: filename,
          ...result,
        });
      }
    }
  }

  return results;
}

// Usage
const results = await processDocumentBatch("path/to/documents/folder");
for (const result of results) {
  console.log(`File: ${result.filename}`);
  console.log(`Summary: ${result.summary}`);
  console.log(`Tag: ${result.tag}`);
  console.log("---");
}
```

## 6. Best Practices

* Error Handling
  * Always validate input files
  * Handle network errors gracefully
* Performance
  * Reuse the client instance
  * Consider batch processing for multiple files
  * Implement rate limiting for large batches
* Security
  * Use environment variables for credentials

## Complete Standalone Example

```typescript
import JamAI from "jamaibase";
import * as fs from "fs";
import * as path from "path";

class DocumentProcessor {
  private client: JamAI;

  constructor(projectId: string, pat: string) {
    this.client = new JamAI({
      projectId: projectId,
      token: pat,
    });
  }

  validateDocument(documentPath: string): boolean {
    if (!fs.existsSync(documentPath)) {
      throw new Error(`Document not found: ${documentPath}`);
    }

    const validExtensions = [
      ".csv",
      ".tsv",
      ".txt",
      ".md",
      ".doc",
      ".docx",
      ".pdf",
      ".ppt",
      ".pptx",
      ".xls",
      ".xlsx",
      ".xml",
      ".html",
      ".json",
      ".jsonl",
    ];

    const fileExt = path.extname(documentPath).toLowerCase();
    if (!validExtensions.includes(fileExt)) {
      throw new Error(
        `Unsupported file format. Use: ${validExtensions.join(", ")}`
      );
    }

    return true;
  }

  async processDocument(
    documentPath: string
  ): Promise<{ summary: string; tag: string } | null> {
    try {
      this.validateDocument(documentPath);

      console.log(`Processing document: ${documentPath}`);
      console.log("Uploading document...");
      const fileResponse = await this.client.file.uploadFile({
        file_path: documentPath,
      });
      console.log("Upload successful!");

      console.log("Extracting information...");
      const response = await this.client.table.addRow({
        table_type: "action",
        table_id: "news_summarization",
        data: [{ document: fileResponse.uri }],
        concurrent: false,
      });

      const results = {
        summary: String(
          response.rows[0]?.columns["summary"]?.choices[0]?.message?.content ??
            ""
        ),
        tag: String(
          response.rows[0]?.columns["tag"]?.choices[0]?.message?.content ?? ""
        ),
      };
      return results;
    } catch (error) {
      console.error(`Error: ${error}`);
      return null;
    }
  }
}

async function processFolder(
  folderPath: string,
  processor: DocumentProcessor
): Promise<void> {
  // Process all documents in a folder
  if (!fs.existsSync(folderPath)) {
    console.log(`Folder not found: ${folderPath}`);
    return;
  }

  const results = [];
  const files = fs.readdirSync(folderPath);

  for (const filename of files) {
    const validExtensions = [
      ".csv",
      ".tsv",
      ".txt",
      ".md",
      ".doc",
      ".docx",
      ".pdf",
      ".ppt",
      ".pptx",
      ".xls",
      ".xlsx",
      ".xml",
      ".html",
      ".json",
      ".jsonl",
    ];

    if (validExtensions.some((ext) => filename.toLowerCase().endsWith(ext))) {
      const documentPath = path.join(folderPath, filename);
      const result = await processor.processDocument(documentPath);
      if (result) {
        results.push({
          filename: filename,
          ...result,
        });
      }
    }
  }

  console.log("\n=== Processing Results ===");
  for (const result of results) {
    console.log(`\nFile: ${result.filename}`);
    console.log(`Summary: ${result.summary}`);
    console.log(`Tag: ${result.tag}`);
  }
}

// Main execution
async function main() {
  // Get credentials from environment variables
  const PROJECT_ID = process.env.JAMAI_PROJECT_ID || "your_project_id";
  const PAT = process.env.JAMAI_API_KEY || "your_PAT";

  const processor = new DocumentProcessor(PROJECT_ID, PAT);

  // Process a single document
  const singleResult = await processor.processDocument("path/to/news.txt");
  if (singleResult) {
    console.log("\nSingle Document Result:");
    console.log(`Summary: ${singleResult.summary}`);
    console.log(`Tag: ${singleResult.tag}`);
  }

  // Or process a folder of documents
  // await processFolder("path/to/documents/folder", processor);
}

main().catch(console.error);
```

## Running the Example

1. Save the code as `document_processor.ts`
2. Create a `.env` file:

   ```
   JAMAI_PROJECT_ID=your_project_id
   JAMAI_API_KEY=your_PAT
   ```
3. Run with:

   ```bash
   npm install dotenv
   ts-node document_processor.ts
   ```

Or compile and run:

```bash
tsc document_processor.ts
node document_processor.js
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.jamaibase.com/developer-reference/typescript-sdk-documentation/quick-start-action-table/action-table-document.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
