Monday, June 15, 2009

Call Center Voice Recording

Ever wonder how you do audit in a large call center?

Here's the basics:

First, most modern call centers are using Voip. It makes it easy to setup, and even better
makes it easy to monitor. Also call-centers tend to be in places like india, or phillipines
serving the US or Europe markets. So VoIp plays a role in getting the traffic from one
country to another.

There are several pieces to this puzzle:

First, you need to capture the raw data:
So to do that, we need a "tee" off the ethernet channel that is connecting to the VoIP gateway.
This will allow us to see all the VoIP IP Traffic that is going back and forth.

It's sometimes called 'port mirroring', 'port monitoring', 'Roving Analysis' (3Com), or 'Switched Port Analyzer' or 'SPAN' (Cisco).

http://wiki.wireshark.org/CaptureSetup/Ethernet
http://www.cisco.com/en/US/products/hw/switches/ps708/products_tech_note09186a008015c612.shtml#descp

Now that we have traffic, a good way to "capture" the voice is Oreka
http://oreka.sourceforge.net/

Oreka lets you capture the packets, and convert them to audio files. It actually consists
of three parts.

- OrkAudio: This is the workhorse that processes the calls and does the actual recording
- OrkWeb: This is the XML based Web U/I to access and manage the system
- OrkTrack: This is the master database (MySQL) that records the call records, metadata, etc.

Oreka lets you get a basic system up quickly.

The next issue, is setting up a system of audit, and to connect and understand the calls into transactions,
customers, call-agents, and supervisors.

For a good GUI on top, I'd switch to a Rails App. This lets me do several things:

1. I can tie agents to calls
2. I can allow agents access to review there own calls
3. I can allow supervisors to view/listen to calls for agents reporting to them
4. I can let audit department audit calls as appriate.
5. Ease of interfacing existing call center apps togeather

Now that we have a phase 1, and phase 2 completed, lets add a phase 3.
One of the emerging technologies is Speach to text.
Using the latest SDK's from Dragon Speaking, we can get very high 99% plus on our agents,
and not bad recognition on our clients/customers calling in. This will allow audit to search
for key words, such as scam, theft, etc that would audit to be better aware of things going
on.

The idea way of implementing the whole system is break things down to separate VM's in a VmWare system.

1. OakCapture - 1 VM per major Trunk (One Per - Multiple DS1, One DS3)
2. OakGui - 1 VM For system - For reference/admin control only
3. Database - In a call center, a Oracle or DB2 may be better suited, depending on the company
4. VoiceCenterManager - A Rails Server using Nginx/Passenger that provides interfaces to agents, supervisors, audit,
and managers. Number of VM determine by staff size
5. Recognition Engines - A separate VM that is running a Ruby Agent tied to a Dragon Speaking SDK allowing speaker dependent and Speaker Independent Speech to text conversion. This allow for the creation of easily searchable as well
as readable results of the calls in text form. Using a rack of blades, and VmWare we can realtime convert all calls to text
index them, and make them searchable.

Note that each call center is different but leveraging Rails, and Ruby a AGILE and fast solution can be combined that
gives the best in Audit and accountability.

Thursday, June 11, 2009

Ghosting NTFS/Windows using Knoxppix

I have a USB 1 Gig stick that is on my key ring.
Its really handy, as I have a complete copy of Knoxppix.
Knoxpix is a Linux Distribution designed to boot and run
from CDROM or DVD. It can also run from a handy USB stick.
With the right options it can also in "RAM", which is handly if you want to
run a few parallel operations, and only need one usb stick.

While you can use clonezilla, if you want something more packaged,
but in a shop that is windows centric, ghosting to a windows server
may make more sense.

Boot your usb stick, then at the bash shell, mount your server:

mount -t cifs //server-name/share-name /mnt/cifs -o username=shareuser,password=sharepassword,domain=nixcraft

On the share, I usually will the have my ntfscloning scripts

On a dell machine, there is really only one partition that has "data",

So to the "dobackup" script is very trival.
This takes the OS partition, in most of the environments I was working in this
would have been /dev/sda2 and uses ntfsclone, which takes only the in-use
sectors, compresses them, and put them in a file on the server.

dobackup script

echo backup $1 to $2
mkdir $2
ntfsclone -s -o - /dev/$1 | gzip > $2/$1.ntfsclone.gzip


The reverse, to restore is:

dorestore script

echo restore $1 to $2
cd $1
cat $2.ntfsclone.gzip | gunzip - | ntfsclone --restore-image --overwrite /dev/$2 -


The only other madatory item is the partition table:

doptablebackup script

echo partion backup $1 to $2
sfdisk -d /dev/$1 > $2/ptable.doc
dd if=/dev/$1 bs=512 count=1 of=$2/ptable.sector


doptablerestore script

echo partion restore $1 to $2
dd of=/dev/$2 bs=512 count=1 if=$1/ptable.sector

Sunday, June 07, 2009

Dynamically Generating Javascript using Parameters

I love re-using code, and really believe in DRY.
In doing ActiveJquery, I want my grids to be very re-usable.
For one, I need to use multiple grid/sub-grids to handle Rails
relationships, second I need to be able to have multiple grids
in one page. And want to do all of this with the least amount of code.

In ActiveJquery, the Grid code, is generated on the fly. While it looks like a normal
call, its actually hitting controller code tucked inside the plugin.

So when we request the javascript code for a particular controller, the ActiveJquery
code generates the appropriate javascript on the fly.

In doing, the sub-table, I need to have parameters passed in, so I rely on standard
Rails Semantics when handling HTML.

<script src="location.js?subof=Company&div=Company_Location" type="text/javascript"></script>


This technique lets me generate customized javascript on the fly, making the generator re-usable, and
the grid re-usable any number of times in the same application.

Saturday, June 06, 2009

Finding ActiveRecord Associations

Im working away on ActiveJquery, and the next thing on the list, is to add support for relationships. This gets to be really interesting, because your Inside the box, in a plugin, and you need to know what associations the user has
defined.

I was scanning the documentation, and looking around for the api to find the information.

After searching for a while, I discovered railway, a gem for rails that does diagraming of rails models using dot. So grab the gem, and look thru the source.

So the key to finding associations is:

@associations = table.reflect_on_all_associations

This results in:
@associations=
[#ActiveRecord::Reflection::AssociationReflection:0x26305cc
@active_record=
Company(id: integer, name: string, location_id: integer, created_at: datetime, updated_at: datetime),
@macro=:has_many,
@name=:user,
@options={:extend=>[]}>,
#<ActiveRecord::Reflection::AssociationReflection:0x262faa0
@active_record=
Company(id: integer, name: string, location_id: integer, created_at: datetime, updated_at: datetime),
@macro=:has_many,
@name=:location,
@options={:extend=>[]}>,
#<ActiveRecord::Reflection::AssociationReflection:0x262f0c8
@active_record=
Company(id: integer, name: string, location_id: integer, created_at: datetime, updated_at: datetime),
@macro=:has_many,
@name=:division,
@options={:extend=>[]}>],



From my models:
class Company < ActiveRecord::Base
has_many :user
has_many :location
has_many :division

end
class Department < ActiveRecord::Base
belongs_to :division
end
class Division < ActiveRecord::Base
belongs_to :company
end
class Location < ActiveRecord::Base
end
class User < ActiveRecord::Base
end