Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"plugins": ["@typescript-eslint", "prettier"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
"env": {
"node": true,
"es2022": true
Expand All @@ -16,6 +13,7 @@
"rules": {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
"prettier/prettier": "error"
}
}
}
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist
node_modules
build
coverage
package-lock.json
8 changes: 8 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"endOfLine": "auto"
}
109 changes: 32 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# quotientai

[![npm version](https://img.shields.io/npm/v/quotientai)](https://www.npmjs.com/package/quotientai)

## Overview

`quotientai` is an SDK built to manage artifacts (prompts, datasets), and run evaluations on [Quotient](https://quotientai.co).
`quotientai` is an SDK and CLI for logging data to [Quotient](https://quotientai.co), and running hallucination and document attribution detections for retrieval and search-augmented AI systems.

## Installation

Expand All @@ -13,13 +14,36 @@ npm install quotientai

## Usage

Create an API key on Quotient and set it as an environment variable called `QUOTIENT_API_KEY`. Then check out the examples in the `examples/` directory or see our [docs](https://docs.quotientai.co) for a more comprehensive walkthrough.
Create an API key on [Quotient](https://app.quotientai.co) and set it as an environment variable called `QUOTIENT_API_KEY`. Then follow the examples below or see our [docs](https://docs.quotientai.co) for a more comprehensive walkthrough.

Send your first log and detect hallucinations. Run the code below and see your Logs and Detections on your [Quotient Dashboard](https://app.quotientai.co/dashboard).

The examples directory contains:
- `example_evaluate.ts` - Running an evaluation against a dataset
- `example_logs.ts` - Logging with hallucination detection
```typescript
import { QuotientAI } from 'quotientai';

const quotient = new QuotientAI(apiKey?: string);

// initialize the logger
const quotientLogger = quotient.logger.init({
appName: 'my-app',
environment: 'dev',
sampleRate: 1.0,
hallucinationDetection: true,
hallucination_detection_sample_rate: 1.0,
});

// create a log
const logId = await quotientLogger.log({
userQuery: 'How do I cook a goose?',
modelOutput: 'The capital of France is Paris',
documents: ['Here is an excellent goose recipe...'],
});

// optionally, you can poll for detection results for further actions
const detectionResults = await quotientLogger.pollForDetections(logId);
```

### QuotientAI
### QuotientAI Client

The main client class that provides access to all QuotientAI resources.

Expand All @@ -31,75 +55,6 @@ new QuotientAI(apiKey?: string)

- `apiKey`: Optional API key. If not provided, will attempt to read from `QUOTIENT_API_KEY` environment variable.

#### Methods

##### evaluate

```typescript
evaluate(params: {
prompt: Prompt;
dataset: Dataset;
model: Model;
parameters: Record<string, any>;
metrics: string[];
}): Promise<Run>
```

Evaluates a model on a dataset using a prompt.

### QuotientLogger

A logger interface for tracking model interactions.

#### Methods

##### init

```typescript
init(config: {
app_name: string;
environment: string;
tags?: Record<string, any>;
sample_rate?: number;
hallucination_detection?: boolean;
inconsistency_detection?: boolean;
hallucination_detection_sample_rate?: number;
}): QuotientLogger
```

Configures the logger with the provided parameters.

##### log

```typescript
log(params: {
user_query: string;
model_output: string;
documents?: string[];
message_history?: Array<Record<string, any>>;
instructions?: string[];
tags?: Record<string, any>;
hallucination_detection?: boolean;
inconsistency_detection?: boolean;
}): Promise<void>
```

Logs a model interaction.

## Error Handling

The client uses a custom `QuotientAIError` class for error handling:

```typescript
try {
await client.evaluate({ ... });
} catch (error) {
if (error instanceof QuotientAIError) {
console.error(`Error ${error.status}: ${error.message}`);
}
}
```

## License
## Docs

MIT
For comprehensive documentation, please visit our [docs](https://docs.quotientai.co).
67 changes: 0 additions & 67 deletions examples/example_evaluate.ts

This file was deleted.

85 changes: 45 additions & 40 deletions examples/example_logs.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,54 @@
import { QuotientAI } from '../quotientai';
import { QuotientAI } from 'quotientai';

async function main() {
const quotient = new QuotientAI();
console.log("QuotientAI client initialized")
const quotient = new QuotientAI();
console.log('QuotientAI client initialized');

// configure the logger
const quotient_logger = quotient.logger.init({
app_name: "my-app",
environment: "dev",
sample_rate: 1.0,
tags: { model: "gpt-4o", feature: "customer-support" },
hallucination_detection: true,
})
// configure the logger
const quotientLogger = quotient.logger.init({
appName: 'my-app',
environment: 'dev',
sampleRate: 1.0,
tags: { model: 'gpt-4o', feature: 'customer-support' },
hallucinationDetection: true,
hallucinationDetectionSampleRate: 1.0,
});

console.log("Logger initialized")
console.log('Logger initialized');

// mock retrieved documents
const retrieved_documents = [
"Sample document 1",
{"page_content": "Sample document 2", "metadata": {"source": "website.com"}},
{"page_content": "Sample document 3"}
]
// mock retrieved documents
const retrievedDocuments = [
'Sample document 1',
{ pageContent: 'Sample document 2', metadata: { source: 'website.com' } },
{ pageContent: 'Sample document 3' },
];

console.log("Preparing to log with quotient_logger")
try {
const response = await quotient_logger.log({
user_query: "How do I cook a goose?",
model_output: "The capital of France is Paris",
documents: retrieved_documents,
message_history: [
{"role": "system", "content": "You are an expert on geography."},
{"role": "user", "content": "What is the capital of France?"},
{"role": "assistant", "content": "The capital of France is Paris"},
],
instructions: [
"You are a helpful assistant that answers questions about the world.",
"Answer the question in a concise manner. If you are not sure, say 'I don't know'.",
],
hallucination_detection: true,
inconsistency_detection: true,
});
console.log(response.message)
} catch (error) {
console.error(error)
}
console.log('Preparing to log with quotient_logger');
try {
const logId = await quotientLogger.log({
userQuery: 'How do I cook a test?',
modelOutput: 'The capital of France is Paris',
documents: retrievedDocuments,
messageHistory: [
{ role: 'system', content: 'You are an expert on geography.' },
{ role: 'user', content: 'What is the capital of France?' },
{ role: 'assistant', content: 'The capital of France is Paris' },
],
instructions: [
'You are a helpful assistant that answers questions about the world.',
"Answer the question in a concise manner. If you are not sure, say 'I don't know'.",
],
hallucinationDetection: true,
inconsistencyDetection: true,
});
console.log('pollForDetections with logId: ', logId);

// poll for the detection results
const detectionResults = await quotientLogger.pollForDetections(logId);
console.log('detectionResults', detectionResults);
} catch (error) {
console.error(error);
}
}

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