> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firecrawl.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Jev

> Firecrawl と TypeSafe の Jev を組み合わせて、ウェブデータに基づく意思決定を高速かつ構造化された形で行う

Firecrawl を TypeSafe の Jev と統合して、ウェブデータに基づく意思決定を高速かつ構造化された形で行いましょう。

<h2 id="setup">
  セットアップ
</h2>

```bash theme={null}
npm install firecrawl @typesafe-ai/sdk
```

`.env` ファイルを作成します:

```bash theme={null}
FIRECRAWL_API_KEY=your_firecrawl_key
TYPESAFE_API_KEY=your_typesafe_key
```

<h2 id="scrape-decide">
  Scrape + Decide
</h2>

この例では、ページをスクレイピングし、その内容について Jev に「はい/いいえ」で答えられる質問を 1 つ尋ねます。`noul` の question は、答えが「はい」である確率を 0〜1 の値で返します。

```typescript theme={null}
import { Firecrawl } from 'firecrawl';
import { noul, TypeSafeClient } from '@typesafe-ai/sdk';

const firecrawl = new Firecrawl({ apiKey: process.env.FIRECRAWL_API_KEY });
const typesafe = new TypeSafeClient();

const page = await firecrawl.scrape('https://firecrawl.dev', { formats: ['markdown'] });

const { answers } = await typesafe.systemOne({
    state: { page: page.markdown ?? '' },
    questions: {
        hasFreeTier: noul('The product offers a free plan or free credits')
    }
});

console.log('Free tier:', answers.hasFreeTier.noul);
```

<h2 id="search-filter">
  Search + Filter
</h2>

この例では、Web を検索し、各結果のタイトルと説明文をもとに Jev に評価させ、関連性の高いものだけをスクレイピングします。`score` 質問は 0 から順に並べた評価基準 (ルーブリック) を受け取り、期待スコアを返します。このスコアはレベルとレベルの中間の値になる場合もあります。3 段階の場合、スコアが 1.5 以上であれば「Directly answers the query」寄りと判断できます。

```typescript theme={null}
import { Firecrawl, type SearchResultWeb } from 'firecrawl';
import { score, TypeSafeClient } from '@typesafe-ai/sdk';

const firecrawl = new Firecrawl({ apiKey: process.env.FIRECRAWL_API_KEY });
const typesafe = new TypeSafeClient();

const query = 'how to rotate Postgres credentials without downtime';
const search = await firecrawl.search(query, { limit: 10 });
const results = (search.web ?? []) as SearchResultWeb[];

const rated = await Promise.all(results.map(async (result) => {
    const { answers } = await typesafe.systemOne({
        state: { query, title: result.title ?? '', description: result.description ?? '' },
        questions: {
            relevance: score('How well this result answers the query', [
                'Unrelated to the query',
                'Related topic, but does not answer the query',
                'Directly answers the query'
            ])
        }
    });
    return { url: result.url, relevance: answers.relevance.score };
}));

const relevant = rated.filter((r) => r.relevance >= 1.5).map((r) => r.url);

if (relevant.length > 0) {
    const { data: pages } = await firecrawl.batchScrape(relevant, { options: { formats: ['markdown'] } });
    console.log(`Scraped ${pages.length} of ${results.length} results`);
}
```

<h2 id="qualify-leads">
  リードの選別
</h2>

この例では、企業のホームページをスクレイピングし、各結果を CRM に送るか、担当者のレビューに回します。`choice` 形式の質問は、選択されたラベルと `confidence` を返します。そのため、確信度の低い回答は鵜呑みにせず、担当者に確認を任せることができます。

```typescript theme={null}
import { Firecrawl } from 'firecrawl';
import { choice, noul, TypeSafeClient } from '@typesafe-ai/sdk';

const firecrawl = new Firecrawl({ apiKey: process.env.FIRECRAWL_API_KEY });
const typesafe = new TypeSafeClient();

const companies = ['https://ramp.com', 'https://mercury.com', 'https://www.jpmorganchase.com'];
const { data: pages } = await firecrawl.batchScrape(companies, { options: { formats: ['markdown'] } });

const leads = await Promise.all(pages.map(async (page) => {
    const { answers } = await typesafe.systemOne({
        state: { homepage: page.markdown ?? '' },
        questions: {
            isFintech: noul('The company builds financial technology such as payments, banking, or spend management software'),
            stage: choice('How established the company appears to be', {
                startup: 'Early stage, with a small team or a single product',
                growth: 'Several products or a sizable customer base',
                enterprise: 'A large, long-established company'
            })
        }
    });

    const { choice: stage, confidence } = answers.stage;
    const qualified = answers.isFintech.noul > 0.8 && stage !== 'enterprise';
    const route = qualified && confidence >= 0.6 ? 'crm' : 'review';

    return { url: page.metadata?.sourceURL, stage, confidence, route };
}));

console.table(leads);
```

質問の型やオプションの詳細については、[TypeSafe のドキュメント](https://docs.typesafe.ai/)を参照してください。
